undirected-graph-typed 2.0.5 → 2.1.0
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/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 +598 -869
- 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 +198 -216
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
- package/src/data-structures/binary-tree/avl-tree.ts +239 -206
- package/src/data-structures/binary-tree/binary-tree.ts +664 -893
- package/src/data-structures/binary-tree/bst.ts +568 -570
- package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
- package/src/data-structures/binary-tree/tree-counter.ts +199 -218
- package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
- 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
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* data-structure-typed
|
|
4
|
+
*
|
|
5
|
+
* @author Pablo Zeng
|
|
6
|
+
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
|
|
7
|
+
* @license MIT License
|
|
8
|
+
*/
|
|
2
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
10
|
exports.DoublyLinkedList = exports.DoublyLinkedListNode = void 0;
|
|
4
11
|
const linear_base_1 = require("../base/linear-base");
|
|
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
|
+
*/
|
|
5
17
|
class DoublyLinkedListNode extends linear_base_1.LinkedListNode {
|
|
6
18
|
/**
|
|
7
|
-
*
|
|
8
|
-
* @
|
|
9
|
-
*
|
|
19
|
+
* Create a node.
|
|
20
|
+
* @remarks Time O(1), Space O(1)
|
|
21
|
+
* @param value - Element value to store.
|
|
22
|
+
* @returns New node instance.
|
|
10
23
|
*/
|
|
11
24
|
constructor(value) {
|
|
12
25
|
super(value);
|
|
@@ -14,21 +27,47 @@ class DoublyLinkedListNode extends linear_base_1.LinkedListNode {
|
|
|
14
27
|
this._next = undefined;
|
|
15
28
|
this._prev = undefined;
|
|
16
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Get the next node link.
|
|
32
|
+
* @remarks Time O(1), Space O(1)
|
|
33
|
+
* @returns Next node or undefined.
|
|
34
|
+
*/
|
|
17
35
|
get next() {
|
|
18
36
|
return this._next;
|
|
19
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Set the next node link.
|
|
40
|
+
* @remarks Time O(1), Space O(1)
|
|
41
|
+
* @param value - Next node or undefined.
|
|
42
|
+
* @returns void
|
|
43
|
+
*/
|
|
20
44
|
set next(value) {
|
|
21
45
|
this._next = value;
|
|
22
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Get the previous node link.
|
|
49
|
+
* @remarks Time O(1), Space O(1)
|
|
50
|
+
* @returns Previous node or undefined.
|
|
51
|
+
*/
|
|
23
52
|
get prev() {
|
|
24
53
|
return this._prev;
|
|
25
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Set the previous node link.
|
|
57
|
+
* @remarks Time O(1), Space O(1)
|
|
58
|
+
* @param value - Previous node or undefined.
|
|
59
|
+
* @returns void
|
|
60
|
+
*/
|
|
26
61
|
set prev(value) {
|
|
27
62
|
this._prev = value;
|
|
28
63
|
}
|
|
29
64
|
}
|
|
30
65
|
exports.DoublyLinkedListNode = DoublyLinkedListNode;
|
|
31
66
|
/**
|
|
67
|
+
* Doubly linked list with O(1) push/pop/unshift/shift and linear scans.
|
|
68
|
+
* @remarks Time O(1), Space O(1)
|
|
69
|
+
* @template E
|
|
70
|
+
* @template R
|
|
32
71
|
* 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.
|
|
33
72
|
* 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.
|
|
34
73
|
* 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.
|
|
@@ -203,6 +242,16 @@ exports.DoublyLinkedListNode = DoublyLinkedListNode;
|
|
|
203
242
|
* this.map = new Map<K, DoublyLinkedListNode<CacheEntry<K, V>>>();
|
|
204
243
|
* }
|
|
205
244
|
*
|
|
245
|
+
* // Get the current cache length
|
|
246
|
+
* get length(): number {
|
|
247
|
+
* return this.list.length;
|
|
248
|
+
* }
|
|
249
|
+
*
|
|
250
|
+
* // Check if it is empty
|
|
251
|
+
* get isEmpty(): boolean {
|
|
252
|
+
* return this.list.isEmpty();
|
|
253
|
+
* }
|
|
254
|
+
*
|
|
206
255
|
* // Get cached value
|
|
207
256
|
* get(key: K): V | undefined {
|
|
208
257
|
* const node = this.map.get(key);
|
|
@@ -248,12 +297,6 @@ exports.DoublyLinkedListNode = DoublyLinkedListNode;
|
|
|
248
297
|
* }
|
|
249
298
|
* }
|
|
250
299
|
*
|
|
251
|
-
* // Move the node to the head of the linked list
|
|
252
|
-
* private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {
|
|
253
|
-
* this.list.delete(node);
|
|
254
|
-
* this.list.unshift(node.value);
|
|
255
|
-
* }
|
|
256
|
-
*
|
|
257
300
|
* // Delete specific key
|
|
258
301
|
* delete(key: K): boolean {
|
|
259
302
|
* const node = this.map.get(key);
|
|
@@ -273,14 +316,10 @@ exports.DoublyLinkedListNode = DoublyLinkedListNode;
|
|
|
273
316
|
* this.map.clear();
|
|
274
317
|
* }
|
|
275
318
|
*
|
|
276
|
-
* //
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
* // Check if it is empty
|
|
282
|
-
* get isEmpty(): boolean {
|
|
283
|
-
* return this.list.isEmpty();
|
|
319
|
+
* // Move the node to the head of the linked list
|
|
320
|
+
* private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {
|
|
321
|
+
* this.list.delete(node);
|
|
322
|
+
* this.list.unshift(node.value);
|
|
284
323
|
* }
|
|
285
324
|
* }
|
|
286
325
|
*
|
|
@@ -463,95 +502,92 @@ exports.DoublyLinkedListNode = DoublyLinkedListNode;
|
|
|
463
502
|
*/
|
|
464
503
|
class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
465
504
|
/**
|
|
466
|
-
*
|
|
467
|
-
* @
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
* @param [options] - The `options` parameter in the constructor is of type
|
|
472
|
-
* `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional
|
|
473
|
-
* configuration options to customize the behavior of the DoublyLinkedList.
|
|
505
|
+
* Create a DoublyLinkedList and optionally bulk-insert elements.
|
|
506
|
+
* @remarks Time O(N), Space O(N)
|
|
507
|
+
* @param [elements] - Iterable of elements or nodes (or raw records if toElementFn is provided).
|
|
508
|
+
* @param [options] - Options such as maxLen and toElementFn.
|
|
509
|
+
* @returns New DoublyLinkedList instance.
|
|
474
510
|
*/
|
|
475
511
|
constructor(elements = [], options) {
|
|
476
512
|
super(options);
|
|
513
|
+
this._equals = Object.is;
|
|
514
|
+
this._length = 0;
|
|
477
515
|
this._head = undefined;
|
|
478
516
|
this._tail = undefined;
|
|
479
517
|
this._length = 0;
|
|
480
|
-
if (options) {
|
|
481
|
-
|
|
482
|
-
if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0)
|
|
483
|
-
this._maxLen = maxLen;
|
|
518
|
+
if ((options === null || options === void 0 ? void 0 : options.maxLen) && Number.isInteger(options.maxLen) && options.maxLen > 0) {
|
|
519
|
+
this._maxLen = options.maxLen;
|
|
484
520
|
}
|
|
485
521
|
this.pushMany(elements);
|
|
486
522
|
}
|
|
523
|
+
/**
|
|
524
|
+
* Get the head node.
|
|
525
|
+
* @remarks Time O(1), Space O(1)
|
|
526
|
+
* @returns Head node or undefined.
|
|
527
|
+
*/
|
|
487
528
|
get head() {
|
|
488
529
|
return this._head;
|
|
489
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* Get the tail node.
|
|
533
|
+
* @remarks Time O(1), Space O(1)
|
|
534
|
+
* @returns Tail node or undefined.
|
|
535
|
+
*/
|
|
490
536
|
get tail() {
|
|
491
537
|
return this._tail;
|
|
492
538
|
}
|
|
539
|
+
/**
|
|
540
|
+
* Get the number of elements.
|
|
541
|
+
* @remarks Time O(1), Space O(1)
|
|
542
|
+
* @returns Current length.
|
|
543
|
+
*/
|
|
493
544
|
get length() {
|
|
494
545
|
return this._length;
|
|
495
546
|
}
|
|
496
547
|
/**
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
*
|
|
500
|
-
* The `get first` function returns the first node in a doubly linked list, or undefined if the list is empty.
|
|
501
|
-
* @returns The method `get first()` returns the first node of the doubly linked list, or `undefined` if the list is empty.
|
|
548
|
+
* Get the first element value.
|
|
549
|
+
* @remarks Time O(1), Space O(1)
|
|
550
|
+
* @returns First element or undefined.
|
|
502
551
|
*/
|
|
503
552
|
get first() {
|
|
504
553
|
var _a;
|
|
505
554
|
return (_a = this.head) === null || _a === void 0 ? void 0 : _a.value;
|
|
506
555
|
}
|
|
507
556
|
/**
|
|
508
|
-
*
|
|
509
|
-
*
|
|
510
|
-
*
|
|
511
|
-
* The `get last` function returns the last node in a doubly linked list, or undefined if the list is empty.
|
|
512
|
-
* @returns The method `get last()` returns the last node of the doubly linked list, or `undefined` if the list is empty.
|
|
557
|
+
* Get the last element value.
|
|
558
|
+
* @remarks Time O(1), Space O(1)
|
|
559
|
+
* @returns Last element or undefined.
|
|
513
560
|
*/
|
|
514
561
|
get last() {
|
|
515
562
|
var _a;
|
|
516
563
|
return (_a = this.tail) === null || _a === void 0 ? void 0 : _a.value;
|
|
517
564
|
}
|
|
518
565
|
/**
|
|
519
|
-
*
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
*
|
|
523
|
-
*
|
|
524
|
-
* @param
|
|
525
|
-
* @returns
|
|
566
|
+
* Create a new list from an array of elements.
|
|
567
|
+
* @remarks Time O(N), Space O(N)
|
|
568
|
+
* @template E
|
|
569
|
+
* @template R
|
|
570
|
+
* @param this - The constructor (subclass) to instantiate.
|
|
571
|
+
* @param data - Array of elements to insert.
|
|
572
|
+
* @returns A new list populated with the array's elements.
|
|
526
573
|
*/
|
|
527
574
|
static fromArray(data) {
|
|
528
|
-
return new
|
|
575
|
+
return new this(data);
|
|
529
576
|
}
|
|
530
577
|
/**
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
* `DoublyLinkedListNode`.
|
|
536
|
-
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
537
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can
|
|
538
|
-
* be one of the following types:
|
|
539
|
-
* @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an
|
|
540
|
-
* instance of `DoublyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the
|
|
541
|
-
* parameter is a `DoublyLinkedListNode<E>`. If it is not an instance of `DoublyLinkedListNode<E>`,
|
|
542
|
-
* the function returns `false`.
|
|
578
|
+
* Type guard: check whether the input is a DoublyLinkedListNode.
|
|
579
|
+
* @remarks Time O(1), Space O(1)
|
|
580
|
+
* @param elementNodeOrPredicate - Element, node, or predicate.
|
|
581
|
+
* @returns True if the value is a DoublyLinkedListNode.
|
|
543
582
|
*/
|
|
544
583
|
isNode(elementNodeOrPredicate) {
|
|
545
584
|
return elementNodeOrPredicate instanceof DoublyLinkedListNode;
|
|
546
585
|
}
|
|
547
586
|
/**
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
* @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`
|
|
553
|
-
* method can accept either an element of type `E` or a `DoublyLinkedListNode<E>` object.
|
|
554
|
-
* @returns The `push` method is returning a boolean value, specifically `true`.
|
|
587
|
+
* Append an element/node to the tail.
|
|
588
|
+
* @remarks Time O(1), Space O(1)
|
|
589
|
+
* @param elementOrNode - Element or node to append.
|
|
590
|
+
* @returns True when appended.
|
|
555
591
|
*/
|
|
556
592
|
push(elementOrNode) {
|
|
557
593
|
const newNode = this._ensureNode(elementOrNode);
|
|
@@ -570,58 +606,50 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
570
606
|
return true;
|
|
571
607
|
}
|
|
572
608
|
/**
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
* The `pop()` function removes and returns the value of the last element in a linked list.
|
|
577
|
-
* @returns The method is returning the value of the removed node.
|
|
609
|
+
* Remove and return the tail element.
|
|
610
|
+
* @remarks Time O(1), Space O(1)
|
|
611
|
+
* @returns Removed element or undefined.
|
|
578
612
|
*/
|
|
579
613
|
pop() {
|
|
580
614
|
if (!this.tail)
|
|
581
615
|
return undefined;
|
|
582
|
-
const
|
|
616
|
+
const removed = this.tail;
|
|
583
617
|
if (this.head === this.tail) {
|
|
584
618
|
this._head = undefined;
|
|
585
619
|
this._tail = undefined;
|
|
586
620
|
}
|
|
587
621
|
else {
|
|
588
|
-
this._tail =
|
|
622
|
+
this._tail = removed.prev;
|
|
589
623
|
this.tail.next = undefined;
|
|
590
624
|
}
|
|
591
625
|
this._length--;
|
|
592
|
-
return
|
|
626
|
+
return removed.value;
|
|
593
627
|
}
|
|
594
628
|
/**
|
|
595
|
-
*
|
|
596
|
-
*
|
|
597
|
-
*
|
|
598
|
-
* The `shift()` function removes and returns the value of the first element in a doubly linked list.
|
|
599
|
-
* @returns The value of the removed node.
|
|
629
|
+
* Remove and return the head element.
|
|
630
|
+
* @remarks Time O(1), Space O(1)
|
|
631
|
+
* @returns Removed element or undefined.
|
|
600
632
|
*/
|
|
601
633
|
shift() {
|
|
602
634
|
if (!this.head)
|
|
603
635
|
return undefined;
|
|
604
|
-
const
|
|
636
|
+
const removed = this.head;
|
|
605
637
|
if (this.head === this.tail) {
|
|
606
638
|
this._head = undefined;
|
|
607
639
|
this._tail = undefined;
|
|
608
640
|
}
|
|
609
641
|
else {
|
|
610
|
-
this._head =
|
|
642
|
+
this._head = removed.next;
|
|
611
643
|
this.head.prev = undefined;
|
|
612
644
|
}
|
|
613
645
|
this._length--;
|
|
614
|
-
return
|
|
646
|
+
return removed.value;
|
|
615
647
|
}
|
|
616
648
|
/**
|
|
617
|
-
*
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
*
|
|
621
|
-
* @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the
|
|
622
|
-
* `unshift` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an
|
|
623
|
-
* element of type `E`.
|
|
624
|
-
* @returns The `unshift` method is returning a boolean value, specifically `true`.
|
|
649
|
+
* Prepend an element/node to the head.
|
|
650
|
+
* @remarks Time O(1), Space O(1)
|
|
651
|
+
* @param elementOrNode - Element or node to prepend.
|
|
652
|
+
* @returns True when prepended.
|
|
625
653
|
*/
|
|
626
654
|
unshift(elementOrNode) {
|
|
627
655
|
const newNode = this._ensureNode(elementOrNode);
|
|
@@ -640,151 +668,114 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
640
668
|
return true;
|
|
641
669
|
}
|
|
642
670
|
/**
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
* transformation function if provided.
|
|
648
|
-
* @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`
|
|
649
|
-
* parameter in the `pushMany` function can accept an iterable containing elements of type `E`, `R`,
|
|
650
|
-
* or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and pushes
|
|
651
|
-
* it onto the linked list. If a transformation function `to
|
|
652
|
-
* @returns The `pushMany` function is returning an array of boolean values (`ans`) which indicate
|
|
653
|
-
* the success or failure of pushing each element into the data structure.
|
|
671
|
+
* Append a sequence of elements/nodes.
|
|
672
|
+
* @remarks Time O(N), Space O(1)
|
|
673
|
+
* @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
|
|
674
|
+
* @returns Array of per-element success flags.
|
|
654
675
|
*/
|
|
655
676
|
pushMany(elements) {
|
|
656
677
|
const ans = [];
|
|
657
678
|
for (const el of elements) {
|
|
658
|
-
if (this.toElementFn)
|
|
679
|
+
if (this.toElementFn)
|
|
659
680
|
ans.push(this.push(this.toElementFn(el)));
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
ans.push(this.push(el));
|
|
681
|
+
else
|
|
682
|
+
ans.push(this.push(el));
|
|
663
683
|
}
|
|
664
684
|
return ans;
|
|
665
685
|
}
|
|
666
686
|
/**
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
*
|
|
671
|
-
* beginning of a Doubly Linked List, returning an array of boolean values indicating the success of
|
|
672
|
-
* each insertion.
|
|
673
|
-
* @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`
|
|
674
|
-
* parameter in the `unshiftMany` function can accept an iterable containing elements of type `E`,
|
|
675
|
-
* `R`, or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and
|
|
676
|
-
* performs an `unshift` operation on the doubly linked list
|
|
677
|
-
* @returns The `unshiftMany` function returns an array of boolean values indicating the success of
|
|
678
|
-
* each unshift operation performed on the elements passed as input.
|
|
687
|
+
* Prepend a sequence of elements/nodes.
|
|
688
|
+
* @remarks Time O(N), Space O(1)
|
|
689
|
+
* @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
|
|
690
|
+
* @returns Array of per-element success flags.
|
|
679
691
|
*/
|
|
680
692
|
unshiftMany(elements) {
|
|
681
693
|
const ans = [];
|
|
682
694
|
for (const el of elements) {
|
|
683
|
-
if (this.toElementFn)
|
|
695
|
+
if (this.toElementFn)
|
|
684
696
|
ans.push(this.unshift(this.toElementFn(el)));
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
ans.push(this.unshift(el));
|
|
697
|
+
else
|
|
698
|
+
ans.push(this.unshift(el));
|
|
688
699
|
}
|
|
689
700
|
return ans;
|
|
690
701
|
}
|
|
691
702
|
/**
|
|
692
|
-
*
|
|
693
|
-
*
|
|
694
|
-
*
|
|
695
|
-
*
|
|
696
|
-
* @param {number} index - The index parameter is a number that represents the position of the element we want to
|
|
697
|
-
* retrieve from the list.
|
|
698
|
-
* @returns The method is returning the value at the specified index in the linked list. If the index is out of bounds
|
|
699
|
-
* or the linked list is empty, it will return undefined.
|
|
703
|
+
* Get the element at a given index.
|
|
704
|
+
* @remarks Time O(N), Space O(1)
|
|
705
|
+
* @param index - Zero-based index.
|
|
706
|
+
* @returns Element or undefined.
|
|
700
707
|
*/
|
|
701
708
|
at(index) {
|
|
702
709
|
if (index < 0 || index >= this._length)
|
|
703
710
|
return undefined;
|
|
704
711
|
let current = this.head;
|
|
705
|
-
for (let i = 0; i < index; i++)
|
|
712
|
+
for (let i = 0; i < index; i++)
|
|
706
713
|
current = current.next;
|
|
707
|
-
}
|
|
708
714
|
return current.value;
|
|
709
715
|
}
|
|
710
716
|
/**
|
|
711
|
-
*
|
|
712
|
-
*
|
|
713
|
-
*
|
|
714
|
-
*
|
|
715
|
-
* range.
|
|
716
|
-
* @param {number} index - The `index` parameter is a number that represents the position of the node we want to
|
|
717
|
-
* retrieve from the doubly linked list. It indicates the zero-based index of the node we want to access.
|
|
718
|
-
* @returns The method `getNodeAt(index: number)` returns a `DoublyLinkedListNode<E>` object if the index is within the
|
|
719
|
-
* valid range of the linked list, otherwise it returns `undefined`.
|
|
717
|
+
* Get the node reference at a given index.
|
|
718
|
+
* @remarks Time O(N), Space O(1)
|
|
719
|
+
* @param index - Zero-based index.
|
|
720
|
+
* @returns Node or undefined.
|
|
720
721
|
*/
|
|
721
722
|
getNodeAt(index) {
|
|
722
723
|
if (index < 0 || index >= this._length)
|
|
723
724
|
return undefined;
|
|
724
725
|
let current = this.head;
|
|
725
|
-
for (let i = 0; i < index; i++)
|
|
726
|
+
for (let i = 0; i < index; i++)
|
|
726
727
|
current = current.next;
|
|
727
|
-
}
|
|
728
728
|
return current;
|
|
729
729
|
}
|
|
730
730
|
/**
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
* or predicate.
|
|
736
|
-
* @param {| E
|
|
737
|
-
* | DoublyLinkedListNode<E>
|
|
738
|
-
* | ((node: DoublyLinkedListNode<E>) => boolean)
|
|
739
|
-
* | undefined} elementNodeOrPredicate - The `getNode` method you provided is used to find a
|
|
740
|
-
* node in a doubly linked list based on a given element, node, or predicate function. The
|
|
741
|
-
* `elementNodeOrPredicate` parameter can be one of the following:
|
|
742
|
-
* @returns The `getNode` method returns a `DoublyLinkedListNode<E>` or `undefined` based on the
|
|
743
|
-
* input `elementNodeOrPredicate`. If the input is `undefined`, the method returns `undefined`.
|
|
744
|
-
* Otherwise, it iterates through the linked list starting from the head node and applies the
|
|
745
|
-
* provided predicate function to each node. If a node satisfies the predicate, that node is
|
|
746
|
-
* returned. If
|
|
731
|
+
* Find a node by value, reference, or predicate.
|
|
732
|
+
* @remarks Time O(N), Space O(1)
|
|
733
|
+
* @param [elementNodeOrPredicate] - Element, node, or predicate to match.
|
|
734
|
+
* @returns Matching node or undefined.
|
|
747
735
|
*/
|
|
748
736
|
getNode(elementNodeOrPredicate) {
|
|
749
737
|
if (elementNodeOrPredicate === undefined)
|
|
750
738
|
return;
|
|
751
|
-
if (this.isNode(elementNodeOrPredicate))
|
|
752
|
-
|
|
739
|
+
if (this.isNode(elementNodeOrPredicate)) {
|
|
740
|
+
const target = elementNodeOrPredicate;
|
|
741
|
+
let cur = this.head;
|
|
742
|
+
while (cur) {
|
|
743
|
+
if (cur === target)
|
|
744
|
+
return target;
|
|
745
|
+
cur = cur.next;
|
|
746
|
+
}
|
|
747
|
+
const isMatch = (node) => this._equals(node.value, target.value);
|
|
748
|
+
cur = this.head;
|
|
749
|
+
while (cur) {
|
|
750
|
+
if (isMatch(cur))
|
|
751
|
+
return cur;
|
|
752
|
+
cur = cur.next;
|
|
753
|
+
}
|
|
754
|
+
return undefined;
|
|
755
|
+
}
|
|
753
756
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
754
757
|
let current = this.head;
|
|
755
758
|
while (current) {
|
|
756
|
-
if (predicate(current))
|
|
759
|
+
if (predicate(current))
|
|
757
760
|
return current;
|
|
758
|
-
}
|
|
759
761
|
current = current.next;
|
|
760
762
|
}
|
|
761
763
|
return undefined;
|
|
762
764
|
}
|
|
763
765
|
/**
|
|
764
|
-
*
|
|
765
|
-
*
|
|
766
|
-
*
|
|
767
|
-
*
|
|
768
|
-
* @
|
|
769
|
-
* which you want to add a new element or node in the doubly linked list. It indicates the location
|
|
770
|
-
* where the new element or node should be inserted.
|
|
771
|
-
* @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
|
|
772
|
-
* `addAt` method can be either a value of type `E` or a `DoublyLinkedListNode<E>` object.
|
|
773
|
-
* @returns The `addAt` method returns a boolean value. It returns `true` if the element or node was
|
|
774
|
-
* successfully added at the specified index, and `false` if the index is out of bounds (less than 0
|
|
775
|
-
* or greater than the length of the list).
|
|
766
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
767
|
+
* @remarks Time O(N), Space O(1)
|
|
768
|
+
* @param index - Zero-based index.
|
|
769
|
+
* @param newElementOrNode - Element or node to insert.
|
|
770
|
+
* @returns True if inserted.
|
|
776
771
|
*/
|
|
777
772
|
addAt(index, newElementOrNode) {
|
|
778
773
|
if (index < 0 || index > this._length)
|
|
779
774
|
return false;
|
|
780
|
-
if (index === 0)
|
|
781
|
-
this.unshift(newElementOrNode);
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
if (index === this._length) {
|
|
785
|
-
this.push(newElementOrNode);
|
|
786
|
-
return true;
|
|
787
|
-
}
|
|
775
|
+
if (index === 0)
|
|
776
|
+
return this.unshift(newElementOrNode);
|
|
777
|
+
if (index === this._length)
|
|
778
|
+
return this.push(newElementOrNode);
|
|
788
779
|
const newNode = this._ensureNode(newElementOrNode);
|
|
789
780
|
const prevNode = this.getNodeAt(index - 1);
|
|
790
781
|
const nextNode = prevNode.next;
|
|
@@ -796,179 +787,123 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
796
787
|
return true;
|
|
797
788
|
}
|
|
798
789
|
/**
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
*
|
|
803
|
-
*
|
|
804
|
-
* @param {E | DoublyLinkedListNode<E>} existingElementOrNode - The `existingElementOrNode` parameter
|
|
805
|
-
* in the `addBefore` method can be either an element of type `E` or a `DoublyLinkedListNode<E>`.
|
|
806
|
-
* @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter
|
|
807
|
-
* represents the element or node that you want to add before the `existingElementOrNode` in a doubly
|
|
808
|
-
* linked list.
|
|
809
|
-
* @returns The `addBefore` method returns a boolean value - `true` if the new element or node was
|
|
810
|
-
* successfully added before the existing element or node, and `false` if the existing element or
|
|
811
|
-
* node was not found.
|
|
790
|
+
* Insert a new element/node before an existing one.
|
|
791
|
+
* @remarks Time O(N), Space O(1)
|
|
792
|
+
* @param existingElementOrNode - Existing element or node.
|
|
793
|
+
* @param newElementOrNode - Element or node to insert.
|
|
794
|
+
* @returns True if inserted.
|
|
812
795
|
*/
|
|
813
796
|
addBefore(existingElementOrNode, newElementOrNode) {
|
|
814
797
|
const existingNode = this.isNode(existingElementOrNode)
|
|
815
798
|
? existingElementOrNode
|
|
816
799
|
: this.getNode(existingElementOrNode);
|
|
817
|
-
if (existingNode)
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
return true;
|
|
830
|
-
}
|
|
831
|
-
return false;
|
|
800
|
+
if (!existingNode)
|
|
801
|
+
return false;
|
|
802
|
+
const newNode = this._ensureNode(newElementOrNode);
|
|
803
|
+
newNode.prev = existingNode.prev;
|
|
804
|
+
if (existingNode.prev)
|
|
805
|
+
existingNode.prev.next = newNode;
|
|
806
|
+
newNode.next = existingNode;
|
|
807
|
+
existingNode.prev = newNode;
|
|
808
|
+
if (existingNode === this.head)
|
|
809
|
+
this._head = newNode;
|
|
810
|
+
this._length++;
|
|
811
|
+
return true;
|
|
832
812
|
}
|
|
833
813
|
/**
|
|
834
|
-
*
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
839
|
-
* @param {E | DoublyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the
|
|
840
|
-
* element or node in the doubly linked list after which you want to add a new element or node.
|
|
841
|
-
* @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
|
|
842
|
-
* `addAfter` method represents the element or node that you want to add after the existing element
|
|
843
|
-
* or node in a doubly linked list. This parameter can be either an element value or a
|
|
844
|
-
* `DoublyLinkedListNode` object that you want to insert
|
|
845
|
-
* @returns The `addAfter` method returns a boolean value - `true` if the new element or node was
|
|
846
|
-
* successfully added after the existing element or node, and `false` if the existing element or node
|
|
847
|
-
* was not found in the linked list.
|
|
814
|
+
* Insert a new element/node after an existing one.
|
|
815
|
+
* @remarks Time O(N), Space O(1)
|
|
816
|
+
* @param existingElementOrNode - Existing element or node.
|
|
817
|
+
* @param newElementOrNode - Element or node to insert.
|
|
818
|
+
* @returns True if inserted.
|
|
848
819
|
*/
|
|
849
820
|
addAfter(existingElementOrNode, newElementOrNode) {
|
|
850
821
|
const existingNode = this.isNode(existingElementOrNode)
|
|
851
822
|
? existingElementOrNode
|
|
852
823
|
: this.getNode(existingElementOrNode);
|
|
853
|
-
if (existingNode)
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
return true;
|
|
866
|
-
}
|
|
867
|
-
return false;
|
|
824
|
+
if (!existingNode)
|
|
825
|
+
return false;
|
|
826
|
+
const newNode = this._ensureNode(newElementOrNode);
|
|
827
|
+
newNode.next = existingNode.next;
|
|
828
|
+
if (existingNode.next)
|
|
829
|
+
existingNode.next.prev = newNode;
|
|
830
|
+
newNode.prev = existingNode;
|
|
831
|
+
existingNode.next = newNode;
|
|
832
|
+
if (existingNode === this.tail)
|
|
833
|
+
this._tail = newNode;
|
|
834
|
+
this._length++;
|
|
835
|
+
return true;
|
|
868
836
|
}
|
|
869
837
|
/**
|
|
870
|
-
*
|
|
871
|
-
*
|
|
872
|
-
*
|
|
873
|
-
*
|
|
874
|
-
*
|
|
875
|
-
* @param {number} index - The `index` parameter in the `setAt` method refers to the position in the
|
|
876
|
-
* data structure where you want to set a new value.
|
|
877
|
-
* @param {E} value - The `value` parameter in the `setAt` method represents the new value that you
|
|
878
|
-
* want to set at the specified index in the data structure.
|
|
879
|
-
* @returns The `setAt` method returns a boolean value - `true` if the value at the specified index
|
|
880
|
-
* is successfully updated, and `false` if the index is out of bounds.
|
|
838
|
+
* Set the element value at an index.
|
|
839
|
+
* @remarks Time O(N), Space O(1)
|
|
840
|
+
* @param index - Zero-based index.
|
|
841
|
+
* @param value - New value.
|
|
842
|
+
* @returns True if updated.
|
|
881
843
|
*/
|
|
882
844
|
setAt(index, value) {
|
|
883
845
|
const node = this.getNodeAt(index);
|
|
884
|
-
if (node)
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
return false;
|
|
846
|
+
if (!node)
|
|
847
|
+
return false;
|
|
848
|
+
node.value = value;
|
|
849
|
+
return true;
|
|
889
850
|
}
|
|
890
851
|
/**
|
|
891
|
-
*
|
|
892
|
-
*
|
|
893
|
-
*
|
|
894
|
-
*
|
|
895
|
-
* @param {number} index - The index parameter represents the position of the element that needs to be deleted in the
|
|
896
|
-
* data structure. It is of type number.
|
|
897
|
-
* @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of
|
|
898
|
-
* bounds.
|
|
852
|
+
* Delete the element at an index.
|
|
853
|
+
* @remarks Time O(N), Space O(1)
|
|
854
|
+
* @param index - Zero-based index.
|
|
855
|
+
* @returns Removed element or undefined.
|
|
899
856
|
*/
|
|
900
857
|
deleteAt(index) {
|
|
901
858
|
if (index < 0 || index >= this._length)
|
|
902
859
|
return;
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
this.
|
|
907
|
-
return deleted;
|
|
908
|
-
}
|
|
909
|
-
if (index === this._length - 1) {
|
|
910
|
-
deleted = this.last;
|
|
911
|
-
this.pop();
|
|
912
|
-
return deleted;
|
|
913
|
-
}
|
|
860
|
+
if (index === 0)
|
|
861
|
+
return this.shift();
|
|
862
|
+
if (index === this._length - 1)
|
|
863
|
+
return this.pop();
|
|
914
864
|
const removedNode = this.getNodeAt(index);
|
|
915
865
|
const prevNode = removedNode.prev;
|
|
916
866
|
const nextNode = removedNode.next;
|
|
917
867
|
prevNode.next = nextNode;
|
|
918
868
|
nextNode.prev = prevNode;
|
|
919
869
|
this._length--;
|
|
920
|
-
return removedNode
|
|
870
|
+
return removedNode.value;
|
|
921
871
|
}
|
|
922
872
|
/**
|
|
923
|
-
*
|
|
924
|
-
*
|
|
925
|
-
*
|
|
926
|
-
*
|
|
927
|
-
* @param {E | DoublyLinkedListNode<E> | undefined} elementOrNode - The `elementOrNode` parameter in
|
|
928
|
-
* the `delete` method can accept an element of type `E`, a `DoublyLinkedListNode` of type `E`, or it
|
|
929
|
-
* can be `undefined`. This parameter is used to identify the node that needs to be deleted from the
|
|
930
|
-
* doubly linked list
|
|
931
|
-
* @returns The `delete` method returns a boolean value - `true` if the element or node was
|
|
932
|
-
* successfully deleted from the doubly linked list, and `false` if the element or node was not found
|
|
933
|
-
* in the list.
|
|
873
|
+
* Delete the first match by value/node.
|
|
874
|
+
* @remarks Time O(N), Space O(1)
|
|
875
|
+
* @param [elementOrNode] - Element or node to remove.
|
|
876
|
+
* @returns True if removed.
|
|
934
877
|
*/
|
|
935
878
|
delete(elementOrNode) {
|
|
936
879
|
const node = this.getNode(elementOrNode);
|
|
937
|
-
if (node)
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
if (nextNode)
|
|
950
|
-
nextNode.prev = prevNode;
|
|
951
|
-
this._length--;
|
|
952
|
-
}
|
|
953
|
-
return true;
|
|
880
|
+
if (!node)
|
|
881
|
+
return false;
|
|
882
|
+
if (node === this.head)
|
|
883
|
+
this.shift();
|
|
884
|
+
else if (node === this.tail)
|
|
885
|
+
this.pop();
|
|
886
|
+
else {
|
|
887
|
+
const prevNode = node.prev;
|
|
888
|
+
const nextNode = node.next;
|
|
889
|
+
prevNode.next = nextNode;
|
|
890
|
+
nextNode.prev = prevNode;
|
|
891
|
+
this._length--;
|
|
954
892
|
}
|
|
955
|
-
return
|
|
893
|
+
return true;
|
|
956
894
|
}
|
|
957
895
|
/**
|
|
958
|
-
*
|
|
959
|
-
*
|
|
960
|
-
*
|
|
961
|
-
* The function checks if a variable has a length greater than zero and returns a boolean value.
|
|
962
|
-
* @returns A boolean value is being returned.
|
|
896
|
+
* Check whether the list is empty.
|
|
897
|
+
* @remarks Time O(1), Space O(1)
|
|
898
|
+
* @returns True if length is 0.
|
|
963
899
|
*/
|
|
964
900
|
isEmpty() {
|
|
965
901
|
return this._length === 0;
|
|
966
902
|
}
|
|
967
903
|
/**
|
|
968
|
-
*
|
|
969
|
-
*
|
|
970
|
-
*
|
|
971
|
-
* The `clear` function resets the linked list by setting the head, tail, and length to undefined and 0 respectively.
|
|
904
|
+
* Remove all nodes and reset length.
|
|
905
|
+
* @remarks Time O(N), Space O(1)
|
|
906
|
+
* @returns void
|
|
972
907
|
*/
|
|
973
908
|
clear() {
|
|
974
909
|
this._head = undefined;
|
|
@@ -976,16 +911,10 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
976
911
|
this._length = 0;
|
|
977
912
|
}
|
|
978
913
|
/**
|
|
979
|
-
*
|
|
980
|
-
*
|
|
981
|
-
*
|
|
982
|
-
*
|
|
983
|
-
* node or predicate.
|
|
984
|
-
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
985
|
-
* elementNodeOrPredicate - The `get` method takes in a parameter called `elementNodeOrPredicate`,
|
|
986
|
-
* which can be one of the following types:
|
|
987
|
-
* @returns The `get` method returns the value of the first node in the doubly linked list that
|
|
988
|
-
* satisfies the provided predicate function. If no such node is found, it returns `undefined`.
|
|
914
|
+
* Find the first value matching a predicate scanning forward.
|
|
915
|
+
* @remarks Time O(N), Space O(1)
|
|
916
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
917
|
+
* @returns Matched value or undefined.
|
|
989
918
|
*/
|
|
990
919
|
search(elementNodeOrPredicate) {
|
|
991
920
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
@@ -998,17 +927,10 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
998
927
|
return undefined;
|
|
999
928
|
}
|
|
1000
929
|
/**
|
|
1001
|
-
*
|
|
1002
|
-
*
|
|
1003
|
-
*
|
|
1004
|
-
*
|
|
1005
|
-
* the tail and moving backwards.
|
|
1006
|
-
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
1007
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getBackward`
|
|
1008
|
-
* function can be one of the following types:
|
|
1009
|
-
* @returns The `getBackward` method returns the value of the element node that matches the provided
|
|
1010
|
-
* predicate when traversing the doubly linked list backwards. If no matching element is found, it
|
|
1011
|
-
* returns `undefined`.
|
|
930
|
+
* Find the first value matching a predicate scanning backward.
|
|
931
|
+
* @remarks Time O(N), Space O(1)
|
|
932
|
+
* @param elementNodeOrPredicate - Element, node, or predicate to match.
|
|
933
|
+
* @returns Matched value or undefined.
|
|
1012
934
|
*/
|
|
1013
935
|
getBackward(elementNodeOrPredicate) {
|
|
1014
936
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
@@ -1021,10 +943,9 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
1021
943
|
return undefined;
|
|
1022
944
|
}
|
|
1023
945
|
/**
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
1026
|
-
*
|
|
1027
|
-
* The `reverse` function reverses the order of the elements in a doubly linked list.
|
|
946
|
+
* Reverse the list in place.
|
|
947
|
+
* @remarks Time O(N), Space O(1)
|
|
948
|
+
* @returns This list.
|
|
1028
949
|
*/
|
|
1029
950
|
reverse() {
|
|
1030
951
|
let current = this.head;
|
|
@@ -1037,100 +958,134 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
1037
958
|
return this;
|
|
1038
959
|
}
|
|
1039
960
|
/**
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
1043
|
-
*
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
961
|
+
* Set the equality comparator used to compare values.
|
|
962
|
+
* @remarks Time O(1), Space O(1)
|
|
963
|
+
* @param equals - Equality predicate (a, b) → boolean.
|
|
964
|
+
* @returns This list.
|
|
965
|
+
*/
|
|
966
|
+
setEquality(equals) {
|
|
967
|
+
this._equals = equals;
|
|
968
|
+
return this;
|
|
969
|
+
}
|
|
970
|
+
/**
|
|
971
|
+
* Deep clone this list (values are copied by reference).
|
|
972
|
+
* @remarks Time O(N), Space O(N)
|
|
973
|
+
* @returns A new list with the same element sequence.
|
|
1047
974
|
*/
|
|
1048
975
|
clone() {
|
|
1049
|
-
|
|
976
|
+
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
977
|
+
for (const v of this)
|
|
978
|
+
out.push(v);
|
|
979
|
+
return out;
|
|
1050
980
|
}
|
|
1051
981
|
/**
|
|
1052
|
-
*
|
|
1053
|
-
*
|
|
1054
|
-
*
|
|
1055
|
-
*
|
|
1056
|
-
*
|
|
1057
|
-
* callback function returns true.
|
|
1058
|
-
* @param callback - The `callback` parameter is a function that will be called for each element in
|
|
1059
|
-
* the DoublyLinkedList. It takes three arguments: the current element, the index of the current
|
|
1060
|
-
* element, and the DoublyLinkedList itself. The callback function should return a boolean value
|
|
1061
|
-
* indicating whether the current element should be included
|
|
1062
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
1063
|
-
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
|
1064
|
-
* passed as the `this` value to the `callback` function. If `thisArg` is
|
|
1065
|
-
* @returns The `filter` method is returning a new `DoublyLinkedList` object that contains the
|
|
1066
|
-
* elements that pass the filter condition specified by the `callback` function.
|
|
982
|
+
* Filter values into a new list of the same class.
|
|
983
|
+
* @remarks Time O(N), Space O(N)
|
|
984
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
985
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
986
|
+
* @returns A new list with kept values.
|
|
1067
987
|
*/
|
|
1068
988
|
filter(callback, thisArg) {
|
|
1069
|
-
const
|
|
989
|
+
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1070
990
|
let index = 0;
|
|
1071
|
-
for (const
|
|
1072
|
-
if (callback.call(thisArg,
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
index++;
|
|
1076
|
-
}
|
|
1077
|
-
return filteredList;
|
|
991
|
+
for (const v of this)
|
|
992
|
+
if (callback.call(thisArg, v, index++, this))
|
|
993
|
+
out.push(v);
|
|
994
|
+
return out;
|
|
1078
995
|
}
|
|
1079
996
|
/**
|
|
1080
|
-
*
|
|
1081
|
-
*
|
|
1082
|
-
*
|
|
1083
|
-
*
|
|
1084
|
-
*
|
|
1085
|
-
* @param callback - The callback parameter is a function that will be called for each element in the
|
|
1086
|
-
* original DoublyLinkedList. It takes three arguments: current (the current element being
|
|
1087
|
-
* processed), index (the index of the current element), and this (the original DoublyLinkedList).
|
|
1088
|
-
* The callback function should return a value of type
|
|
1089
|
-
* @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to
|
|
1090
|
-
* convert the raw element (`RR`) to the desired element type (`T`). It takes the raw element as
|
|
1091
|
-
* input and returns the converted element. If this parameter is not provided, the raw element will
|
|
1092
|
-
* be used as is.
|
|
1093
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
1094
|
-
* specify the value of `this` within the callback function. It is used to set the context or scope
|
|
1095
|
-
* in which the callback function will be executed. If `thisArg` is provided, it will be used as the
|
|
1096
|
-
* value of
|
|
1097
|
-
* @returns a new instance of the `DoublyLinkedList` class with elements of type `T` and `RR`.
|
|
997
|
+
* Map values into a new list of the same class.
|
|
998
|
+
* @remarks Time O(N), Space O(N)
|
|
999
|
+
* @param callback - Mapping function (value, index, list) → newValue.
|
|
1000
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1001
|
+
* @returns A new list with mapped values.
|
|
1098
1002
|
*/
|
|
1099
|
-
|
|
1100
|
-
const
|
|
1003
|
+
mapSame(callback, thisArg) {
|
|
1004
|
+
const out = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
1101
1005
|
let index = 0;
|
|
1102
|
-
for (const
|
|
1103
|
-
|
|
1104
|
-
|
|
1006
|
+
for (const v of this) {
|
|
1007
|
+
const mv = thisArg === undefined ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
|
|
1008
|
+
out.push(mv);
|
|
1105
1009
|
}
|
|
1106
|
-
return
|
|
1010
|
+
return out;
|
|
1107
1011
|
}
|
|
1108
1012
|
/**
|
|
1109
|
-
*
|
|
1110
|
-
*
|
|
1111
|
-
*
|
|
1112
|
-
*
|
|
1113
|
-
*
|
|
1114
|
-
* @param
|
|
1115
|
-
*
|
|
1116
|
-
* @returns
|
|
1117
|
-
* node, or predicate function in the doubly linked list.
|
|
1013
|
+
* Map values into a new list (possibly different element type).
|
|
1014
|
+
* @remarks Time O(N), Space O(N)
|
|
1015
|
+
* @template EM
|
|
1016
|
+
* @template RM
|
|
1017
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
1018
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
1019
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1020
|
+
* @returns A new DoublyLinkedList with mapped values.
|
|
1118
1021
|
*/
|
|
1119
|
-
|
|
1120
|
-
const
|
|
1121
|
-
let
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1022
|
+
map(callback, options, thisArg) {
|
|
1023
|
+
const out = this._createLike([], Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), { maxLen: this._maxLen }));
|
|
1024
|
+
let index = 0;
|
|
1025
|
+
for (const v of this)
|
|
1026
|
+
out.push(callback.call(thisArg, v, index++, this));
|
|
1027
|
+
return out;
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* (Protected) Create or return a node for the given input (node or raw element).
|
|
1031
|
+
* @remarks Time O(1), Space O(1)
|
|
1032
|
+
* @param elementOrNode - Element value or node to normalize.
|
|
1033
|
+
* @returns A DoublyLinkedListNode for the provided input.
|
|
1034
|
+
*/
|
|
1035
|
+
_ensureNode(elementOrNode) {
|
|
1036
|
+
if (this.isNode(elementOrNode))
|
|
1037
|
+
return elementOrNode;
|
|
1038
|
+
return new DoublyLinkedListNode(elementOrNode);
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* (Protected) Normalize input into a predicate over nodes.
|
|
1042
|
+
* @remarks Time O(1), Space O(1)
|
|
1043
|
+
* @param elementNodeOrPredicate - Element, node, or node predicate.
|
|
1044
|
+
* @returns A predicate function taking a node and returning true/false.
|
|
1045
|
+
*/
|
|
1046
|
+
_ensurePredicate(elementNodeOrPredicate) {
|
|
1047
|
+
if (this.isNode(elementNodeOrPredicate)) {
|
|
1048
|
+
const target = elementNodeOrPredicate;
|
|
1049
|
+
return (node) => node === target;
|
|
1050
|
+
}
|
|
1051
|
+
if (typeof elementNodeOrPredicate === 'function') {
|
|
1052
|
+
return elementNodeOrPredicate;
|
|
1128
1053
|
}
|
|
1129
|
-
|
|
1054
|
+
const value = elementNodeOrPredicate;
|
|
1055
|
+
return (node) => this._equals(node.value, value);
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* (Protected) Get the previous node of a given node.
|
|
1059
|
+
* @remarks Time O(1), Space O(1)
|
|
1060
|
+
* @param node - A node in the list.
|
|
1061
|
+
* @returns Previous node or undefined.
|
|
1062
|
+
*/
|
|
1063
|
+
_getPrevNode(node) {
|
|
1064
|
+
return node.prev;
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* (Protected) Create an empty instance of the same concrete class.
|
|
1068
|
+
* @remarks Time O(1), Space O(1)
|
|
1069
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1070
|
+
* @returns An empty like-kind list instance.
|
|
1071
|
+
*/
|
|
1072
|
+
_createInstance(options) {
|
|
1073
|
+
const Ctor = this.constructor;
|
|
1074
|
+
return new Ctor([], options);
|
|
1130
1075
|
}
|
|
1131
1076
|
/**
|
|
1132
|
-
*
|
|
1077
|
+
* (Protected) Create a like-kind instance and seed it from an iterable.
|
|
1078
|
+
* @remarks Time O(N), Space O(N)
|
|
1079
|
+
* @template EM
|
|
1080
|
+
* @template RM
|
|
1081
|
+
* @param [elements] - Iterable used to seed the new list.
|
|
1082
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1083
|
+
* @returns A like-kind DoublyLinkedList instance.
|
|
1133
1084
|
*/
|
|
1085
|
+
_createLike(elements = [], options) {
|
|
1086
|
+
const Ctor = this.constructor;
|
|
1087
|
+
return new Ctor(elements, options);
|
|
1088
|
+
}
|
|
1134
1089
|
*_getIterator() {
|
|
1135
1090
|
let current = this.head;
|
|
1136
1091
|
while (current) {
|
|
@@ -1138,10 +1093,6 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
1138
1093
|
current = current.next;
|
|
1139
1094
|
}
|
|
1140
1095
|
}
|
|
1141
|
-
/**
|
|
1142
|
-
* The function returns an iterator that iterates over the elements of a data structure in reverse
|
|
1143
|
-
* order.
|
|
1144
|
-
*/
|
|
1145
1096
|
*_getReverseIterator() {
|
|
1146
1097
|
let current = this.tail;
|
|
1147
1098
|
while (current) {
|
|
@@ -1149,10 +1100,6 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
1149
1100
|
current = current.prev;
|
|
1150
1101
|
}
|
|
1151
1102
|
}
|
|
1152
|
-
/**
|
|
1153
|
-
* The function returns an iterator that iterates over the nodes of a doubly linked list starting
|
|
1154
|
-
* from the head.
|
|
1155
|
-
*/
|
|
1156
1103
|
*_getNodeIterator() {
|
|
1157
1104
|
let current = this.head;
|
|
1158
1105
|
while (current) {
|
|
@@ -1160,78 +1107,5 @@ class DoublyLinkedList extends linear_base_1.LinearLinkedBase {
|
|
|
1160
1107
|
current = current.next;
|
|
1161
1108
|
}
|
|
1162
1109
|
}
|
|
1163
|
-
// protected *_getReverseNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {
|
|
1164
|
-
// const reversedArr = [...this._getNodeIterator()].reverse();
|
|
1165
|
-
//
|
|
1166
|
-
// for (const item of reversedArr) {
|
|
1167
|
-
// yield item;
|
|
1168
|
-
// }
|
|
1169
|
-
// }
|
|
1170
|
-
/**
|
|
1171
|
-
* The function `_isPredicate` checks if the input is a function that takes a `DoublyLinkedListNode`
|
|
1172
|
-
* as an argument and returns a boolean.
|
|
1173
|
-
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
1174
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following
|
|
1175
|
-
* types:
|
|
1176
|
-
* @returns The _isPredicate method is returning a boolean value indicating whether the
|
|
1177
|
-
* elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a
|
|
1178
|
-
* function, the method will return true, indicating that it is a predicate function.
|
|
1179
|
-
*/
|
|
1180
|
-
_isPredicate(elementNodeOrPredicate) {
|
|
1181
|
-
return typeof elementNodeOrPredicate === 'function';
|
|
1182
|
-
}
|
|
1183
|
-
/**
|
|
1184
|
-
* The function `_ensureNode` ensures that the input is a valid node in a doubly linked list.
|
|
1185
|
-
* @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can be either
|
|
1186
|
-
* an element of type `E` or a `DoublyLinkedListNode` containing an element of type `E`.
|
|
1187
|
-
* @returns If the `elementOrNode` parameter is already a `DoublyLinkedListNode`, it will be returned
|
|
1188
|
-
* as is. Otherwise, a new `DoublyLinkedListNode` instance will be created with the `elementOrNode`
|
|
1189
|
-
* value and returned.
|
|
1190
|
-
*/
|
|
1191
|
-
_ensureNode(elementOrNode) {
|
|
1192
|
-
if (this.isNode(elementOrNode))
|
|
1193
|
-
return elementOrNode;
|
|
1194
|
-
return new DoublyLinkedListNode(elementOrNode);
|
|
1195
|
-
}
|
|
1196
|
-
/**
|
|
1197
|
-
* The function `_ensurePredicate` in TypeScript ensures that the input is either a node, a predicate
|
|
1198
|
-
* function, or a value to compare with the node's value.
|
|
1199
|
-
* @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
1200
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following
|
|
1201
|
-
* types:
|
|
1202
|
-
* @returns A function is being returned that takes a `DoublyLinkedListNode` as a parameter and
|
|
1203
|
-
* returns a boolean value based on the conditions specified in the code.
|
|
1204
|
-
*/
|
|
1205
|
-
_ensurePredicate(elementNodeOrPredicate) {
|
|
1206
|
-
if (this.isNode(elementNodeOrPredicate))
|
|
1207
|
-
return (node) => node === elementNodeOrPredicate;
|
|
1208
|
-
if (this._isPredicate(elementNodeOrPredicate))
|
|
1209
|
-
return elementNodeOrPredicate;
|
|
1210
|
-
return (node) => node.value === elementNodeOrPredicate;
|
|
1211
|
-
}
|
|
1212
|
-
/**
|
|
1213
|
-
* The function `_createInstance` returns a new instance of `DoublyLinkedList` with the specified
|
|
1214
|
-
* options.
|
|
1215
|
-
* @param [options] - The `options` parameter in the `_createInstance` method is of type
|
|
1216
|
-
* `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional
|
|
1217
|
-
* configuration options when creating a new instance of the `DoublyLinkedList` class.
|
|
1218
|
-
* @returns An instance of the `DoublyLinkedList` class with an empty array and the provided options
|
|
1219
|
-
* is being returned, cast as the current class type.
|
|
1220
|
-
*/
|
|
1221
|
-
_createInstance(options) {
|
|
1222
|
-
return new DoublyLinkedList([], options);
|
|
1223
|
-
}
|
|
1224
|
-
/**
|
|
1225
|
-
* The function `_getPrevNode` returns the previous node of a given node in a doubly linked list.
|
|
1226
|
-
* @param node - The parameter `node` in the `_getPrevNode` method is of type
|
|
1227
|
-
* `DoublyLinkedListNode<E>`, which represents a node in a doubly linked list containing an element
|
|
1228
|
-
* of type `E`.
|
|
1229
|
-
* @returns The `_getPrevNode` method is returning the previous node of the input `node` in a doubly
|
|
1230
|
-
* linked list. If the input node has a previous node, it will return that node. Otherwise, it will
|
|
1231
|
-
* return `undefined`.
|
|
1232
|
-
*/
|
|
1233
|
-
_getPrevNode(node) {
|
|
1234
|
-
return node.prev;
|
|
1235
|
-
}
|
|
1236
1110
|
}
|
|
1237
1111
|
exports.DoublyLinkedList = DoublyLinkedList;
|