linked-list-typed 2.0.5 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/dist/data-structures/base/iterable-element-base.d.ts +186 -83
- package/dist/data-structures/base/iterable-element-base.js +149 -107
- package/dist/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/data-structures/base/linear-base.d.ts +250 -192
- package/dist/data-structures/base/linear-base.js +137 -274
- package/dist/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/data-structures/binary-tree/avl-tree-counter.js +171 -205
- package/dist/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
- package/dist/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/data-structures/binary-tree/avl-tree.js +208 -195
- package/dist/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/data-structures/binary-tree/binary-tree.js +602 -873
- package/dist/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/data-structures/binary-tree/bst.js +505 -481
- package/dist/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/data-structures/binary-tree/red-black-tree.js +114 -209
- package/dist/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/data-structures/binary-tree/tree-counter.js +172 -203
- package/dist/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/data-structures/binary-tree/tree-multi-map.js +105 -85
- package/dist/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/data-structures/graph/abstract-graph.js +267 -237
- package/dist/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/data-structures/graph/directed-graph.js +146 -233
- package/dist/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/data-structures/graph/map-graph.js +56 -59
- package/dist/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/data-structures/graph/undirected-graph.js +129 -149
- package/dist/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/data-structures/hash/hash-map.js +270 -457
- package/dist/data-structures/heap/heap.d.ts +214 -289
- package/dist/data-structures/heap/heap.js +340 -349
- package/dist/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/data-structures/heap/max-heap.js +11 -66
- package/dist/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/data-structures/heap/min-heap.js +11 -66
- package/dist/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/data-structures/linked-list/doubly-linked-list.js +368 -494
- package/dist/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/data-structures/linked-list/singly-linked-list.js +447 -466
- package/dist/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/data-structures/queue/deque.d.ts +227 -254
- package/dist/data-structures/queue/deque.js +309 -348
- package/dist/data-structures/queue/queue.d.ts +180 -201
- package/dist/data-structures/queue/queue.js +265 -248
- package/dist/data-structures/stack/stack.d.ts +124 -102
- package/dist/data-structures/stack/stack.js +181 -125
- package/dist/data-structures/trie/trie.d.ts +164 -165
- package/dist/data-structures/trie/trie.js +189 -172
- package/dist/interfaces/binary-tree.d.ts +56 -6
- package/dist/interfaces/graph.d.ts +16 -0
- package/dist/types/data-structures/base/base.d.ts +1 -1
- package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/types/utils/utils.d.ts +1 -0
- package/dist/utils/utils.d.ts +1 -1
- package/dist/utils/utils.js +2 -1
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +238 -115
- package/src/data-structures/base/iterable-entry-base.ts +96 -120
- package/src/data-structures/base/linear-base.ts +271 -277
- package/src/data-structures/binary-tree/avl-tree-counter.ts +196 -217
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +188 -102
- package/src/data-structures/binary-tree/avl-tree.ts +237 -206
- package/src/data-structures/binary-tree/binary-tree.ts +665 -896
- package/src/data-structures/binary-tree/bst.ts +565 -572
- package/src/data-structures/binary-tree/red-black-tree.ts +157 -223
- package/src/data-structures/binary-tree/tree-counter.ts +195 -219
- package/src/data-structures/binary-tree/tree-multi-map.ts +127 -98
- package/src/data-structures/graph/abstract-graph.ts +339 -264
- package/src/data-structures/graph/directed-graph.ts +146 -236
- package/src/data-structures/graph/map-graph.ts +63 -60
- package/src/data-structures/graph/undirected-graph.ts +129 -152
- package/src/data-structures/hash/hash-map.ts +274 -496
- package/src/data-structures/heap/heap.ts +389 -402
- package/src/data-structures/heap/max-heap.ts +12 -76
- package/src/data-structures/heap/min-heap.ts +13 -76
- package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
- package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
- package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
- package/src/data-structures/priority-queue/priority-queue.ts +3 -92
- package/src/data-structures/queue/deque.ts +381 -357
- package/src/data-structures/queue/queue.ts +310 -264
- package/src/data-structures/stack/stack.ts +217 -131
- package/src/data-structures/trie/trie.ts +240 -175
- package/src/interfaces/binary-tree.ts +240 -6
- package/src/interfaces/graph.ts +37 -0
- package/src/types/data-structures/base/base.ts +5 -5
- package/src/types/data-structures/graph/abstract-graph.ts +5 -0
- package/src/types/utils/utils.ts +2 -0
- package/src/utils/utils.ts +9 -14
|
@@ -5,15 +5,23 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
import type { DoublyLinkedListOptions, ElementCallback, LinearBaseOptions } from '../../types';
|
|
9
10
|
import { LinearLinkedBase, LinkedListNode } from '../base/linear-base';
|
|
10
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Node of a doubly linked list; stores value and prev/next links.
|
|
14
|
+
* @remarks Time O(1), Space O(1)
|
|
15
|
+
* @template E
|
|
16
|
+
*/
|
|
11
17
|
export class DoublyLinkedListNode<E = any> extends LinkedListNode<E> {
|
|
12
18
|
/**
|
|
13
|
-
*
|
|
14
|
-
* @
|
|
15
|
-
*
|
|
19
|
+
* Create a node.
|
|
20
|
+
* @remarks Time O(1), Space O(1)
|
|
21
|
+
* @param value - Element value to store.
|
|
22
|
+
* @returns New node instance.
|
|
16
23
|
*/
|
|
24
|
+
|
|
17
25
|
constructor(value: E) {
|
|
18
26
|
super(value);
|
|
19
27
|
this._value = value;
|
|
@@ -23,26 +31,56 @@ export class DoublyLinkedListNode<E = any> extends LinkedListNode<E> {
|
|
|
23
31
|
|
|
24
32
|
protected override _next: DoublyLinkedListNode<E> | undefined;
|
|
25
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Get the next node link.
|
|
36
|
+
* @remarks Time O(1), Space O(1)
|
|
37
|
+
* @returns Next node or undefined.
|
|
38
|
+
*/
|
|
39
|
+
|
|
26
40
|
override get next(): DoublyLinkedListNode<E> | undefined {
|
|
27
41
|
return this._next;
|
|
28
42
|
}
|
|
29
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Set the next node link.
|
|
46
|
+
* @remarks Time O(1), Space O(1)
|
|
47
|
+
* @param value - Next node or undefined.
|
|
48
|
+
* @returns void
|
|
49
|
+
*/
|
|
50
|
+
|
|
30
51
|
override set next(value: DoublyLinkedListNode<E> | undefined) {
|
|
31
52
|
this._next = value;
|
|
32
53
|
}
|
|
33
54
|
|
|
34
55
|
protected _prev: DoublyLinkedListNode<E> | undefined;
|
|
35
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Get the previous node link.
|
|
59
|
+
* @remarks Time O(1), Space O(1)
|
|
60
|
+
* @returns Previous node or undefined.
|
|
61
|
+
*/
|
|
62
|
+
|
|
36
63
|
get prev(): DoublyLinkedListNode<E> | undefined {
|
|
37
64
|
return this._prev;
|
|
38
65
|
}
|
|
39
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Set the previous node link.
|
|
69
|
+
* @remarks Time O(1), Space O(1)
|
|
70
|
+
* @param value - Previous node or undefined.
|
|
71
|
+
* @returns void
|
|
72
|
+
*/
|
|
73
|
+
|
|
40
74
|
set prev(value: DoublyLinkedListNode<E> | undefined) {
|
|
41
75
|
this._prev = value;
|
|
42
76
|
}
|
|
43
77
|
}
|
|
44
78
|
|
|
45
79
|
/**
|
|
80
|
+
* Doubly linked list with O(1) push/pop/unshift/shift and linear scans.
|
|
81
|
+
* @remarks Time O(1), Space O(1)
|
|
82
|
+
* @template E
|
|
83
|
+
* @template R
|
|
46
84
|
* 1. Node Structure: Each node contains three parts: a data field, a pointer (or reference) to the previous node, and a pointer to the next node. This structure allows traversal of the linked list in both directions.
|
|
47
85
|
* 2. Bidirectional Traversal: Unlike singly linked lists, doubly linked lists can be easily traversed forwards or backwards. This makes insertions and deletions in the list more flexible and efficient.
|
|
48
86
|
* 3. No Centralized Index: Unlike arrays, elements in a linked list are not stored contiguously, so there is no centralized index. Accessing elements in a linked list typically requires traversing from the head or tail node.
|
|
@@ -217,6 +255,16 @@ export class DoublyLinkedListNode<E = any> extends LinkedListNode<E> {
|
|
|
217
255
|
* this.map = new Map<K, DoublyLinkedListNode<CacheEntry<K, V>>>();
|
|
218
256
|
* }
|
|
219
257
|
*
|
|
258
|
+
* // Get the current cache length
|
|
259
|
+
* get length(): number {
|
|
260
|
+
* return this.list.length;
|
|
261
|
+
* }
|
|
262
|
+
*
|
|
263
|
+
* // Check if it is empty
|
|
264
|
+
* get isEmpty(): boolean {
|
|
265
|
+
* return this.list.isEmpty();
|
|
266
|
+
* }
|
|
267
|
+
*
|
|
220
268
|
* // Get cached value
|
|
221
269
|
* get(key: K): V | undefined {
|
|
222
270
|
* const node = this.map.get(key);
|
|
@@ -262,12 +310,6 @@ export class DoublyLinkedListNode<E = any> extends LinkedListNode<E> {
|
|
|
262
310
|
* }
|
|
263
311
|
* }
|
|
264
312
|
*
|
|
265
|
-
* // Move the node to the head of the linked list
|
|
266
|
-
* private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {
|
|
267
|
-
* this.list.delete(node);
|
|
268
|
-
* this.list.unshift(node.value);
|
|
269
|
-
* }
|
|
270
|
-
*
|
|
271
313
|
* // Delete specific key
|
|
272
314
|
* delete(key: K): boolean {
|
|
273
315
|
* const node = this.map.get(key);
|
|
@@ -287,14 +329,10 @@ export class DoublyLinkedListNode<E = any> extends LinkedListNode<E> {
|
|
|
287
329
|
* this.map.clear();
|
|
288
330
|
* }
|
|
289
331
|
*
|
|
290
|
-
* //
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
* // Check if it is empty
|
|
296
|
-
* get isEmpty(): boolean {
|
|
297
|
-
* return this.list.isEmpty();
|
|
332
|
+
* // Move the node to the head of the linked list
|
|
333
|
+
* private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {
|
|
334
|
+
* this.list.delete(node);
|
|
335
|
+
* this.list.unshift(node.value);
|
|
298
336
|
* }
|
|
299
337
|
* }
|
|
300
338
|
*
|
|
@@ -476,16 +514,16 @@ export class DoublyLinkedListNode<E = any> extends LinkedListNode<E> {
|
|
|
476
514
|
* console.log(scheduler.listProcesses()); // []
|
|
477
515
|
*/
|
|
478
516
|
export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, DoublyLinkedListNode<E>> {
|
|
517
|
+
protected _equals: (a: E, b: E) => boolean = Object.is as unknown as (a: E, b: E) => boolean;
|
|
518
|
+
|
|
479
519
|
/**
|
|
480
|
-
*
|
|
481
|
-
* @
|
|
482
|
-
*
|
|
483
|
-
*
|
|
484
|
-
*
|
|
485
|
-
* @param [options] - The `options` parameter in the constructor is of type
|
|
486
|
-
* `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional
|
|
487
|
-
* configuration options to customize the behavior of the DoublyLinkedList.
|
|
520
|
+
* Create a DoublyLinkedList and optionally bulk-insert elements.
|
|
521
|
+
* @remarks Time O(N), Space O(N)
|
|
522
|
+
* @param [elements] - Iterable of elements or nodes (or raw records if toElementFn is provided).
|
|
523
|
+
* @param [options] - Options such as maxLen and toElementFn.
|
|
524
|
+
* @returns New DoublyLinkedList instance.
|
|
488
525
|
*/
|
|
526
|
+
|
|
489
527
|
constructor(
|
|
490
528
|
elements: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>> = [],
|
|
491
529
|
options?: DoublyLinkedListOptions<E, R>
|
|
@@ -495,9 +533,8 @@ export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, D
|
|
|
495
533
|
this._tail = undefined;
|
|
496
534
|
this._length = 0;
|
|
497
535
|
|
|
498
|
-
if (options) {
|
|
499
|
-
|
|
500
|
-
if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;
|
|
536
|
+
if (options?.maxLen && Number.isInteger(options.maxLen) && options.maxLen > 0) {
|
|
537
|
+
this._maxLen = options.maxLen;
|
|
501
538
|
}
|
|
502
539
|
|
|
503
540
|
this.pushMany(elements);
|
|
@@ -505,71 +542,87 @@ export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, D
|
|
|
505
542
|
|
|
506
543
|
protected _head: DoublyLinkedListNode<E> | undefined;
|
|
507
544
|
|
|
545
|
+
/**
|
|
546
|
+
* Get the head node.
|
|
547
|
+
* @remarks Time O(1), Space O(1)
|
|
548
|
+
* @returns Head node or undefined.
|
|
549
|
+
*/
|
|
550
|
+
|
|
508
551
|
get head(): DoublyLinkedListNode<E> | undefined {
|
|
509
552
|
return this._head;
|
|
510
553
|
}
|
|
511
554
|
|
|
512
555
|
protected _tail: DoublyLinkedListNode<E> | undefined;
|
|
513
556
|
|
|
557
|
+
/**
|
|
558
|
+
* Get the tail node.
|
|
559
|
+
* @remarks Time O(1), Space O(1)
|
|
560
|
+
* @returns Tail node or undefined.
|
|
561
|
+
*/
|
|
562
|
+
|
|
514
563
|
get tail(): DoublyLinkedListNode<E> | undefined {
|
|
515
564
|
return this._tail;
|
|
516
565
|
}
|
|
517
566
|
|
|
518
|
-
protected _length
|
|
567
|
+
protected _length = 0;
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Get the number of elements.
|
|
571
|
+
* @remarks Time O(1), Space O(1)
|
|
572
|
+
* @returns Current length.
|
|
573
|
+
*/
|
|
519
574
|
|
|
520
575
|
get length(): number {
|
|
521
576
|
return this._length;
|
|
522
577
|
}
|
|
523
578
|
|
|
524
579
|
/**
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
* The `get first` function returns the first node in a doubly linked list, or undefined if the list is empty.
|
|
529
|
-
* @returns The method `get first()` returns the first node of the doubly linked list, or `undefined` if the list is empty.
|
|
580
|
+
* Get the first element value.
|
|
581
|
+
* @remarks Time O(1), Space O(1)
|
|
582
|
+
* @returns First element or undefined.
|
|
530
583
|
*/
|
|
584
|
+
|
|
531
585
|
get first(): E | undefined {
|
|
532
586
|
return this.head?.value;
|
|
533
587
|
}
|
|
534
588
|
|
|
535
589
|
/**
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
*
|
|
539
|
-
* The `get last` function returns the last node in a doubly linked list, or undefined if the list is empty.
|
|
540
|
-
* @returns The method `get last()` returns the last node of the doubly linked list, or `undefined` if the list is empty.
|
|
590
|
+
* Get the last element value.
|
|
591
|
+
* @remarks Time O(1), Space O(1)
|
|
592
|
+
* @returns Last element or undefined.
|
|
541
593
|
*/
|
|
594
|
+
|
|
542
595
|
get last(): E | undefined {
|
|
543
596
|
return this.tail?.value;
|
|
544
597
|
}
|
|
545
598
|
|
|
546
599
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
* @param
|
|
553
|
-
* @returns
|
|
600
|
+
* Create a new list from an array of elements.
|
|
601
|
+
* @remarks Time O(N), Space O(N)
|
|
602
|
+
* @template E
|
|
603
|
+
* @template R
|
|
604
|
+
* @param this - The constructor (subclass) to instantiate.
|
|
605
|
+
* @param data - Array of elements to insert.
|
|
606
|
+
* @returns A new list populated with the array's elements.
|
|
554
607
|
*/
|
|
555
|
-
|
|
556
|
-
|
|
608
|
+
|
|
609
|
+
static fromArray<E, R = any>(
|
|
610
|
+
this: new (
|
|
611
|
+
elements?: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>,
|
|
612
|
+
options?: DoublyLinkedListOptions<E, R>
|
|
613
|
+
) => any,
|
|
614
|
+
data: E[]
|
|
615
|
+
) {
|
|
616
|
+
return new this(data);
|
|
557
617
|
}
|
|
558
618
|
|
|
559
619
|
/**
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
* `DoublyLinkedListNode`.
|
|
565
|
-
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
566
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can
|
|
567
|
-
* be one of the following types:
|
|
568
|
-
* @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an
|
|
569
|
-
* instance of `DoublyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the
|
|
570
|
-
* parameter is a `DoublyLinkedListNode<E>`. If it is not an instance of `DoublyLinkedListNode<E>`,
|
|
571
|
-
* the function returns `false`.
|
|
620
|
+
* Type guard: check whether the input is a DoublyLinkedListNode.
|
|
621
|
+
* @remarks Time O(1), Space O(1)
|
|
622
|
+
* @param elementNodeOrPredicate - Element, node, or predicate.
|
|
623
|
+
* @returns True if the value is a DoublyLinkedListNode.
|
|
572
624
|
*/
|
|
625
|
+
|
|
573
626
|
isNode(
|
|
574
627
|
elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)
|
|
575
628
|
): elementNodeOrPredicate is DoublyLinkedListNode<E> {
|
|
@@ -577,14 +630,12 @@ export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, D
|
|
|
577
630
|
}
|
|
578
631
|
|
|
579
632
|
/**
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
* @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`
|
|
585
|
-
* method can accept either an element of type `E` or a `DoublyLinkedListNode<E>` object.
|
|
586
|
-
* @returns The `push` method is returning a boolean value, specifically `true`.
|
|
633
|
+
* Append an element/node to the tail.
|
|
634
|
+
* @remarks Time O(1), Space O(1)
|
|
635
|
+
* @param elementOrNode - Element or node to append.
|
|
636
|
+
* @returns True when appended.
|
|
587
637
|
*/
|
|
638
|
+
|
|
588
639
|
push(elementOrNode: E | DoublyLinkedListNode<E>): boolean {
|
|
589
640
|
const newNode = this._ensureNode(elementOrNode);
|
|
590
641
|
if (!this.head) {
|
|
@@ -601,57 +652,52 @@ export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, D
|
|
|
601
652
|
}
|
|
602
653
|
|
|
603
654
|
/**
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
607
|
-
* The `pop()` function removes and returns the value of the last element in a linked list.
|
|
608
|
-
* @returns The method is returning the value of the removed node.
|
|
655
|
+
* Remove and return the tail element.
|
|
656
|
+
* @remarks Time O(1), Space O(1)
|
|
657
|
+
* @returns Removed element or undefined.
|
|
609
658
|
*/
|
|
659
|
+
|
|
610
660
|
pop(): E | undefined {
|
|
611
661
|
if (!this.tail) return undefined;
|
|
612
|
-
const
|
|
662
|
+
const removed = this.tail;
|
|
613
663
|
if (this.head === this.tail) {
|
|
614
664
|
this._head = undefined;
|
|
615
665
|
this._tail = undefined;
|
|
616
666
|
} else {
|
|
617
|
-
this._tail =
|
|
667
|
+
this._tail = removed.prev;
|
|
618
668
|
this.tail!.next = undefined;
|
|
619
669
|
}
|
|
620
670
|
this._length--;
|
|
621
|
-
return
|
|
671
|
+
return removed.value;
|
|
622
672
|
}
|
|
623
673
|
|
|
624
674
|
/**
|
|
625
|
-
*
|
|
626
|
-
*
|
|
627
|
-
*
|
|
628
|
-
* The `shift()` function removes and returns the value of the first element in a doubly linked list.
|
|
629
|
-
* @returns The value of the removed node.
|
|
675
|
+
* Remove and return the head element.
|
|
676
|
+
* @remarks Time O(1), Space O(1)
|
|
677
|
+
* @returns Removed element or undefined.
|
|
630
678
|
*/
|
|
679
|
+
|
|
631
680
|
shift(): E | undefined {
|
|
632
681
|
if (!this.head) return undefined;
|
|
633
|
-
const
|
|
682
|
+
const removed = this.head;
|
|
634
683
|
if (this.head === this.tail) {
|
|
635
684
|
this._head = undefined;
|
|
636
685
|
this._tail = undefined;
|
|
637
686
|
} else {
|
|
638
|
-
this._head =
|
|
687
|
+
this._head = removed.next;
|
|
639
688
|
this.head!.prev = undefined;
|
|
640
689
|
}
|
|
641
690
|
this._length--;
|
|
642
|
-
return
|
|
691
|
+
return removed.value;
|
|
643
692
|
}
|
|
644
693
|
|
|
645
694
|
/**
|
|
646
|
-
*
|
|
647
|
-
*
|
|
648
|
-
*
|
|
649
|
-
*
|
|
650
|
-
* @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the
|
|
651
|
-
* `unshift` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an
|
|
652
|
-
* element of type `E`.
|
|
653
|
-
* @returns The `unshift` method is returning a boolean value, specifically `true`.
|
|
695
|
+
* Prepend an element/node to the head.
|
|
696
|
+
* @remarks Time O(1), Space O(1)
|
|
697
|
+
* @param elementOrNode - Element or node to prepend.
|
|
698
|
+
* @returns True when prepended.
|
|
654
699
|
*/
|
|
700
|
+
|
|
655
701
|
unshift(elementOrNode: E | DoublyLinkedListNode<E>): boolean {
|
|
656
702
|
const newNode = this._ensureNode(elementOrNode);
|
|
657
703
|
if (!this.head) {
|
|
@@ -668,352 +714,254 @@ export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, D
|
|
|
668
714
|
}
|
|
669
715
|
|
|
670
716
|
/**
|
|
671
|
-
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
* transformation function if provided.
|
|
676
|
-
* @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`
|
|
677
|
-
* parameter in the `pushMany` function can accept an iterable containing elements of type `E`, `R`,
|
|
678
|
-
* or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and pushes
|
|
679
|
-
* it onto the linked list. If a transformation function `to
|
|
680
|
-
* @returns The `pushMany` function is returning an array of boolean values (`ans`) which indicate
|
|
681
|
-
* the success or failure of pushing each element into the data structure.
|
|
717
|
+
* Append a sequence of elements/nodes.
|
|
718
|
+
* @remarks Time O(N), Space O(1)
|
|
719
|
+
* @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
|
|
720
|
+
* @returns Array of per-element success flags.
|
|
682
721
|
*/
|
|
683
|
-
|
|
722
|
+
|
|
723
|
+
pushMany(elements: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>): boolean[] {
|
|
684
724
|
const ans: boolean[] = [];
|
|
685
725
|
for (const el of elements) {
|
|
686
|
-
if (this.toElementFn)
|
|
687
|
-
|
|
688
|
-
continue;
|
|
689
|
-
}
|
|
690
|
-
ans.push(this.push(el as E | DoublyLinkedListNode<E>));
|
|
726
|
+
if (this.toElementFn) ans.push(this.push(this.toElementFn(el as R)));
|
|
727
|
+
else ans.push(this.push(el as E | DoublyLinkedListNode<E>));
|
|
691
728
|
}
|
|
692
729
|
return ans;
|
|
693
730
|
}
|
|
694
731
|
|
|
695
732
|
/**
|
|
696
|
-
*
|
|
697
|
-
*
|
|
698
|
-
*
|
|
699
|
-
*
|
|
700
|
-
* beginning of a Doubly Linked List, returning an array of boolean values indicating the success of
|
|
701
|
-
* each insertion.
|
|
702
|
-
* @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`
|
|
703
|
-
* parameter in the `unshiftMany` function can accept an iterable containing elements of type `E`,
|
|
704
|
-
* `R`, or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and
|
|
705
|
-
* performs an `unshift` operation on the doubly linked list
|
|
706
|
-
* @returns The `unshiftMany` function returns an array of boolean values indicating the success of
|
|
707
|
-
* each unshift operation performed on the elements passed as input.
|
|
733
|
+
* Prepend a sequence of elements/nodes.
|
|
734
|
+
* @remarks Time O(N), Space O(1)
|
|
735
|
+
* @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
|
|
736
|
+
* @returns Array of per-element success flags.
|
|
708
737
|
*/
|
|
709
|
-
|
|
738
|
+
|
|
739
|
+
unshiftMany(elements: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>): boolean[] {
|
|
710
740
|
const ans: boolean[] = [];
|
|
711
741
|
for (const el of elements) {
|
|
712
|
-
if (this.toElementFn)
|
|
713
|
-
|
|
714
|
-
continue;
|
|
715
|
-
}
|
|
716
|
-
ans.push(this.unshift(el as E | DoublyLinkedListNode<E>));
|
|
742
|
+
if (this.toElementFn) ans.push(this.unshift(this.toElementFn(el as R)));
|
|
743
|
+
else ans.push(this.unshift(el as E | DoublyLinkedListNode<E>));
|
|
717
744
|
}
|
|
718
745
|
return ans;
|
|
719
746
|
}
|
|
720
747
|
|
|
721
748
|
/**
|
|
722
|
-
*
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
*
|
|
726
|
-
* @param {number} index - The index parameter is a number that represents the position of the element we want to
|
|
727
|
-
* retrieve from the list.
|
|
728
|
-
* @returns The method is returning the value at the specified index in the linked list. If the index is out of bounds
|
|
729
|
-
* or the linked list is empty, it will return undefined.
|
|
749
|
+
* Get the element at a given index.
|
|
750
|
+
* @remarks Time O(N), Space O(1)
|
|
751
|
+
* @param index - Zero-based index.
|
|
752
|
+
* @returns Element or undefined.
|
|
730
753
|
*/
|
|
754
|
+
|
|
731
755
|
at(index: number): E | undefined {
|
|
732
756
|
if (index < 0 || index >= this._length) return undefined;
|
|
733
757
|
let current = this.head;
|
|
734
|
-
for (let i = 0; i < index; i++)
|
|
735
|
-
current = current!.next;
|
|
736
|
-
}
|
|
758
|
+
for (let i = 0; i < index; i++) current = current!.next;
|
|
737
759
|
return current!.value;
|
|
738
760
|
}
|
|
739
761
|
|
|
740
762
|
/**
|
|
741
|
-
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
*
|
|
745
|
-
* range.
|
|
746
|
-
* @param {number} index - The `index` parameter is a number that represents the position of the node we want to
|
|
747
|
-
* retrieve from the doubly linked list. It indicates the zero-based index of the node we want to access.
|
|
748
|
-
* @returns The method `getNodeAt(index: number)` returns a `DoublyLinkedListNode<E>` object if the index is within the
|
|
749
|
-
* valid range of the linked list, otherwise it returns `undefined`.
|
|
763
|
+
* Get the node reference at a given index.
|
|
764
|
+
* @remarks Time O(N), Space O(1)
|
|
765
|
+
* @param index - Zero-based index.
|
|
766
|
+
* @returns Node or undefined.
|
|
750
767
|
*/
|
|
768
|
+
|
|
751
769
|
getNodeAt(index: number): DoublyLinkedListNode<E> | undefined {
|
|
752
770
|
if (index < 0 || index >= this._length) return undefined;
|
|
753
771
|
let current = this.head;
|
|
754
|
-
for (let i = 0; i < index; i++)
|
|
755
|
-
current = current!.next;
|
|
756
|
-
}
|
|
772
|
+
for (let i = 0; i < index; i++) current = current!.next;
|
|
757
773
|
return current;
|
|
758
774
|
}
|
|
759
775
|
|
|
760
776
|
/**
|
|
761
|
-
*
|
|
762
|
-
*
|
|
763
|
-
*
|
|
764
|
-
*
|
|
765
|
-
* or predicate.
|
|
766
|
-
* @param {| E
|
|
767
|
-
* | DoublyLinkedListNode<E>
|
|
768
|
-
* | ((node: DoublyLinkedListNode<E>) => boolean)
|
|
769
|
-
* | undefined} elementNodeOrPredicate - The `getNode` method you provided is used to find a
|
|
770
|
-
* node in a doubly linked list based on a given element, node, or predicate function. The
|
|
771
|
-
* `elementNodeOrPredicate` parameter can be one of the following:
|
|
772
|
-
* @returns The `getNode` method returns a `DoublyLinkedListNode<E>` or `undefined` based on the
|
|
773
|
-
* input `elementNodeOrPredicate`. If the input is `undefined`, the method returns `undefined`.
|
|
774
|
-
* Otherwise, it iterates through the linked list starting from the head node and applies the
|
|
775
|
-
* provided predicate function to each node. If a node satisfies the predicate, that node is
|
|
776
|
-
* returned. If
|
|
777
|
+
* Find a node by value, reference, or predicate.
|
|
778
|
+
* @remarks Time O(N), Space O(1)
|
|
779
|
+
* @param [elementNodeOrPredicate] - Element, node, or predicate to match.
|
|
780
|
+
* @returns Matching node or undefined.
|
|
777
781
|
*/
|
|
782
|
+
|
|
778
783
|
getNode(
|
|
779
784
|
elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean) | undefined
|
|
780
785
|
): DoublyLinkedListNode<E> | undefined {
|
|
781
786
|
if (elementNodeOrPredicate === undefined) return;
|
|
782
|
-
|
|
787
|
+
|
|
788
|
+
if (this.isNode(elementNodeOrPredicate)) {
|
|
789
|
+
const target = elementNodeOrPredicate;
|
|
790
|
+
|
|
791
|
+
let cur = this.head;
|
|
792
|
+
while (cur) {
|
|
793
|
+
if (cur === target) return target;
|
|
794
|
+
cur = cur.next;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
const isMatch = (node: DoublyLinkedListNode<E>) => this._equals(node.value, target.value);
|
|
798
|
+
cur = this.head;
|
|
799
|
+
while (cur) {
|
|
800
|
+
if (isMatch(cur)) return cur;
|
|
801
|
+
cur = cur.next;
|
|
802
|
+
}
|
|
803
|
+
return undefined;
|
|
804
|
+
}
|
|
805
|
+
|
|
783
806
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
784
807
|
let current = this.head;
|
|
785
|
-
|
|
786
808
|
while (current) {
|
|
787
|
-
if (predicate(current))
|
|
788
|
-
return current;
|
|
789
|
-
}
|
|
809
|
+
if (predicate(current)) return current;
|
|
790
810
|
current = current.next;
|
|
791
811
|
}
|
|
792
|
-
|
|
793
812
|
return undefined;
|
|
794
813
|
}
|
|
795
814
|
|
|
796
815
|
/**
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
* @
|
|
802
|
-
* which you want to add a new element or node in the doubly linked list. It indicates the location
|
|
803
|
-
* where the new element or node should be inserted.
|
|
804
|
-
* @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
|
|
805
|
-
* `addAt` method can be either a value of type `E` or a `DoublyLinkedListNode<E>` object.
|
|
806
|
-
* @returns The `addAt` method returns a boolean value. It returns `true` if the element or node was
|
|
807
|
-
* successfully added at the specified index, and `false` if the index is out of bounds (less than 0
|
|
808
|
-
* or greater than the length of the list).
|
|
816
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
817
|
+
* @remarks Time O(N), Space O(1)
|
|
818
|
+
* @param index - Zero-based index.
|
|
819
|
+
* @param newElementOrNode - Element or node to insert.
|
|
820
|
+
* @returns True if inserted.
|
|
809
821
|
*/
|
|
822
|
+
|
|
810
823
|
addAt(index: number, newElementOrNode: E | DoublyLinkedListNode<E>): boolean {
|
|
811
824
|
if (index < 0 || index > this._length) return false;
|
|
812
|
-
if (index === 0)
|
|
813
|
-
|
|
814
|
-
return true;
|
|
815
|
-
}
|
|
816
|
-
if (index === this._length) {
|
|
817
|
-
this.push(newElementOrNode);
|
|
818
|
-
return true;
|
|
819
|
-
}
|
|
825
|
+
if (index === 0) return this.unshift(newElementOrNode);
|
|
826
|
+
if (index === this._length) return this.push(newElementOrNode);
|
|
820
827
|
|
|
821
828
|
const newNode = this._ensureNode(newElementOrNode);
|
|
822
|
-
const prevNode = this.getNodeAt(index - 1)
|
|
823
|
-
const nextNode = prevNode
|
|
829
|
+
const prevNode = this.getNodeAt(index - 1)!;
|
|
830
|
+
const nextNode = prevNode.next!;
|
|
824
831
|
newNode.prev = prevNode;
|
|
825
832
|
newNode.next = nextNode;
|
|
826
|
-
prevNode
|
|
827
|
-
nextNode
|
|
833
|
+
prevNode.next = newNode;
|
|
834
|
+
nextNode.prev = newNode;
|
|
828
835
|
this._length++;
|
|
829
836
|
return true;
|
|
830
837
|
}
|
|
831
838
|
|
|
832
839
|
/**
|
|
833
|
-
*
|
|
834
|
-
*
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
* @param {E | DoublyLinkedListNode<E>} existingElementOrNode - The `existingElementOrNode` parameter
|
|
839
|
-
* in the `addBefore` method can be either an element of type `E` or a `DoublyLinkedListNode<E>`.
|
|
840
|
-
* @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter
|
|
841
|
-
* represents the element or node that you want to add before the `existingElementOrNode` in a doubly
|
|
842
|
-
* linked list.
|
|
843
|
-
* @returns The `addBefore` method returns a boolean value - `true` if the new element or node was
|
|
844
|
-
* successfully added before the existing element or node, and `false` if the existing element or
|
|
845
|
-
* node was not found.
|
|
840
|
+
* Insert a new element/node before an existing one.
|
|
841
|
+
* @remarks Time O(N), Space O(1)
|
|
842
|
+
* @param existingElementOrNode - Existing element or node.
|
|
843
|
+
* @param newElementOrNode - Element or node to insert.
|
|
844
|
+
* @returns True if inserted.
|
|
846
845
|
*/
|
|
846
|
+
|
|
847
847
|
addBefore(
|
|
848
848
|
existingElementOrNode: E | DoublyLinkedListNode<E>,
|
|
849
849
|
newElementOrNode: E | DoublyLinkedListNode<E>
|
|
850
850
|
): boolean {
|
|
851
|
-
const existingNode
|
|
851
|
+
const existingNode = this.isNode(existingElementOrNode)
|
|
852
852
|
? existingElementOrNode
|
|
853
853
|
: this.getNode(existingElementOrNode);
|
|
854
|
+
if (!existingNode) return false;
|
|
854
855
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
if (existingNode === this.head) {
|
|
864
|
-
this._head = newNode;
|
|
865
|
-
}
|
|
866
|
-
this._length++;
|
|
867
|
-
return true;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
return false;
|
|
856
|
+
const newNode = this._ensureNode(newElementOrNode);
|
|
857
|
+
newNode.prev = existingNode.prev;
|
|
858
|
+
if (existingNode.prev) existingNode.prev.next = newNode;
|
|
859
|
+
newNode.next = existingNode;
|
|
860
|
+
existingNode.prev = newNode;
|
|
861
|
+
if (existingNode === this.head) this._head = newNode;
|
|
862
|
+
this._length++;
|
|
863
|
+
return true;
|
|
871
864
|
}
|
|
872
865
|
|
|
873
866
|
/**
|
|
874
|
-
*
|
|
875
|
-
*
|
|
876
|
-
*
|
|
877
|
-
*
|
|
878
|
-
*
|
|
879
|
-
* @param {E | DoublyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the
|
|
880
|
-
* element or node in the doubly linked list after which you want to add a new element or node.
|
|
881
|
-
* @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
|
|
882
|
-
* `addAfter` method represents the element or node that you want to add after the existing element
|
|
883
|
-
* or node in a doubly linked list. This parameter can be either an element value or a
|
|
884
|
-
* `DoublyLinkedListNode` object that you want to insert
|
|
885
|
-
* @returns The `addAfter` method returns a boolean value - `true` if the new element or node was
|
|
886
|
-
* successfully added after the existing element or node, and `false` if the existing element or node
|
|
887
|
-
* was not found in the linked list.
|
|
867
|
+
* Insert a new element/node after an existing one.
|
|
868
|
+
* @remarks Time O(N), Space O(1)
|
|
869
|
+
* @param existingElementOrNode - Existing element or node.
|
|
870
|
+
* @param newElementOrNode - Element or node to insert.
|
|
871
|
+
* @returns True if inserted.
|
|
888
872
|
*/
|
|
873
|
+
|
|
889
874
|
addAfter(existingElementOrNode: E | DoublyLinkedListNode<E>, newElementOrNode: E | DoublyLinkedListNode<E>): boolean {
|
|
890
|
-
const existingNode
|
|
875
|
+
const existingNode = this.isNode(existingElementOrNode)
|
|
891
876
|
? existingElementOrNode
|
|
892
877
|
: this.getNode(existingElementOrNode);
|
|
878
|
+
if (!existingNode) return false;
|
|
893
879
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
if (existingNode === this.tail) {
|
|
903
|
-
this._tail = newNode;
|
|
904
|
-
}
|
|
905
|
-
this._length++;
|
|
906
|
-
return true;
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
return false;
|
|
880
|
+
const newNode = this._ensureNode(newElementOrNode);
|
|
881
|
+
newNode.next = existingNode.next;
|
|
882
|
+
if (existingNode.next) existingNode.next.prev = newNode;
|
|
883
|
+
newNode.prev = existingNode;
|
|
884
|
+
existingNode.next = newNode;
|
|
885
|
+
if (existingNode === this.tail) this._tail = newNode;
|
|
886
|
+
this._length++;
|
|
887
|
+
return true;
|
|
910
888
|
}
|
|
911
889
|
|
|
912
890
|
/**
|
|
913
|
-
*
|
|
914
|
-
*
|
|
915
|
-
*
|
|
916
|
-
*
|
|
917
|
-
*
|
|
918
|
-
* @param {number} index - The `index` parameter in the `setAt` method refers to the position in the
|
|
919
|
-
* data structure where you want to set a new value.
|
|
920
|
-
* @param {E} value - The `value` parameter in the `setAt` method represents the new value that you
|
|
921
|
-
* want to set at the specified index in the data structure.
|
|
922
|
-
* @returns The `setAt` method returns a boolean value - `true` if the value at the specified index
|
|
923
|
-
* is successfully updated, and `false` if the index is out of bounds.
|
|
891
|
+
* Set the element value at an index.
|
|
892
|
+
* @remarks Time O(N), Space O(1)
|
|
893
|
+
* @param index - Zero-based index.
|
|
894
|
+
* @param value - New value.
|
|
895
|
+
* @returns True if updated.
|
|
924
896
|
*/
|
|
897
|
+
|
|
925
898
|
setAt(index: number, value: E): boolean {
|
|
926
899
|
const node = this.getNodeAt(index);
|
|
927
|
-
if (node)
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
}
|
|
931
|
-
return false;
|
|
900
|
+
if (!node) return false;
|
|
901
|
+
node.value = value;
|
|
902
|
+
return true;
|
|
932
903
|
}
|
|
933
904
|
|
|
934
905
|
/**
|
|
935
|
-
*
|
|
936
|
-
*
|
|
937
|
-
*
|
|
938
|
-
*
|
|
939
|
-
* @param {number} index - The index parameter represents the position of the element that needs to be deleted in the
|
|
940
|
-
* data structure. It is of type number.
|
|
941
|
-
* @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of
|
|
942
|
-
* bounds.
|
|
906
|
+
* Delete the element at an index.
|
|
907
|
+
* @remarks Time O(N), Space O(1)
|
|
908
|
+
* @param index - Zero-based index.
|
|
909
|
+
* @returns Removed element or undefined.
|
|
943
910
|
*/
|
|
911
|
+
|
|
944
912
|
deleteAt(index: number): E | undefined {
|
|
945
913
|
if (index < 0 || index >= this._length) return;
|
|
946
|
-
|
|
947
|
-
if (index ===
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
this.pop();
|
|
955
|
-
return deleted;
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
const removedNode = this.getNodeAt(index);
|
|
959
|
-
const prevNode = removedNode!.prev;
|
|
960
|
-
const nextNode = removedNode!.next;
|
|
961
|
-
prevNode!.next = nextNode;
|
|
962
|
-
nextNode!.prev = prevNode;
|
|
914
|
+
if (index === 0) return this.shift();
|
|
915
|
+
if (index === this._length - 1) return this.pop();
|
|
916
|
+
|
|
917
|
+
const removedNode = this.getNodeAt(index)!;
|
|
918
|
+
const prevNode = removedNode.prev!;
|
|
919
|
+
const nextNode = removedNode.next!;
|
|
920
|
+
prevNode.next = nextNode;
|
|
921
|
+
nextNode.prev = prevNode;
|
|
963
922
|
this._length--;
|
|
964
|
-
return removedNode
|
|
923
|
+
return removedNode.value;
|
|
965
924
|
}
|
|
966
925
|
|
|
967
926
|
/**
|
|
968
|
-
*
|
|
969
|
-
*
|
|
970
|
-
*
|
|
971
|
-
*
|
|
972
|
-
* @param {E | DoublyLinkedListNode<E> | undefined} elementOrNode - The `elementOrNode` parameter in
|
|
973
|
-
* the `delete` method can accept an element of type `E`, a `DoublyLinkedListNode` of type `E`, or it
|
|
974
|
-
* can be `undefined`. This parameter is used to identify the node that needs to be deleted from the
|
|
975
|
-
* doubly linked list
|
|
976
|
-
* @returns The `delete` method returns a boolean value - `true` if the element or node was
|
|
977
|
-
* successfully deleted from the doubly linked list, and `false` if the element or node was not found
|
|
978
|
-
* in the list.
|
|
927
|
+
* Delete the first match by value/node.
|
|
928
|
+
* @remarks Time O(N), Space O(1)
|
|
929
|
+
* @param [elementOrNode] - Element or node to remove.
|
|
930
|
+
* @returns True if removed.
|
|
979
931
|
*/
|
|
932
|
+
|
|
980
933
|
delete(elementOrNode: E | DoublyLinkedListNode<E> | undefined): boolean {
|
|
981
|
-
const node
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
if (nextNode) nextNode.prev = prevNode;
|
|
993
|
-
this._length--;
|
|
994
|
-
}
|
|
995
|
-
return true;
|
|
934
|
+
const node = this.getNode(elementOrNode);
|
|
935
|
+
if (!node) return false;
|
|
936
|
+
|
|
937
|
+
if (node === this.head) this.shift();
|
|
938
|
+
else if (node === this.tail) this.pop();
|
|
939
|
+
else {
|
|
940
|
+
const prevNode = node.prev!;
|
|
941
|
+
const nextNode = node.next!;
|
|
942
|
+
prevNode.next = nextNode;
|
|
943
|
+
nextNode.prev = prevNode;
|
|
944
|
+
this._length--;
|
|
996
945
|
}
|
|
997
|
-
return
|
|
946
|
+
return true;
|
|
998
947
|
}
|
|
999
948
|
|
|
1000
949
|
/**
|
|
1001
|
-
*
|
|
1002
|
-
*
|
|
1003
|
-
*
|
|
1004
|
-
* The function checks if a variable has a length greater than zero and returns a boolean value.
|
|
1005
|
-
* @returns A boolean value is being returned.
|
|
950
|
+
* Check whether the list is empty.
|
|
951
|
+
* @remarks Time O(1), Space O(1)
|
|
952
|
+
* @returns True if length is 0.
|
|
1006
953
|
*/
|
|
954
|
+
|
|
1007
955
|
isEmpty(): boolean {
|
|
1008
956
|
return this._length === 0;
|
|
1009
957
|
}
|
|
1010
958
|
|
|
1011
959
|
/**
|
|
1012
|
-
*
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1015
|
-
* The `clear` function resets the linked list by setting the head, tail, and length to undefined and 0 respectively.
|
|
960
|
+
* Remove all nodes and reset length.
|
|
961
|
+
* @remarks Time O(N), Space O(1)
|
|
962
|
+
* @returns void
|
|
1016
963
|
*/
|
|
964
|
+
|
|
1017
965
|
clear(): void {
|
|
1018
966
|
this._head = undefined;
|
|
1019
967
|
this._tail = undefined;
|
|
@@ -1021,17 +969,12 @@ export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, D
|
|
|
1021
969
|
}
|
|
1022
970
|
|
|
1023
971
|
/**
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
1026
|
-
*
|
|
1027
|
-
*
|
|
1028
|
-
* node or predicate.
|
|
1029
|
-
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
1030
|
-
* elementNodeOrPredicate - The `get` method takes in a parameter called `elementNodeOrPredicate`,
|
|
1031
|
-
* which can be one of the following types:
|
|
1032
|
-
* @returns The `get` method returns the value of the first node in the doubly linked list that
|
|
1033
|
-
* satisfies the provided predicate function. If no such node is found, it returns `undefined`.
|
|
972
|
+
* Find the first value matching a predicate scanning forward.
|
|
973
|
+
* @remarks Time O(N), Space O(1)
|
|
974
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
975
|
+
* @returns Matched value or undefined.
|
|
1034
976
|
*/
|
|
977
|
+
|
|
1035
978
|
search(
|
|
1036
979
|
elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)
|
|
1037
980
|
): E | undefined {
|
|
@@ -1045,18 +988,12 @@ export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, D
|
|
|
1045
988
|
}
|
|
1046
989
|
|
|
1047
990
|
/**
|
|
1048
|
-
*
|
|
1049
|
-
*
|
|
1050
|
-
*
|
|
1051
|
-
*
|
|
1052
|
-
* the tail and moving backwards.
|
|
1053
|
-
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
1054
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getBackward`
|
|
1055
|
-
* function can be one of the following types:
|
|
1056
|
-
* @returns The `getBackward` method returns the value of the element node that matches the provided
|
|
1057
|
-
* predicate when traversing the doubly linked list backwards. If no matching element is found, it
|
|
1058
|
-
* returns `undefined`.
|
|
991
|
+
* Find the first value matching a predicate scanning backward.
|
|
992
|
+
* @remarks Time O(N), Space O(1)
|
|
993
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
994
|
+
* @returns Matched value or undefined.
|
|
1059
995
|
*/
|
|
996
|
+
|
|
1060
997
|
getBackward(
|
|
1061
998
|
elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)
|
|
1062
999
|
): E | undefined {
|
|
@@ -1070,11 +1007,11 @@ export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, D
|
|
|
1070
1007
|
}
|
|
1071
1008
|
|
|
1072
1009
|
/**
|
|
1073
|
-
*
|
|
1074
|
-
*
|
|
1075
|
-
*
|
|
1076
|
-
* The `reverse` function reverses the order of the elements in a doubly linked list.
|
|
1010
|
+
* Reverse the list in place.
|
|
1011
|
+
* @remarks Time O(N), Space O(1)
|
|
1012
|
+
* @returns This list.
|
|
1077
1013
|
*/
|
|
1014
|
+
|
|
1078
1015
|
reverse(): this {
|
|
1079
1016
|
let current = this.head;
|
|
1080
1017
|
[this._head, this._tail] = [this.tail, this.head];
|
|
@@ -1087,226 +1024,185 @@ export class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, D
|
|
|
1087
1024
|
}
|
|
1088
1025
|
|
|
1089
1026
|
/**
|
|
1090
|
-
*
|
|
1091
|
-
*
|
|
1092
|
-
*
|
|
1093
|
-
*
|
|
1094
|
-
* as the original list.
|
|
1095
|
-
* @returns The `clone()` method is returning a new instance of the `DoublyLinkedList` class, which
|
|
1096
|
-
* is a copy of the original list.
|
|
1027
|
+
* Set the equality comparator used to compare values.
|
|
1028
|
+
* @remarks Time O(1), Space O(1)
|
|
1029
|
+
* @param equals - Equality predicate (a, b) → boolean.
|
|
1030
|
+
* @returns This list.
|
|
1097
1031
|
*/
|
|
1098
|
-
|
|
1099
|
-
|
|
1032
|
+
|
|
1033
|
+
setEquality(equals: (a: E, b: E) => boolean): this {
|
|
1034
|
+
this._equals = equals;
|
|
1035
|
+
return this;
|
|
1100
1036
|
}
|
|
1101
1037
|
|
|
1102
1038
|
/**
|
|
1103
|
-
*
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
1106
|
-
* The `filter` function creates a new DoublyLinkedList by iterating over the elements of the current
|
|
1107
|
-
* list and applying a callback function to each element, returning only the elements for which the
|
|
1108
|
-
* callback function returns true.
|
|
1109
|
-
* @param callback - The `callback` parameter is a function that will be called for each element in
|
|
1110
|
-
* the DoublyLinkedList. It takes three arguments: the current element, the index of the current
|
|
1111
|
-
* element, and the DoublyLinkedList itself. The callback function should return a boolean value
|
|
1112
|
-
* indicating whether the current element should be included
|
|
1113
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
1114
|
-
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
|
1115
|
-
* passed as the `this` value to the `callback` function. If `thisArg` is
|
|
1116
|
-
* @returns The `filter` method is returning a new `DoublyLinkedList` object that contains the
|
|
1117
|
-
* elements that pass the filter condition specified by the `callback` function.
|
|
1039
|
+
* Deep clone this list (values are copied by reference).
|
|
1040
|
+
* @remarks Time O(N), Space O(N)
|
|
1041
|
+
* @returns A new list with the same element sequence.
|
|
1118
1042
|
*/
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
for (const
|
|
1123
|
-
|
|
1124
|
-
filteredList.push(current);
|
|
1125
|
-
}
|
|
1126
|
-
index++;
|
|
1127
|
-
}
|
|
1128
|
-
return filteredList;
|
|
1043
|
+
|
|
1044
|
+
clone(): this {
|
|
1045
|
+
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1046
|
+
for (const v of this) out.push(v);
|
|
1047
|
+
return out;
|
|
1129
1048
|
}
|
|
1130
1049
|
|
|
1131
1050
|
/**
|
|
1132
|
-
*
|
|
1133
|
-
*
|
|
1134
|
-
*
|
|
1135
|
-
*
|
|
1136
|
-
*
|
|
1137
|
-
* @param callback - The callback parameter is a function that will be called for each element in the
|
|
1138
|
-
* original DoublyLinkedList. It takes three arguments: current (the current element being
|
|
1139
|
-
* processed), index (the index of the current element), and this (the original DoublyLinkedList).
|
|
1140
|
-
* The callback function should return a value of type
|
|
1141
|
-
* @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to
|
|
1142
|
-
* convert the raw element (`RR`) to the desired element type (`T`). It takes the raw element as
|
|
1143
|
-
* input and returns the converted element. If this parameter is not provided, the raw element will
|
|
1144
|
-
* be used as is.
|
|
1145
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
1146
|
-
* specify the value of `this` within the callback function. It is used to set the context or scope
|
|
1147
|
-
* in which the callback function will be executed. If `thisArg` is provided, it will be used as the
|
|
1148
|
-
* value of
|
|
1149
|
-
* @returns a new instance of the `DoublyLinkedList` class with elements of type `T` and `RR`.
|
|
1051
|
+
* Filter values into a new list of the same class.
|
|
1052
|
+
* @remarks Time O(N), Space O(N)
|
|
1053
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
1054
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1055
|
+
* @returns A new list with kept values.
|
|
1150
1056
|
*/
|
|
1151
|
-
map<EM, RM>(
|
|
1152
|
-
callback: ElementCallback<E, R, EM>,
|
|
1153
|
-
toElementFn?: (rawElement: RM) => EM,
|
|
1154
|
-
thisArg?: any
|
|
1155
|
-
): DoublyLinkedList<EM, RM> {
|
|
1156
|
-
const mappedList = new DoublyLinkedList<EM, RM>([], { toElementFn, maxLen: this._maxLen });
|
|
1157
|
-
let index = 0;
|
|
1158
|
-
for (const current of this) {
|
|
1159
|
-
mappedList.push(callback.call(thisArg, current, index, this));
|
|
1160
|
-
index++;
|
|
1161
|
-
}
|
|
1162
1057
|
|
|
1163
|
-
|
|
1058
|
+
filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): this {
|
|
1059
|
+
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1060
|
+
let index = 0;
|
|
1061
|
+
for (const v of this) if (callback.call(thisArg, v, index++, this)) out.push(v);
|
|
1062
|
+
return out;
|
|
1164
1063
|
}
|
|
1165
1064
|
|
|
1166
1065
|
/**
|
|
1167
|
-
*
|
|
1168
|
-
*
|
|
1169
|
-
*
|
|
1170
|
-
*
|
|
1171
|
-
*
|
|
1172
|
-
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementOrNode
|
|
1173
|
-
* - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values:
|
|
1174
|
-
* @returns The `countOccurrences` method returns the number of occurrences of the specified element,
|
|
1175
|
-
* node, or predicate function in the doubly linked list.
|
|
1066
|
+
* Map values into a new list of the same class.
|
|
1067
|
+
* @remarks Time O(N), Space O(N)
|
|
1068
|
+
* @param callback - Mapping function (value, index, list) → newValue.
|
|
1069
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1070
|
+
* @returns A new list with mapped values.
|
|
1176
1071
|
*/
|
|
1177
|
-
countOccurrences(elementOrNode: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)): number {
|
|
1178
|
-
const predicate = this._ensurePredicate(elementOrNode);
|
|
1179
|
-
let count = 0;
|
|
1180
|
-
let current = this.head;
|
|
1181
1072
|
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1073
|
+
mapSame(callback: ElementCallback<E, R, E>, thisArg?: any): this {
|
|
1074
|
+
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1075
|
+
let index = 0;
|
|
1076
|
+
for (const v of this) {
|
|
1077
|
+
const mv = thisArg === undefined ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
|
|
1078
|
+
out.push(mv);
|
|
1187
1079
|
}
|
|
1188
|
-
|
|
1189
|
-
return count;
|
|
1080
|
+
return out;
|
|
1190
1081
|
}
|
|
1191
1082
|
|
|
1192
1083
|
/**
|
|
1193
|
-
*
|
|
1084
|
+
* Map values into a new list (possibly different element type).
|
|
1085
|
+
* @remarks Time O(N), Space O(N)
|
|
1086
|
+
* @template EM
|
|
1087
|
+
* @template RM
|
|
1088
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
1089
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
1090
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1091
|
+
* @returns A new DoublyLinkedList with mapped values.
|
|
1194
1092
|
*/
|
|
1195
|
-
protected *_getIterator(): IterableIterator<E> {
|
|
1196
|
-
let current = this.head;
|
|
1197
1093
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1094
|
+
map<EM, RM>(
|
|
1095
|
+
callback: ElementCallback<E, R, EM>,
|
|
1096
|
+
options?: DoublyLinkedListOptions<EM, RM>,
|
|
1097
|
+
thisArg?: any
|
|
1098
|
+
): DoublyLinkedList<EM, RM> {
|
|
1099
|
+
const out = this._createLike<EM, RM>([], { ...(options ?? {}), maxLen: this._maxLen });
|
|
1100
|
+
let index = 0;
|
|
1101
|
+
for (const v of this) out.push(callback.call(thisArg, v, index++, this));
|
|
1102
|
+
return out;
|
|
1202
1103
|
}
|
|
1203
1104
|
|
|
1204
1105
|
/**
|
|
1205
|
-
*
|
|
1206
|
-
*
|
|
1106
|
+
* (Protected) Create or return a node for the given input (node or raw element).
|
|
1107
|
+
* @remarks Time O(1), Space O(1)
|
|
1108
|
+
* @param elementOrNode - Element value or node to normalize.
|
|
1109
|
+
* @returns A DoublyLinkedListNode for the provided input.
|
|
1207
1110
|
*/
|
|
1208
|
-
protected *_getReverseIterator(): IterableIterator<E> {
|
|
1209
|
-
let current = this.tail;
|
|
1210
1111
|
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
}
|
|
1112
|
+
protected _ensureNode(elementOrNode: E | DoublyLinkedListNode<E>) {
|
|
1113
|
+
if (this.isNode(elementOrNode)) return elementOrNode;
|
|
1114
|
+
return new DoublyLinkedListNode<E>(elementOrNode);
|
|
1215
1115
|
}
|
|
1216
1116
|
|
|
1217
1117
|
/**
|
|
1218
|
-
*
|
|
1219
|
-
*
|
|
1118
|
+
* (Protected) Normalize input into a predicate over nodes.
|
|
1119
|
+
* @remarks Time O(1), Space O(1)
|
|
1120
|
+
* @param elementNodeOrPredicate - Element, node, or node predicate.
|
|
1121
|
+
* @returns A predicate function taking a node and returning true/false.
|
|
1220
1122
|
*/
|
|
1221
|
-
protected *_getNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {
|
|
1222
|
-
let current = this.head;
|
|
1223
1123
|
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1124
|
+
protected _ensurePredicate(
|
|
1125
|
+
elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)
|
|
1126
|
+
): (node: DoublyLinkedListNode<E>) => boolean {
|
|
1127
|
+
if (this.isNode(elementNodeOrPredicate)) {
|
|
1128
|
+
const target = elementNodeOrPredicate;
|
|
1129
|
+
return (node: DoublyLinkedListNode<E>) => node === target;
|
|
1227
1130
|
}
|
|
1131
|
+
if (typeof elementNodeOrPredicate === 'function') {
|
|
1132
|
+
return elementNodeOrPredicate as (node: DoublyLinkedListNode<E>) => boolean;
|
|
1133
|
+
}
|
|
1134
|
+
const value = elementNodeOrPredicate as E;
|
|
1135
|
+
return (node: DoublyLinkedListNode<E>) => this._equals(node.value, value);
|
|
1228
1136
|
}
|
|
1229
1137
|
|
|
1230
|
-
// protected *_getReverseNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {
|
|
1231
|
-
// const reversedArr = [...this._getNodeIterator()].reverse();
|
|
1232
|
-
//
|
|
1233
|
-
// for (const item of reversedArr) {
|
|
1234
|
-
// yield item;
|
|
1235
|
-
// }
|
|
1236
|
-
// }
|
|
1237
|
-
|
|
1238
1138
|
/**
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1241
|
-
* @param
|
|
1242
|
-
*
|
|
1243
|
-
* types:
|
|
1244
|
-
* @returns The _isPredicate method is returning a boolean value indicating whether the
|
|
1245
|
-
* elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a
|
|
1246
|
-
* function, the method will return true, indicating that it is a predicate function.
|
|
1139
|
+
* (Protected) Get the previous node of a given node.
|
|
1140
|
+
* @remarks Time O(1), Space O(1)
|
|
1141
|
+
* @param node - A node in the list.
|
|
1142
|
+
* @returns Previous node or undefined.
|
|
1247
1143
|
*/
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
return typeof elementNodeOrPredicate === 'function';
|
|
1144
|
+
|
|
1145
|
+
protected _getPrevNode(node: DoublyLinkedListNode<E>): DoublyLinkedListNode<E> | undefined {
|
|
1146
|
+
return node.prev;
|
|
1252
1147
|
}
|
|
1253
1148
|
|
|
1254
1149
|
/**
|
|
1255
|
-
*
|
|
1256
|
-
* @
|
|
1257
|
-
*
|
|
1258
|
-
* @returns
|
|
1259
|
-
* as is. Otherwise, a new `DoublyLinkedListNode` instance will be created with the `elementOrNode`
|
|
1260
|
-
* value and returned.
|
|
1150
|
+
* (Protected) Create an empty instance of the same concrete class.
|
|
1151
|
+
* @remarks Time O(1), Space O(1)
|
|
1152
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1153
|
+
* @returns An empty like-kind list instance.
|
|
1261
1154
|
*/
|
|
1262
|
-
protected _ensureNode(elementOrNode: E | DoublyLinkedListNode<E>) {
|
|
1263
|
-
if (this.isNode(elementOrNode)) return elementOrNode;
|
|
1264
1155
|
|
|
1265
|
-
|
|
1156
|
+
protected override _createInstance(options?: LinearBaseOptions<E, R>): this {
|
|
1157
|
+
const Ctor = this.constructor as new (
|
|
1158
|
+
elements?: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>,
|
|
1159
|
+
options?: DoublyLinkedListOptions<E, R>
|
|
1160
|
+
) => this;
|
|
1161
|
+
return new Ctor([], options as DoublyLinkedListOptions<E, R> | undefined);
|
|
1266
1162
|
}
|
|
1267
1163
|
|
|
1268
1164
|
/**
|
|
1269
|
-
*
|
|
1270
|
-
*
|
|
1271
|
-
* @
|
|
1272
|
-
*
|
|
1273
|
-
*
|
|
1274
|
-
* @
|
|
1275
|
-
* returns
|
|
1165
|
+
* (Protected) Create a like-kind instance and seed it from an iterable.
|
|
1166
|
+
* @remarks Time O(N), Space O(N)
|
|
1167
|
+
* @template EM
|
|
1168
|
+
* @template RM
|
|
1169
|
+
* @param [elements] - Iterable used to seed the new list.
|
|
1170
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1171
|
+
* @returns A like-kind DoublyLinkedList instance.
|
|
1276
1172
|
*/
|
|
1277
|
-
protected _ensurePredicate(
|
|
1278
|
-
elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)
|
|
1279
|
-
) {
|
|
1280
|
-
if (this.isNode(elementNodeOrPredicate)) return (node: DoublyLinkedListNode<E>) => node === elementNodeOrPredicate;
|
|
1281
1173
|
|
|
1282
|
-
|
|
1174
|
+
protected _createLike<EM = E, RM = R>(
|
|
1175
|
+
elements: Iterable<EM> | Iterable<RM> | Iterable<DoublyLinkedListNode<EM>> = [],
|
|
1176
|
+
options?: DoublyLinkedListOptions<EM, RM>
|
|
1177
|
+
): DoublyLinkedList<EM, RM> {
|
|
1178
|
+
const Ctor = this.constructor as new (
|
|
1179
|
+
elements?: Iterable<EM> | Iterable<RM> | Iterable<DoublyLinkedListNode<EM>>,
|
|
1180
|
+
options?: DoublyLinkedListOptions<EM, RM>
|
|
1181
|
+
) => DoublyLinkedList<EM, RM>;
|
|
1182
|
+
return new Ctor(elements, options);
|
|
1183
|
+
}
|
|
1283
1184
|
|
|
1284
|
-
|
|
1185
|
+
protected *_getIterator(): IterableIterator<E> {
|
|
1186
|
+
let current = this.head;
|
|
1187
|
+
while (current) {
|
|
1188
|
+
yield current.value;
|
|
1189
|
+
current = current.next;
|
|
1190
|
+
}
|
|
1285
1191
|
}
|
|
1286
1192
|
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
* @returns An instance of the `DoublyLinkedList` class with an empty array and the provided options
|
|
1294
|
-
* is being returned, cast as the current class type.
|
|
1295
|
-
*/
|
|
1296
|
-
protected override _createInstance(options?: DoublyLinkedListOptions<E, R>): this {
|
|
1297
|
-
return new DoublyLinkedList<E, R>([], options) as this;
|
|
1193
|
+
protected *_getReverseIterator(): IterableIterator<E> {
|
|
1194
|
+
let current = this.tail;
|
|
1195
|
+
while (current) {
|
|
1196
|
+
yield current.value;
|
|
1197
|
+
current = current.prev;
|
|
1198
|
+
}
|
|
1298
1199
|
}
|
|
1299
1200
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
* linked list. If the input node has a previous node, it will return that node. Otherwise, it will
|
|
1307
|
-
* return `undefined`.
|
|
1308
|
-
*/
|
|
1309
|
-
protected _getPrevNode(node: DoublyLinkedListNode<E>): DoublyLinkedListNode<E> | undefined {
|
|
1310
|
-
return node.prev;
|
|
1201
|
+
protected *_getNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {
|
|
1202
|
+
let current = this.head;
|
|
1203
|
+
while (current) {
|
|
1204
|
+
yield current;
|
|
1205
|
+
current = current.next;
|
|
1206
|
+
}
|
|
1311
1207
|
}
|
|
1312
1208
|
}
|