data-structure-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/CHANGELOG.md +1 -1
- package/COMMANDS.md +17 -0
- package/benchmark/report.html +13 -77
- package/benchmark/report.json +145 -177
- package/dist/cjs/data-structures/base/iterable-element-base.d.ts +186 -83
- package/dist/cjs/data-structures/base/iterable-element-base.js +149 -107
- package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
- package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/cjs/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
- package/dist/cjs/data-structures/base/linear-base.d.ts +250 -192
- package/dist/cjs/data-structures/base/linear-base.js +137 -274
- package/dist/cjs/data-structures/base/linear-base.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js +171 -205
- package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/cjs/data-structures/binary-tree/avl-tree.js +208 -195
- package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +594 -865
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/cjs/data-structures/binary-tree/bst.js +505 -481
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/cjs/data-structures/binary-tree/red-black-tree.js +114 -209
- package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/cjs/data-structures/binary-tree/tree-counter.js +172 -203
- package/dist/cjs/data-structures/binary-tree/tree-counter.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +105 -85
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/cjs/data-structures/graph/abstract-graph.js +267 -237
- package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/cjs/data-structures/graph/directed-graph.js +146 -233
- package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/cjs/data-structures/graph/map-graph.js +56 -59
- package/dist/cjs/data-structures/graph/map-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/cjs/data-structures/graph/undirected-graph.js +129 -149
- package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
- package/dist/cjs/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/cjs/data-structures/hash/hash-map.js +270 -457
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/heap/heap.d.ts +214 -289
- package/dist/cjs/data-structures/heap/heap.js +340 -349
- package/dist/cjs/data-structures/heap/heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/cjs/data-structures/heap/max-heap.js +11 -66
- package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/cjs/data-structures/heap/min-heap.js +11 -66
- package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +368 -494
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js +447 -466
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/cjs/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/cjs/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/queue/deque.d.ts +227 -254
- package/dist/cjs/data-structures/queue/deque.js +309 -348
- package/dist/cjs/data-structures/queue/deque.js.map +1 -1
- package/dist/cjs/data-structures/queue/queue.d.ts +180 -201
- package/dist/cjs/data-structures/queue/queue.js +265 -248
- package/dist/cjs/data-structures/queue/queue.js.map +1 -1
- package/dist/cjs/data-structures/stack/stack.d.ts +124 -102
- package/dist/cjs/data-structures/stack/stack.js +181 -125
- package/dist/cjs/data-structures/stack/stack.js.map +1 -1
- package/dist/cjs/data-structures/trie/trie.d.ts +164 -165
- package/dist/cjs/data-structures/trie/trie.js +189 -172
- package/dist/cjs/data-structures/trie/trie.js.map +1 -1
- package/dist/cjs/interfaces/binary-tree.d.ts +56 -6
- package/dist/cjs/interfaces/graph.d.ts +16 -0
- package/dist/cjs/types/data-structures/base/base.d.ts +1 -1
- package/dist/cjs/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/cjs/types/utils/utils.d.ts +1 -0
- package/dist/cjs/utils/utils.d.ts +1 -1
- package/dist/cjs/utils/utils.js +2 -1
- package/dist/cjs/utils/utils.js.map +1 -1
- package/dist/esm/data-structures/base/iterable-element-base.d.ts +186 -83
- package/dist/esm/data-structures/base/iterable-element-base.js +155 -107
- package/dist/esm/data-structures/base/iterable-element-base.js.map +1 -1
- package/dist/esm/data-structures/base/iterable-entry-base.d.ts +95 -119
- package/dist/esm/data-structures/base/iterable-entry-base.js +59 -116
- package/dist/esm/data-structures/base/iterable-entry-base.js.map +1 -1
- package/dist/esm/data-structures/base/linear-base.d.ts +250 -192
- package/dist/esm/data-structures/base/linear-base.js +137 -274
- package/dist/esm/data-structures/base/linear-base.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
- package/dist/esm/data-structures/binary-tree/avl-tree-counter.js +171 -212
- package/dist/esm/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
- package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js +133 -94
- package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/avl-tree.d.ts +138 -149
- package/dist/esm/data-structures/binary-tree/avl-tree.js +206 -200
- package/dist/esm/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/binary-tree.d.ts +476 -632
- package/dist/esm/data-structures/binary-tree/binary-tree.js +598 -874
- package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/bst.d.ts +258 -306
- package/dist/esm/data-structures/binary-tree/bst.js +507 -487
- package/dist/esm/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/red-black-tree.d.ts +107 -179
- package/dist/esm/data-structures/binary-tree/red-black-tree.js +114 -215
- package/dist/esm/data-structures/binary-tree/red-black-tree.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/tree-counter.d.ts +132 -154
- package/dist/esm/data-structures/binary-tree/tree-counter.js +175 -209
- package/dist/esm/data-structures/binary-tree/tree-counter.js.map +1 -1
- package/dist/esm/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
- package/dist/esm/data-structures/binary-tree/tree-multi-map.js +103 -92
- package/dist/esm/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/esm/data-structures/graph/abstract-graph.d.ts +238 -233
- package/dist/esm/data-structures/graph/abstract-graph.js +267 -237
- package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/esm/data-structures/graph/directed-graph.d.ts +108 -224
- package/dist/esm/data-structures/graph/directed-graph.js +145 -233
- package/dist/esm/data-structures/graph/directed-graph.js.map +1 -1
- package/dist/esm/data-structures/graph/map-graph.d.ts +49 -55
- package/dist/esm/data-structures/graph/map-graph.js +56 -59
- package/dist/esm/data-structures/graph/map-graph.js.map +1 -1
- package/dist/esm/data-structures/graph/undirected-graph.d.ts +103 -146
- package/dist/esm/data-structures/graph/undirected-graph.js +128 -149
- package/dist/esm/data-structures/graph/undirected-graph.js.map +1 -1
- package/dist/esm/data-structures/hash/hash-map.d.ts +164 -338
- package/dist/esm/data-structures/hash/hash-map.js +270 -457
- package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
- package/dist/esm/data-structures/heap/heap.d.ts +214 -289
- package/dist/esm/data-structures/heap/heap.js +329 -349
- package/dist/esm/data-structures/heap/heap.js.map +1 -1
- package/dist/esm/data-structures/heap/max-heap.d.ts +11 -47
- package/dist/esm/data-structures/heap/max-heap.js +11 -66
- package/dist/esm/data-structures/heap/max-heap.js.map +1 -1
- package/dist/esm/data-structures/heap/min-heap.d.ts +12 -47
- package/dist/esm/data-structures/heap/min-heap.js +11 -66
- package/dist/esm/data-structures/heap/min-heap.js.map +1 -1
- package/dist/esm/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
- package/dist/esm/data-structures/linked-list/doubly-linked-list.js +368 -495
- package/dist/esm/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +261 -310
- package/dist/esm/data-structures/linked-list/singly-linked-list.js +448 -467
- package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/esm/data-structures/linked-list/skip-linked-list.d.ts +0 -107
- package/dist/esm/data-structures/linked-list/skip-linked-list.js +0 -100
- package/dist/esm/data-structures/linked-list/skip-linked-list.js.map +1 -1
- package/dist/esm/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
- package/dist/esm/data-structures/priority-queue/max-priority-queue.js +11 -78
- package/dist/esm/data-structures/priority-queue/max-priority-queue.js.map +1 -1
- package/dist/esm/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
- package/dist/esm/data-structures/priority-queue/min-priority-queue.js +10 -79
- package/dist/esm/data-structures/priority-queue/min-priority-queue.js.map +1 -1
- package/dist/esm/data-structures/priority-queue/priority-queue.d.ts +2 -61
- package/dist/esm/data-structures/priority-queue/priority-queue.js +8 -83
- package/dist/esm/data-structures/priority-queue/priority-queue.js.map +1 -1
- package/dist/esm/data-structures/queue/deque.d.ts +227 -254
- package/dist/esm/data-structures/queue/deque.js +313 -348
- package/dist/esm/data-structures/queue/deque.js.map +1 -1
- package/dist/esm/data-structures/queue/queue.d.ts +180 -201
- package/dist/esm/data-structures/queue/queue.js +263 -248
- package/dist/esm/data-structures/queue/queue.js.map +1 -1
- package/dist/esm/data-structures/stack/stack.d.ts +124 -102
- package/dist/esm/data-structures/stack/stack.js +181 -125
- package/dist/esm/data-structures/stack/stack.js.map +1 -1
- package/dist/esm/data-structures/trie/trie.d.ts +164 -165
- package/dist/esm/data-structures/trie/trie.js +193 -172
- package/dist/esm/data-structures/trie/trie.js.map +1 -1
- package/dist/esm/interfaces/binary-tree.d.ts +56 -6
- package/dist/esm/interfaces/graph.d.ts +16 -0
- package/dist/esm/types/data-structures/base/base.d.ts +1 -1
- package/dist/esm/types/data-structures/graph/abstract-graph.d.ts +4 -0
- package/dist/esm/types/utils/utils.d.ts +1 -0
- package/dist/esm/utils/utils.d.ts +1 -1
- package/dist/esm/utils/utils.js +2 -1
- package/dist/esm/utils/utils.js.map +1 -1
- package/dist/umd/data-structure-typed.js +4685 -6477
- package/dist/umd/data-structure-typed.min.js +8 -6
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +3 -4
- 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 +660 -889
- 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
- package/test/integration/index.html +1 -1
- package/test/performance/benchmark-runner.ts +528 -0
- package/test/performance/reportor.mjs +43 -43
- package/test/performance/runner-config.json +39 -0
- package/test/performance/single-suite-runner.ts +69 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +3 -3
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +5 -5
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +4 -4
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +350 -90
- package/test/unit/data-structures/binary-tree/bst.test.ts +12 -9
- package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/tree-counter.test.ts +25 -24
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +3 -3
- package/test/unit/data-structures/graph/abstract-graph.test.ts +0 -4
- package/test/unit/data-structures/graph/directed-graph.test.ts +1 -1
- package/test/unit/data-structures/heap/heap.test.ts +14 -21
- package/test/unit/data-structures/heap/max-heap.test.ts +5 -9
- package/test/unit/data-structures/heap/min-heap.test.ts +1 -4
- package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +14 -14
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +0 -7
- package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +8 -11
- package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +1 -4
- package/test/unit/data-structures/priority-queue/priority-queue.test.ts +1 -4
- package/test/unit/data-structures/queue/queue.test.ts +4 -5
- package/test/unit/utils/utils.test.ts +0 -1
- package/test/performance/data-structures/binary-tree/avl-tree.test.mjs +0 -71
- package/test/performance/data-structures/binary-tree/red-black-tree.test.mjs +0 -81
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* data-structure-typed
|
|
3
|
+
*
|
|
4
|
+
* @author Pablo Zeng
|
|
5
|
+
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
|
|
6
|
+
* @license MIT License
|
|
7
|
+
*/
|
|
1
8
|
import { LinearLinkedBase, LinkedListNode } from '../base/linear-base';
|
|
9
|
+
/**
|
|
10
|
+
* Node of a singly linked list; stores value and the next link.
|
|
11
|
+
* @remarks Time O(1), Space O(1)
|
|
12
|
+
* @template E
|
|
13
|
+
*/
|
|
2
14
|
export class SinglyLinkedListNode extends LinkedListNode {
|
|
3
15
|
/**
|
|
4
|
-
*
|
|
5
|
-
* @
|
|
6
|
-
*
|
|
16
|
+
* Create a list node.
|
|
17
|
+
* @remarks Time O(1), Space O(1)
|
|
18
|
+
* @param value - Element value to store.
|
|
19
|
+
* @returns New node instance.
|
|
7
20
|
*/
|
|
8
21
|
constructor(value) {
|
|
9
22
|
super(value);
|
|
@@ -11,20 +24,34 @@ export class SinglyLinkedListNode extends LinkedListNode {
|
|
|
11
24
|
this._next = undefined;
|
|
12
25
|
}
|
|
13
26
|
_next;
|
|
27
|
+
/**
|
|
28
|
+
* Get the next node.
|
|
29
|
+
* @remarks Time O(1), Space O(1)
|
|
30
|
+
* @returns Next node or undefined.
|
|
31
|
+
*/
|
|
14
32
|
get next() {
|
|
15
33
|
return this._next;
|
|
16
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Set the next node.
|
|
37
|
+
* @remarks Time O(1), Space O(1)
|
|
38
|
+
* @param value - Next node or undefined.
|
|
39
|
+
* @returns void
|
|
40
|
+
*/
|
|
17
41
|
set next(value) {
|
|
18
42
|
this._next = value;
|
|
19
43
|
}
|
|
20
44
|
}
|
|
21
45
|
/**
|
|
46
|
+
* Singly linked list with O(1) push/pop-like ends operations and linear scans.
|
|
47
|
+
* @remarks Time O(1), Space O(1)
|
|
48
|
+
* @template E
|
|
49
|
+
* @template R
|
|
22
50
|
* 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.
|
|
23
51
|
* 2. Bidirectional Traversal: Unlike doubly linked lists, singly linked lists can be easily traversed forwards but not backwards.
|
|
24
52
|
* 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.
|
|
25
53
|
* 4. High Efficiency in Insertion and Deletion: Adding or removing elements in a linked list does not require moving other elements, making these operations more efficient than in arrays.
|
|
26
54
|
* Caution: Although our linked list classes provide methods such as at, setAt, addAt, and indexOf that are based on array indices, their time complexity, like that of the native Array.lastIndexOf, is 𝑂(𝑛). If you need to use these methods frequently, you might want to consider other data structures, such as Deque or Queue (designed for random access). Similarly, since the native Array.shift method has a time complexity of 𝑂(𝑛), using an array to simulate a queue can be inefficient. In such cases, you should use Queue or Deque, as these data structures leverage deferred array rearrangement, effectively reducing the average time complexity to 𝑂(1).
|
|
27
|
-
*
|
|
28
55
|
* @example
|
|
29
56
|
* // implementation of a basic text editor
|
|
30
57
|
* class TextEditor {
|
|
@@ -93,60 +120,88 @@ export class SinglyLinkedListNode extends LinkedListNode {
|
|
|
93
120
|
* console.log(editor.getText()); // 'Haello'
|
|
94
121
|
*/
|
|
95
122
|
export class SinglyLinkedList extends LinearLinkedBase {
|
|
123
|
+
_equals = Object.is;
|
|
124
|
+
/**
|
|
125
|
+
* Create a SinglyLinkedList and optionally bulk-insert elements.
|
|
126
|
+
* @remarks Time O(N), Space O(N)
|
|
127
|
+
* @param [elements] - Iterable of elements or nodes (or raw records if toElementFn is provided).
|
|
128
|
+
* @param [options] - Options such as maxLen and toElementFn.
|
|
129
|
+
* @returns New SinglyLinkedList instance.
|
|
130
|
+
*/
|
|
96
131
|
constructor(elements = [], options) {
|
|
97
132
|
super(options);
|
|
98
|
-
if (options) {
|
|
99
|
-
}
|
|
100
133
|
this.pushMany(elements);
|
|
101
134
|
}
|
|
102
135
|
_head;
|
|
136
|
+
/**
|
|
137
|
+
* Get the head node.
|
|
138
|
+
* @remarks Time O(1), Space O(1)
|
|
139
|
+
* @returns Head node or undefined.
|
|
140
|
+
*/
|
|
103
141
|
get head() {
|
|
104
142
|
return this._head;
|
|
105
143
|
}
|
|
106
144
|
_tail;
|
|
145
|
+
/**
|
|
146
|
+
* Get the tail node.
|
|
147
|
+
* @remarks Time O(1), Space O(1)
|
|
148
|
+
* @returns Tail node or undefined.
|
|
149
|
+
*/
|
|
107
150
|
get tail() {
|
|
108
151
|
return this._tail;
|
|
109
152
|
}
|
|
153
|
+
_length = 0;
|
|
154
|
+
/**
|
|
155
|
+
* Get the number of elements.
|
|
156
|
+
* @remarks Time O(1), Space O(1)
|
|
157
|
+
* @returns Current length.
|
|
158
|
+
*/
|
|
159
|
+
get length() {
|
|
160
|
+
return this._length;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get the first element value.
|
|
164
|
+
* @remarks Time O(1), Space O(1)
|
|
165
|
+
* @returns First element or undefined.
|
|
166
|
+
*/
|
|
110
167
|
get first() {
|
|
111
168
|
return this.head?.value;
|
|
112
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Get the last element value.
|
|
172
|
+
* @remarks Time O(1), Space O(1)
|
|
173
|
+
* @returns Last element or undefined.
|
|
174
|
+
*/
|
|
113
175
|
get last() {
|
|
114
176
|
return this.tail?.value;
|
|
115
177
|
}
|
|
116
|
-
_length = 0;
|
|
117
|
-
get length() {
|
|
118
|
-
return this._length;
|
|
119
|
-
}
|
|
120
178
|
/**
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* @param
|
|
127
|
-
* @
|
|
179
|
+
* Create a new list from an iterable of elements.
|
|
180
|
+
* @remarks Time O(N), Space O(N)
|
|
181
|
+
* @template E
|
|
182
|
+
* @template R
|
|
183
|
+
* @template S
|
|
184
|
+
* @param this - The constructor (subclass) to instantiate.
|
|
185
|
+
* @param data - Iterable of elements to insert.
|
|
186
|
+
* @param [options] - Options forwarded to the constructor.
|
|
187
|
+
* @returns A new list populated with the iterable's elements.
|
|
128
188
|
*/
|
|
129
|
-
static
|
|
130
|
-
const
|
|
131
|
-
for (const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return singlyLinkedList;
|
|
189
|
+
static from(data, options) {
|
|
190
|
+
const list = new this([], options);
|
|
191
|
+
for (const x of data)
|
|
192
|
+
list.push(x);
|
|
193
|
+
return list;
|
|
135
194
|
}
|
|
136
195
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
* @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`
|
|
142
|
-
* method can accept either an element of type `E` or a `SinglyLinkedListNode<E>` object.
|
|
143
|
-
* @returns The `push` method is returning a boolean value, specifically `true`.
|
|
196
|
+
* Append an element/node to the tail.
|
|
197
|
+
* @remarks Time O(1), Space O(1)
|
|
198
|
+
* @param elementOrNode - Element or node to append.
|
|
199
|
+
* @returns True when appended.
|
|
144
200
|
*/
|
|
145
201
|
push(elementOrNode) {
|
|
146
202
|
const newNode = this._ensureNode(elementOrNode);
|
|
147
203
|
if (!this.head) {
|
|
148
|
-
this._head = newNode;
|
|
149
|
-
this._tail = newNode;
|
|
204
|
+
this._head = this._tail = newNode;
|
|
150
205
|
}
|
|
151
206
|
else {
|
|
152
207
|
this.tail.next = newNode;
|
|
@@ -158,12 +213,9 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
158
213
|
return true;
|
|
159
214
|
}
|
|
160
215
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* The `pop` function removes and returns the value of the last element in a linked list.
|
|
165
|
-
* @returns The method is returning the value of the element that is being popped from the end of the
|
|
166
|
-
* list.
|
|
216
|
+
* Remove and return the tail element.
|
|
217
|
+
* @remarks Time O(N), Space O(1)
|
|
218
|
+
* @returns Removed element or undefined.
|
|
167
219
|
*/
|
|
168
220
|
pop() {
|
|
169
221
|
if (!this.head)
|
|
@@ -176,9 +228,8 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
176
228
|
return value;
|
|
177
229
|
}
|
|
178
230
|
let current = this.head;
|
|
179
|
-
while (current.next !== this.tail)
|
|
231
|
+
while (current.next !== this.tail)
|
|
180
232
|
current = current.next;
|
|
181
|
-
}
|
|
182
233
|
const value = this.tail.value;
|
|
183
234
|
current.next = undefined;
|
|
184
235
|
this._tail = current;
|
|
@@ -186,36 +237,30 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
186
237
|
return value;
|
|
187
238
|
}
|
|
188
239
|
/**
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
* The `shift()` function removes and returns the value of the first element in a linked list.
|
|
193
|
-
* @returns The value of the removed node.
|
|
240
|
+
* Remove and return the head element.
|
|
241
|
+
* @remarks Time O(1), Space O(1)
|
|
242
|
+
* @returns Removed element or undefined.
|
|
194
243
|
*/
|
|
195
244
|
shift() {
|
|
196
245
|
if (!this.head)
|
|
197
246
|
return undefined;
|
|
198
|
-
const
|
|
247
|
+
const removed = this.head;
|
|
199
248
|
this._head = this.head.next;
|
|
249
|
+
if (!this._head)
|
|
250
|
+
this._tail = undefined;
|
|
200
251
|
this._length--;
|
|
201
|
-
return
|
|
252
|
+
return removed.value;
|
|
202
253
|
}
|
|
203
254
|
/**
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
* TypeScript.
|
|
209
|
-
* @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the
|
|
210
|
-
* `unshift` method can be either an element of type `E` or a `SinglyLinkedListNode` containing an
|
|
211
|
-
* element of type `E`.
|
|
212
|
-
* @returns The `unshift` method is returning a boolean value, specifically `true`.
|
|
255
|
+
* Prepend an element/node to the head.
|
|
256
|
+
* @remarks Time O(1), Space O(1)
|
|
257
|
+
* @param elementOrNode - Element or node to prepend.
|
|
258
|
+
* @returns True when prepended.
|
|
213
259
|
*/
|
|
214
260
|
unshift(elementOrNode) {
|
|
215
261
|
const newNode = this._ensureNode(elementOrNode);
|
|
216
262
|
if (!this.head) {
|
|
217
|
-
this._head = newNode;
|
|
218
|
-
this._tail = newNode;
|
|
263
|
+
this._head = this._tail = newNode;
|
|
219
264
|
}
|
|
220
265
|
else {
|
|
221
266
|
newNode.next = this.head;
|
|
@@ -225,63 +270,42 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
225
270
|
return true;
|
|
226
271
|
}
|
|
227
272
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
* transformation function if provided.
|
|
233
|
-
* @param {Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>} elements - The `elements`
|
|
234
|
-
* parameter in the `pushMany` function can accept an iterable containing elements of type `E`, `R`,
|
|
235
|
-
* or `SinglyLinkedListNode<E>`.
|
|
236
|
-
* @returns The `pushMany` function returns an array of boolean values indicating whether each
|
|
237
|
-
* element was successfully pushed into the data structure.
|
|
273
|
+
* Append a sequence of elements/nodes.
|
|
274
|
+
* @remarks Time O(N), Space O(1)
|
|
275
|
+
* @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
|
|
276
|
+
* @returns Array of per-element success flags.
|
|
238
277
|
*/
|
|
239
278
|
pushMany(elements) {
|
|
240
279
|
const ans = [];
|
|
241
280
|
for (const el of elements) {
|
|
242
|
-
if (this.toElementFn)
|
|
281
|
+
if (this.toElementFn)
|
|
243
282
|
ans.push(this.push(this.toElementFn(el)));
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
ans.push(this.push(el));
|
|
283
|
+
else
|
|
284
|
+
ans.push(this.push(el));
|
|
247
285
|
}
|
|
248
286
|
return ans;
|
|
249
287
|
}
|
|
250
288
|
/**
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
* converting them using a provided function.
|
|
256
|
-
* @param {Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>} elements - The `elements`
|
|
257
|
-
* parameter in the `unshiftMany` function can accept an iterable containing elements of type `E`,
|
|
258
|
-
* `R`, or `SinglyLinkedListNode<E>`. The function iterates over each element in the iterable and
|
|
259
|
-
* performs an `unshift` operation on the linked list for each
|
|
260
|
-
* @returns The `unshiftMany` function is returning an array of boolean values, where each value
|
|
261
|
-
* represents the result of calling the `unshift` method on the current instance of the class.
|
|
289
|
+
* Prepend a sequence of elements/nodes.
|
|
290
|
+
* @remarks Time O(N), Space O(1)
|
|
291
|
+
* @param elements - Iterable of elements or nodes (or raw records if toElementFn is provided).
|
|
292
|
+
* @returns Array of per-element success flags.
|
|
262
293
|
*/
|
|
263
294
|
unshiftMany(elements) {
|
|
264
295
|
const ans = [];
|
|
265
296
|
for (const el of elements) {
|
|
266
|
-
if (this.toElementFn)
|
|
297
|
+
if (this.toElementFn)
|
|
267
298
|
ans.push(this.unshift(this.toElementFn(el)));
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
ans.push(this.unshift(el));
|
|
299
|
+
else
|
|
300
|
+
ans.push(this.unshift(el));
|
|
271
301
|
}
|
|
272
302
|
return ans;
|
|
273
303
|
}
|
|
274
304
|
/**
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
* predicate.
|
|
280
|
-
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
281
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `get` method can be one of
|
|
282
|
-
* the following types:
|
|
283
|
-
* @returns The `get` method returns the value of the first node in the singly linked list that
|
|
284
|
-
* satisfies the provided predicate function. If no such node is found, it returns `undefined`.
|
|
305
|
+
* Find the first value matching a predicate (by node).
|
|
306
|
+
* @remarks Time O(N), Space O(1)
|
|
307
|
+
* @param elementNodeOrPredicate - Element, node, or node predicate to match.
|
|
308
|
+
* @returns Matched value or undefined.
|
|
285
309
|
*/
|
|
286
310
|
search(elementNodeOrPredicate) {
|
|
287
311
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
@@ -294,97 +318,67 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
294
318
|
return undefined;
|
|
295
319
|
}
|
|
296
320
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
* @param {number} index - The index parameter is a number that represents the position of the element we want to
|
|
302
|
-
* retrieve from the list.
|
|
303
|
-
* @returns The method `at(index: number): E | undefined` returns the value at the specified index in the linked list, or
|
|
304
|
-
* `undefined` if the index is out of bounds.
|
|
321
|
+
* Get the element at a given index.
|
|
322
|
+
* @remarks Time O(N), Space O(1)
|
|
323
|
+
* @param index - Zero-based index.
|
|
324
|
+
* @returns Element or undefined.
|
|
305
325
|
*/
|
|
306
326
|
at(index) {
|
|
307
327
|
if (index < 0 || index >= this._length)
|
|
308
328
|
return undefined;
|
|
309
329
|
let current = this.head;
|
|
310
|
-
for (let i = 0; i < index; i++)
|
|
330
|
+
for (let i = 0; i < index; i++)
|
|
311
331
|
current = current.next;
|
|
312
|
-
}
|
|
313
332
|
return current.value;
|
|
314
333
|
}
|
|
315
334
|
/**
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
321
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can be
|
|
322
|
-
* one of the following types:
|
|
323
|
-
* @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an
|
|
324
|
-
* instance of `SinglyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the
|
|
325
|
-
* parameter is a `SinglyLinkedListNode<E>`. If it is not an instance of `SinglyLinkedListNode<E>`,
|
|
326
|
-
* the function returns `false`.
|
|
335
|
+
* Type guard: check whether the input is a SinglyLinkedListNode.
|
|
336
|
+
* @remarks Time O(1), Space O(1)
|
|
337
|
+
* @param elementNodeOrPredicate - Element, node, or predicate.
|
|
338
|
+
* @returns True if the value is a SinglyLinkedListNode.
|
|
327
339
|
*/
|
|
328
340
|
isNode(elementNodeOrPredicate) {
|
|
329
341
|
return elementNodeOrPredicate instanceof SinglyLinkedListNode;
|
|
330
342
|
}
|
|
331
343
|
/**
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
* @param {number} index - The `index` parameter is a number that represents the position of the node we want to
|
|
337
|
-
* retrieve from the linked list. It indicates the zero-based index of the node we want to access.
|
|
338
|
-
* @returns The method `getNodeAt(index: number)` returns a `SinglyLinkedListNode<E>` object if the node at the
|
|
339
|
-
* specified index exists, or `undefined` if the index is out of bounds.
|
|
344
|
+
* Get the node reference at a given index.
|
|
345
|
+
* @remarks Time O(N), Space O(1)
|
|
346
|
+
* @param index - Zero-based index.
|
|
347
|
+
* @returns Node or undefined.
|
|
340
348
|
*/
|
|
341
349
|
getNodeAt(index) {
|
|
350
|
+
if (index < 0 || index >= this._length)
|
|
351
|
+
return undefined;
|
|
342
352
|
let current = this.head;
|
|
343
|
-
for (let i = 0; i < index; i++)
|
|
353
|
+
for (let i = 0; i < index; i++)
|
|
344
354
|
current = current.next;
|
|
345
|
-
}
|
|
346
355
|
return current;
|
|
347
356
|
}
|
|
348
357
|
/**
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
* @param {number} index - The index parameter represents the position of the element that needs to be deleted in the
|
|
354
|
-
* data structure. It is of type number.
|
|
355
|
-
* @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of
|
|
356
|
-
* bounds.
|
|
358
|
+
* Delete the element at an index.
|
|
359
|
+
* @remarks Time O(N), Space O(1)
|
|
360
|
+
* @param index - Zero-based index.
|
|
361
|
+
* @returns Removed element or undefined.
|
|
357
362
|
*/
|
|
358
363
|
deleteAt(index) {
|
|
359
364
|
if (index < 0 || index >= this._length)
|
|
360
|
-
return;
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
deleted = this.first;
|
|
364
|
-
this.shift();
|
|
365
|
-
return deleted;
|
|
366
|
-
}
|
|
365
|
+
return undefined;
|
|
366
|
+
if (index === 0)
|
|
367
|
+
return this.shift();
|
|
367
368
|
const targetNode = this.getNodeAt(index);
|
|
368
369
|
const prevNode = this._getPrevNode(targetNode);
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
return deleted;
|
|
376
|
-
}
|
|
377
|
-
return;
|
|
370
|
+
const value = targetNode.value;
|
|
371
|
+
prevNode.next = targetNode.next;
|
|
372
|
+
if (targetNode === this.tail)
|
|
373
|
+
this._tail = prevNode;
|
|
374
|
+
this._length--;
|
|
375
|
+
return value;
|
|
378
376
|
}
|
|
379
377
|
/**
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
* @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can accept either a value of type `E`
|
|
385
|
-
* or a `SinglyLinkedListNode<E>` object.
|
|
386
|
-
* @returns The `delete` method returns a boolean value. It returns `true` if the value or node is found and
|
|
387
|
-
* successfully deleted from the linked list, and `false` if the value or node is not found in the linked list.
|
|
378
|
+
* Delete the first match by value/node.
|
|
379
|
+
* @remarks Time O(N), Space O(1)
|
|
380
|
+
* @param [elementOrNode] - Element or node to remove; if omitted/undefined, nothing happens.
|
|
381
|
+
* @returns True if removed.
|
|
388
382
|
*/
|
|
389
383
|
delete(elementOrNode) {
|
|
390
384
|
if (elementOrNode === undefined || !this.head)
|
|
@@ -394,7 +388,6 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
394
388
|
return false;
|
|
395
389
|
const prevNode = this._getPrevNode(node);
|
|
396
390
|
if (!prevNode) {
|
|
397
|
-
// The node is the head
|
|
398
391
|
this._head = node.next;
|
|
399
392
|
if (node === this.tail)
|
|
400
393
|
this._tail = undefined;
|
|
@@ -408,31 +401,19 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
408
401
|
return true;
|
|
409
402
|
}
|
|
410
403
|
/**
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
* @
|
|
416
|
-
* new element or node in the linked list. It is a number that indicates the index where the new
|
|
417
|
-
* element or node should be inserted.
|
|
418
|
-
* @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
|
|
419
|
-
* `addAt` method can be either a value of type `E` or a `SinglyLinkedListNode<E>` object. This
|
|
420
|
-
* parameter represents the element or node that you want to add to the linked list at the specified
|
|
421
|
-
* index.
|
|
422
|
-
* @returns The `addAt` method returns a boolean value - `true` if the element or node was
|
|
423
|
-
* successfully added at the specified index, and `false` if the index is out of bounds.
|
|
404
|
+
* Insert a new element/node at an index, shifting following nodes.
|
|
405
|
+
* @remarks Time O(N), Space O(1)
|
|
406
|
+
* @param index - Zero-based index.
|
|
407
|
+
* @param newElementOrNode - Element or node to insert.
|
|
408
|
+
* @returns True if inserted.
|
|
424
409
|
*/
|
|
425
410
|
addAt(index, newElementOrNode) {
|
|
426
411
|
if (index < 0 || index > this._length)
|
|
427
412
|
return false;
|
|
428
|
-
if (index === 0)
|
|
429
|
-
this.unshift(newElementOrNode);
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
if (index === this._length) {
|
|
433
|
-
this.push(newElementOrNode);
|
|
434
|
-
return true;
|
|
435
|
-
}
|
|
413
|
+
if (index === 0)
|
|
414
|
+
return this.unshift(newElementOrNode);
|
|
415
|
+
if (index === this._length)
|
|
416
|
+
return this.push(newElementOrNode);
|
|
436
417
|
const newNode = this._ensureNode(newElementOrNode);
|
|
437
418
|
const prevNode = this.getNodeAt(index - 1);
|
|
438
419
|
newNode.next = prevNode.next;
|
|
@@ -441,43 +422,31 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
441
422
|
return true;
|
|
442
423
|
}
|
|
443
424
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
* @param {number} index - The `index` parameter in the `setAt` method refers to the position in the
|
|
450
|
-
* data structure where you want to set a new value.
|
|
451
|
-
* @param {E} value - The `value` parameter in the `setAt` method represents the new value that you
|
|
452
|
-
* want to set at the specified index in the data structure.
|
|
453
|
-
* @returns The `setAt` method returns a boolean value - `true` if the value at the specified index
|
|
454
|
-
* is successfully updated, and `false` if the index is out of bounds (i.e., the node at that index
|
|
455
|
-
* does not exist).
|
|
425
|
+
* Set the element value at an index.
|
|
426
|
+
* @remarks Time O(N), Space O(1)
|
|
427
|
+
* @param index - Zero-based index.
|
|
428
|
+
* @param value - New value.
|
|
429
|
+
* @returns True if updated.
|
|
456
430
|
*/
|
|
457
431
|
setAt(index, value) {
|
|
458
432
|
const node = this.getNodeAt(index);
|
|
459
|
-
if (node)
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
return false;
|
|
433
|
+
if (!node)
|
|
434
|
+
return false;
|
|
435
|
+
node.value = value;
|
|
436
|
+
return true;
|
|
464
437
|
}
|
|
465
438
|
/**
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
* The function checks if the length of a data structure is equal to zero and returns a boolean value indicating
|
|
470
|
-
* whether it is empty or not.
|
|
471
|
-
* @returns A boolean value indicating whether the length of the object is equal to 0.
|
|
439
|
+
* Check whether the list is empty.
|
|
440
|
+
* @remarks Time O(1), Space O(1)
|
|
441
|
+
* @returns True if length is 0.
|
|
472
442
|
*/
|
|
473
443
|
isEmpty() {
|
|
474
444
|
return this._length === 0;
|
|
475
445
|
}
|
|
476
446
|
/**
|
|
477
|
-
*
|
|
478
|
-
*
|
|
479
|
-
*
|
|
480
|
-
* The `clear` function resets the linked list by setting the head, tail, and length to undefined and 0 respectively.
|
|
447
|
+
* Remove all nodes and reset length.
|
|
448
|
+
* @remarks Time O(N), Space O(1)
|
|
449
|
+
* @returns void
|
|
481
450
|
*/
|
|
482
451
|
clear() {
|
|
483
452
|
this._head = undefined;
|
|
@@ -485,18 +454,16 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
485
454
|
this._length = 0;
|
|
486
455
|
}
|
|
487
456
|
/**
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
* The `reverse` function reverses the order of the nodes in a singly linked list.
|
|
492
|
-
* @returns The reverse() method does not return anything. It has a return type of void.
|
|
457
|
+
* Reverse the list in place.
|
|
458
|
+
* @remarks Time O(N), Space O(1)
|
|
459
|
+
* @returns This list.
|
|
493
460
|
*/
|
|
494
461
|
reverse() {
|
|
495
462
|
if (!this.head || this.head === this.tail)
|
|
496
463
|
return this;
|
|
497
|
-
let prev
|
|
464
|
+
let prev;
|
|
498
465
|
let current = this.head;
|
|
499
|
-
let next
|
|
466
|
+
let next;
|
|
500
467
|
while (current) {
|
|
501
468
|
next = current.next;
|
|
502
469
|
current.next = prev;
|
|
@@ -507,17 +474,10 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
507
474
|
return this;
|
|
508
475
|
}
|
|
509
476
|
/**
|
|
510
|
-
*
|
|
511
|
-
*
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
* element, node, or predicate.
|
|
515
|
-
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean) | undefined} elementNodeOrPredicate
|
|
516
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getNode` method can be one
|
|
517
|
-
* of the following types:
|
|
518
|
-
* @returns The `getNode` method returns either a `SinglyLinkedListNode<E>` if a matching node is
|
|
519
|
-
* found based on the provided predicate, or it returns `undefined` if no matching node is found or
|
|
520
|
-
* if the input parameter is `undefined`.
|
|
477
|
+
* Find a node by value, reference, or predicate.
|
|
478
|
+
* @remarks Time O(N), Space O(1)
|
|
479
|
+
* @param [elementNodeOrPredicate] - Element, node, or node predicate to match.
|
|
480
|
+
* @returns Matching node or undefined.
|
|
521
481
|
*/
|
|
522
482
|
getNode(elementNodeOrPredicate) {
|
|
523
483
|
if (elementNodeOrPredicate === undefined)
|
|
@@ -527,28 +487,18 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
527
487
|
const predicate = this._ensurePredicate(elementNodeOrPredicate);
|
|
528
488
|
let current = this.head;
|
|
529
489
|
while (current) {
|
|
530
|
-
if (predicate(current))
|
|
490
|
+
if (predicate(current))
|
|
531
491
|
return current;
|
|
532
|
-
}
|
|
533
492
|
current = current.next;
|
|
534
493
|
}
|
|
535
494
|
return undefined;
|
|
536
495
|
}
|
|
537
496
|
/**
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
* @param {E | SinglyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the
|
|
544
|
-
* element or node in the linked list before which you want to add a new element or node.
|
|
545
|
-
* @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
|
|
546
|
-
* `addBefore` method represents the element or node that you want to insert before the existing
|
|
547
|
-
* element or node in the linked list. This new element can be of type `E` or a
|
|
548
|
-
* `SinglyLinkedListNode<E>`.
|
|
549
|
-
* @returns The `addBefore` method returns a boolean value - `true` if the new element or node was
|
|
550
|
-
* successfully added before the existing element or node, and `false` if the operation was
|
|
551
|
-
* unsuccessful.
|
|
497
|
+
* Insert a new element/node before an existing one.
|
|
498
|
+
* @remarks Time O(N), Space O(1)
|
|
499
|
+
* @param existingElementOrNode - Existing element or node.
|
|
500
|
+
* @param newElementOrNode - Element or node to insert.
|
|
501
|
+
* @returns True if inserted.
|
|
552
502
|
*/
|
|
553
503
|
addBefore(existingElementOrNode, newElementOrNode) {
|
|
554
504
|
const existingNode = this.getNode(existingElementOrNode);
|
|
@@ -557,8 +507,11 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
557
507
|
const prevNode = this._getPrevNode(existingNode);
|
|
558
508
|
const newNode = this._ensureNode(newElementOrNode);
|
|
559
509
|
if (!prevNode) {
|
|
560
|
-
|
|
561
|
-
this.
|
|
510
|
+
newNode.next = this._head;
|
|
511
|
+
this._head = newNode;
|
|
512
|
+
if (!this._tail)
|
|
513
|
+
this._tail = newNode;
|
|
514
|
+
this._length++;
|
|
562
515
|
}
|
|
563
516
|
else {
|
|
564
517
|
prevNode.next = newNode;
|
|
@@ -568,299 +521,327 @@ export class SinglyLinkedList extends LinearLinkedBase {
|
|
|
568
521
|
return true;
|
|
569
522
|
}
|
|
570
523
|
/**
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
* @param {E | SinglyLinkedListNode<E>} existingElementOrNode - existingElementOrNode can be either
|
|
577
|
-
* an element of type E or a SinglyLinkedListNode of type E.
|
|
578
|
-
* @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the
|
|
579
|
-
* `addAfter` method represents the element or node that you want to add after the existing element
|
|
580
|
-
* or node in a singly linked list. This parameter can be either the value of the new element or a
|
|
581
|
-
* reference to a `SinglyLinkedListNode` containing
|
|
582
|
-
* @returns The `addAfter` method returns a boolean value - `true` if the new element or node was
|
|
583
|
-
* successfully added after the existing element or node, and `false` if the existing element or node
|
|
584
|
-
* was not found.
|
|
524
|
+
* Insert a new element/node after an existing one.
|
|
525
|
+
* @remarks Time O(N), Space O(1)
|
|
526
|
+
* @param existingElementOrNode - Existing element or node.
|
|
527
|
+
* @param newElementOrNode - Element or node to insert.
|
|
528
|
+
* @returns True if inserted.
|
|
585
529
|
*/
|
|
586
530
|
addAfter(existingElementOrNode, newElementOrNode) {
|
|
587
531
|
const existingNode = this.getNode(existingElementOrNode);
|
|
588
|
-
if (existingNode)
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
}
|
|
598
|
-
return false;
|
|
532
|
+
if (!existingNode)
|
|
533
|
+
return false;
|
|
534
|
+
const newNode = this._ensureNode(newElementOrNode);
|
|
535
|
+
newNode.next = existingNode.next;
|
|
536
|
+
existingNode.next = newNode;
|
|
537
|
+
if (existingNode === this.tail)
|
|
538
|
+
this._tail = newNode;
|
|
539
|
+
this._length++;
|
|
540
|
+
return true;
|
|
599
541
|
}
|
|
600
542
|
/**
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
* @
|
|
607
|
-
* to start modifying the list. It specifies the position where elements will be added or removed.
|
|
608
|
-
* @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the
|
|
609
|
-
* number of elements to remove from the array starting at the specified `start` index. If
|
|
610
|
-
* `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new
|
|
611
|
-
* elements can still be inserted at
|
|
612
|
-
* @param {E[]} items - The `items` parameter in the `splice` method represents the elements to be
|
|
613
|
-
* inserted into the list at the specified `start` index. These elements will be inserted in place of
|
|
614
|
-
* the elements that are removed from the list. The `splice` method allows you to add new elements to
|
|
615
|
-
* the list while
|
|
616
|
-
* @returns The `splice` method is returning a `SinglyLinkedList` containing the elements that were
|
|
617
|
-
* removed from the original list during the splice operation.
|
|
543
|
+
* Remove and/or insert elements at a position (array-like behavior).
|
|
544
|
+
* @remarks Time O(N + M), Space O(M)
|
|
545
|
+
* @param start - Start index (clamped to [0, length]).
|
|
546
|
+
* @param [deleteCount] - Number of elements to remove (default 0).
|
|
547
|
+
* @param [items] - Elements to insert after `start`.
|
|
548
|
+
* @returns A new list containing the removed elements (typed as `this`).
|
|
618
549
|
*/
|
|
619
550
|
splice(start, deleteCount = 0, ...items) {
|
|
620
|
-
const removedList = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });
|
|
621
|
-
// If `start` is out of range, perform boundary processing
|
|
622
551
|
start = Math.max(0, Math.min(start, this.length));
|
|
623
552
|
deleteCount = Math.max(0, deleteCount);
|
|
624
|
-
|
|
553
|
+
const removedList = this._createInstance();
|
|
625
554
|
const prevNode = start === 0 ? undefined : this.getNodeAt(start - 1);
|
|
626
|
-
|
|
627
|
-
let
|
|
628
|
-
|
|
629
|
-
removedList.push(
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
const nextNode = current;
|
|
633
|
-
let lastInsertedNode = undefined;
|
|
634
|
-
for (const item of items) {
|
|
635
|
-
const newNode = this._ensureNode(item);
|
|
636
|
-
if (!lastInsertedNode) {
|
|
637
|
-
if (prevNode) {
|
|
638
|
-
prevNode.next = newNode;
|
|
639
|
-
}
|
|
640
|
-
else {
|
|
641
|
-
this._head = newNode;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
else {
|
|
645
|
-
lastInsertedNode.next = newNode;
|
|
646
|
-
}
|
|
647
|
-
lastInsertedNode = newNode;
|
|
648
|
-
}
|
|
649
|
-
// Connect new node to `nextNode`
|
|
650
|
-
if (lastInsertedNode) {
|
|
651
|
-
lastInsertedNode.next = nextNode;
|
|
555
|
+
let cur = prevNode ? prevNode.next : this.head;
|
|
556
|
+
let removedCount = 0;
|
|
557
|
+
while (removedCount < deleteCount && cur) {
|
|
558
|
+
removedList.push(cur.value);
|
|
559
|
+
cur = cur.next;
|
|
560
|
+
removedCount++;
|
|
652
561
|
}
|
|
653
|
-
|
|
654
|
-
|
|
562
|
+
const afterNode = cur;
|
|
563
|
+
if (prevNode) {
|
|
564
|
+
prevNode.next = afterNode;
|
|
655
565
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
566
|
+
else {
|
|
567
|
+
this._head = afterNode;
|
|
568
|
+
}
|
|
569
|
+
if (!afterNode)
|
|
570
|
+
this._tail = prevNode;
|
|
571
|
+
if (items.length > 0) {
|
|
572
|
+
let firstInserted;
|
|
573
|
+
let lastInserted;
|
|
574
|
+
for (const it of items) {
|
|
575
|
+
const node = this._ensureNode(it);
|
|
576
|
+
if (!firstInserted)
|
|
577
|
+
firstInserted = node;
|
|
578
|
+
if (lastInserted)
|
|
579
|
+
lastInserted.next = node;
|
|
580
|
+
lastInserted = node;
|
|
581
|
+
}
|
|
582
|
+
if (prevNode)
|
|
583
|
+
prevNode.next = firstInserted;
|
|
584
|
+
else
|
|
585
|
+
this._head = firstInserted;
|
|
586
|
+
lastInserted.next = afterNode;
|
|
587
|
+
if (!afterNode)
|
|
588
|
+
this._tail = lastInserted;
|
|
589
|
+
}
|
|
590
|
+
this._length += items.length - removedCount;
|
|
591
|
+
if (this._length === 0) {
|
|
592
|
+
this._head = undefined;
|
|
593
|
+
this._tail = undefined;
|
|
659
594
|
}
|
|
660
|
-
this._length += items.length - removedList.length;
|
|
661
595
|
return removedList;
|
|
662
596
|
}
|
|
663
597
|
/**
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
* of a specified element or nodes that satisfy a given predicate.
|
|
669
|
-
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementOrNode
|
|
670
|
-
* - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values:
|
|
671
|
-
* @returns The `countOccurrences` method returns the number of occurrences of the specified element,
|
|
672
|
-
* node, or predicate function in the singly linked list.
|
|
598
|
+
* Count how many nodes match a value/node/predicate.
|
|
599
|
+
* @remarks Time O(N), Space O(1)
|
|
600
|
+
* @param elementOrNode - Element, node, or node predicate to match.
|
|
601
|
+
* @returns Number of matches in the list.
|
|
673
602
|
*/
|
|
674
603
|
countOccurrences(elementOrNode) {
|
|
675
|
-
const predicate = this.
|
|
604
|
+
const predicate = elementOrPredicate(elementOrNode, this._equals);
|
|
676
605
|
let count = 0;
|
|
677
606
|
let current = this.head;
|
|
678
607
|
while (current) {
|
|
679
|
-
if (predicate(current))
|
|
608
|
+
if (predicate(current))
|
|
680
609
|
count++;
|
|
681
|
-
}
|
|
682
610
|
current = current.next;
|
|
683
611
|
}
|
|
684
612
|
return count;
|
|
685
613
|
}
|
|
686
614
|
/**
|
|
687
|
-
*
|
|
688
|
-
*
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
* as the original list.
|
|
692
|
-
* @returns The `clone()` method is returning a new instance of the `SinglyLinkedList` class, which
|
|
693
|
-
* is a clone of the original list.
|
|
615
|
+
* Set the equality comparator used to compare values.
|
|
616
|
+
* @remarks Time O(1), Space O(1)
|
|
617
|
+
* @param equals - Equality predicate (a, b) → boolean.
|
|
618
|
+
* @returns This list.
|
|
694
619
|
*/
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
*
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
*
|
|
704
|
-
* filtered list.
|
|
705
|
-
* @param callback - The callback parameter is a function that will be called for each element in the
|
|
706
|
-
* list. It takes three arguments: the current element, the index of the current element, and the
|
|
707
|
-
* list itself. The callback function should return a boolean value indicating whether the current
|
|
708
|
-
* element should be included in the filtered list or not
|
|
709
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
|
710
|
-
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
|
711
|
-
* passed as the `this` value to the `callback` function. If `thisArg` is
|
|
712
|
-
* @returns The `filter` method is returning a new `SinglyLinkedList` object that contains the
|
|
713
|
-
* elements that pass the filter condition specified by the `callback` function.
|
|
620
|
+
setEquality(equals) {
|
|
621
|
+
this._equals = equals;
|
|
622
|
+
return this;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Delete the first node whose value matches a predicate.
|
|
626
|
+
* @remarks Time O(N), Space O(1)
|
|
627
|
+
* @param predicate - Predicate (value, index, list) → boolean to decide deletion.
|
|
628
|
+
* @returns True if a node was removed.
|
|
714
629
|
*/
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
let
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
630
|
+
deleteWhere(predicate) {
|
|
631
|
+
let prev;
|
|
632
|
+
let current = this.head;
|
|
633
|
+
let i = 0;
|
|
634
|
+
while (current) {
|
|
635
|
+
if (predicate(current.value, i++, this)) {
|
|
636
|
+
if (!prev) {
|
|
637
|
+
this._head = current.next;
|
|
638
|
+
if (current === this._tail)
|
|
639
|
+
this._tail = undefined;
|
|
640
|
+
}
|
|
641
|
+
else {
|
|
642
|
+
prev.next = current.next;
|
|
643
|
+
if (current === this._tail)
|
|
644
|
+
this._tail = prev;
|
|
645
|
+
}
|
|
646
|
+
this._length--;
|
|
647
|
+
return true;
|
|
721
648
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
return filteredList;
|
|
725
|
-
}
|
|
726
|
-
/**
|
|
727
|
-
* Time Complexity: O(n)
|
|
728
|
-
* Space Complexity: O(n)
|
|
729
|
-
*
|
|
730
|
-
* The `map` function takes a callback function and returns a new SinglyLinkedList with the results
|
|
731
|
-
* of applying the callback to each element in the original list.
|
|
732
|
-
* @param callback - The `callback` parameter is a function that will be called for each element in
|
|
733
|
-
* the original list. It takes three arguments: `current` (the current element being processed),
|
|
734
|
-
* `index` (the index of the current element), and `this` (the original list). It should return a
|
|
735
|
-
* value
|
|
736
|
-
* @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to
|
|
737
|
-
* convert the raw element (`RR`) to the desired element type (`T`). It takes the raw element as
|
|
738
|
-
* input and returns the converted element. If this parameter is not provided, the raw element will
|
|
739
|
-
* be used as is.
|
|
740
|
-
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
|
741
|
-
* specify the value of `this` within the callback function. It is used to set the context or scope
|
|
742
|
-
* in which the callback function will be executed. If `thisArg` is provided, it will be used as the
|
|
743
|
-
* value of
|
|
744
|
-
* @returns a new instance of the `SinglyLinkedList` class with the mapped elements.
|
|
745
|
-
*/
|
|
746
|
-
map(callback, toElementFn, thisArg) {
|
|
747
|
-
const mappedList = new SinglyLinkedList([], { toElementFn, maxLen: this._maxLen });
|
|
748
|
-
let index = 0;
|
|
749
|
-
for (const current of this) {
|
|
750
|
-
mappedList.push(callback.call(thisArg, current, index, this));
|
|
751
|
-
index++;
|
|
649
|
+
prev = current;
|
|
650
|
+
current = current.next;
|
|
752
651
|
}
|
|
753
|
-
return
|
|
652
|
+
return false;
|
|
754
653
|
}
|
|
755
654
|
/**
|
|
756
|
-
*
|
|
757
|
-
*
|
|
758
|
-
* @
|
|
759
|
-
* `SinglyLinkedListOptions<E, R>`, which is used to configure the behavior of the `SinglyLinkedList`
|
|
760
|
-
* instance being created. It is an optional parameter, meaning it can be omitted when calling the
|
|
761
|
-
* method.
|
|
762
|
-
* @returns An instance of the `SinglyLinkedList` class with an empty array and the provided options
|
|
763
|
-
* is being returned.
|
|
655
|
+
* Deep clone this list (values are copied by reference).
|
|
656
|
+
* @remarks Time O(N), Space O(N)
|
|
657
|
+
* @returns A new list with the same element sequence.
|
|
764
658
|
*/
|
|
765
|
-
|
|
766
|
-
|
|
659
|
+
clone() {
|
|
660
|
+
const out = this._createInstance();
|
|
661
|
+
for (const v of this)
|
|
662
|
+
out.push(v);
|
|
663
|
+
return out;
|
|
767
664
|
}
|
|
768
665
|
/**
|
|
769
|
-
*
|
|
666
|
+
* Filter values into a new list of the same class.
|
|
667
|
+
* @remarks Time O(N), Space O(N)
|
|
668
|
+
* @param callback - Predicate (value, index, list) → boolean to keep value.
|
|
669
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
670
|
+
* @returns A new list with kept values.
|
|
770
671
|
*/
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
672
|
+
filter(callback, thisArg) {
|
|
673
|
+
const out = this._createInstance();
|
|
674
|
+
let index = 0;
|
|
675
|
+
for (const value of this)
|
|
676
|
+
if (callback.call(thisArg, value, index++, this))
|
|
677
|
+
out.push(value);
|
|
678
|
+
return out;
|
|
777
679
|
}
|
|
778
680
|
/**
|
|
779
|
-
*
|
|
681
|
+
* Map values into a new list of the same class.
|
|
682
|
+
* @remarks Time O(N), Space O(N)
|
|
683
|
+
* @param callback - Mapping function (value, index, list) → newValue.
|
|
684
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
685
|
+
* @returns A new list with mapped values.
|
|
780
686
|
*/
|
|
781
|
-
|
|
782
|
-
const
|
|
783
|
-
|
|
784
|
-
|
|
687
|
+
mapSame(callback, thisArg) {
|
|
688
|
+
const out = this._createInstance();
|
|
689
|
+
let index = 0;
|
|
690
|
+
for (const value of this) {
|
|
691
|
+
const mv = thisArg === undefined ? callback(value, index++, this) : callback.call(thisArg, value, index++, this);
|
|
692
|
+
out.push(mv);
|
|
785
693
|
}
|
|
694
|
+
return out;
|
|
786
695
|
}
|
|
787
696
|
/**
|
|
788
|
-
*
|
|
789
|
-
*
|
|
697
|
+
* Map values into a new list (possibly different element type).
|
|
698
|
+
* @remarks Time O(N), Space O(N)
|
|
699
|
+
* @template EM
|
|
700
|
+
* @template RM
|
|
701
|
+
* @param callback - Mapping function (value, index, list) → newElement.
|
|
702
|
+
* @param [options] - Options for the output list (e.g., maxLen, toElementFn).
|
|
703
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
704
|
+
* @returns A new SinglyLinkedList with mapped values.
|
|
790
705
|
*/
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
706
|
+
map(callback, options, thisArg) {
|
|
707
|
+
const out = this._createLike([], { ...(options ?? {}), maxLen: this._maxLen });
|
|
708
|
+
let index = 0;
|
|
709
|
+
for (const value of this)
|
|
710
|
+
out.push(callback.call(thisArg, value, index++, this));
|
|
711
|
+
return out;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* (Protected) Create a node from a value.
|
|
715
|
+
* @remarks Time O(1), Space O(1)
|
|
716
|
+
* @param value - Value to wrap in a node.
|
|
717
|
+
* @returns A new SinglyLinkedListNode instance.
|
|
718
|
+
*/
|
|
719
|
+
_createNode(value) {
|
|
720
|
+
return new SinglyLinkedListNode(value);
|
|
797
721
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
// }
|
|
804
|
-
// }
|
|
805
|
-
/**
|
|
806
|
-
* The _isPredicate function in TypeScript checks if the input is a function that takes a
|
|
807
|
-
* SinglyLinkedListNode as an argument and returns a boolean.
|
|
808
|
-
* @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate
|
|
809
|
-
* elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following types:
|
|
810
|
-
* @returns The _isPredicate method is returning a boolean value based on whether the
|
|
811
|
-
* elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a
|
|
812
|
-
* function, the method will return true, indicating that it is a predicate function. If it is not a
|
|
813
|
-
* function, the method will return false.
|
|
722
|
+
/**
|
|
723
|
+
* (Protected) Check if input is a node predicate function.
|
|
724
|
+
* @remarks Time O(1), Space O(1)
|
|
725
|
+
* @param elementNodeOrPredicate - Element, node, or node predicate.
|
|
726
|
+
* @returns True if input is a predicate function.
|
|
814
727
|
*/
|
|
815
728
|
_isPredicate(elementNodeOrPredicate) {
|
|
816
729
|
return typeof elementNodeOrPredicate === 'function';
|
|
817
730
|
}
|
|
818
731
|
/**
|
|
819
|
-
*
|
|
820
|
-
*
|
|
821
|
-
* @param
|
|
822
|
-
*
|
|
823
|
-
* @returns A SinglyLinkedListNode<E> object is being returned.
|
|
732
|
+
* (Protected) Normalize input into a node instance.
|
|
733
|
+
* @remarks Time O(1), Space O(1)
|
|
734
|
+
* @param elementOrNode - Element or node.
|
|
735
|
+
* @returns A SinglyLinkedListNode for the provided input.
|
|
824
736
|
*/
|
|
825
737
|
_ensureNode(elementOrNode) {
|
|
826
738
|
if (this.isNode(elementOrNode))
|
|
827
739
|
return elementOrNode;
|
|
828
|
-
return
|
|
740
|
+
return this._createNode(elementOrNode);
|
|
829
741
|
}
|
|
830
742
|
/**
|
|
831
|
-
*
|
|
832
|
-
*
|
|
833
|
-
* @param
|
|
834
|
-
*
|
|
835
|
-
* @returns A function is being returned. If the input `elementNodeOrPredicate` is already a node, a
|
|
836
|
-
* function is returned that checks if a given node is equal to the input node. If the input is a
|
|
837
|
-
* predicate function, it is returned as is. If the input is neither a node nor a predicate function,
|
|
838
|
-
* a function is returned that checks if a given node's value is equal to the input
|
|
743
|
+
* (Protected) Normalize input into a node predicate.
|
|
744
|
+
* @remarks Time O(1), Space O(1)
|
|
745
|
+
* @param elementNodeOrPredicate - Element, node, or predicate.
|
|
746
|
+
* @returns A predicate taking a node and returning true/false.
|
|
839
747
|
*/
|
|
840
748
|
_ensurePredicate(elementNodeOrPredicate) {
|
|
841
749
|
if (this.isNode(elementNodeOrPredicate))
|
|
842
750
|
return (node) => node === elementNodeOrPredicate;
|
|
843
751
|
if (this._isPredicate(elementNodeOrPredicate))
|
|
844
752
|
return elementNodeOrPredicate;
|
|
845
|
-
|
|
753
|
+
const value = elementNodeOrPredicate;
|
|
754
|
+
return (node) => this._equals(node.value, value);
|
|
846
755
|
}
|
|
847
756
|
/**
|
|
848
|
-
*
|
|
849
|
-
* @
|
|
850
|
-
*
|
|
851
|
-
*
|
|
852
|
-
* @returns The `_getPrevNode` method returns either the previous node of the input node in a singly
|
|
853
|
-
* linked list or `undefined` if the input node is the head of the list or if the input node is not
|
|
854
|
-
* found in the list.
|
|
757
|
+
* (Protected) Get the previous node of a given node.
|
|
758
|
+
* @remarks Time O(N), Space O(1)
|
|
759
|
+
* @param node - A node in the list.
|
|
760
|
+
* @returns Previous node or undefined.
|
|
855
761
|
*/
|
|
856
762
|
_getPrevNode(node) {
|
|
857
763
|
if (!this.head || this.head === node)
|
|
858
764
|
return undefined;
|
|
859
765
|
let current = this.head;
|
|
860
|
-
while (current.next && current.next !== node)
|
|
766
|
+
while (current.next && current.next !== node)
|
|
861
767
|
current = current.next;
|
|
862
|
-
}
|
|
863
768
|
return current.next === node ? current : undefined;
|
|
864
769
|
}
|
|
770
|
+
/**
|
|
771
|
+
* (Protected) Iterate values from head to tail.
|
|
772
|
+
* @remarks Time O(N), Space O(1)
|
|
773
|
+
* @returns Iterator of values (E).
|
|
774
|
+
*/
|
|
775
|
+
*_getIterator() {
|
|
776
|
+
let current = this.head;
|
|
777
|
+
while (current) {
|
|
778
|
+
yield current.value;
|
|
779
|
+
current = current.next;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* (Protected) Iterate values from tail to head.
|
|
784
|
+
* @remarks Time O(N), Space O(N)
|
|
785
|
+
* @returns Iterator of values (E).
|
|
786
|
+
*/
|
|
787
|
+
*_getReverseIterator() {
|
|
788
|
+
const reversedArr = [...this].reverse();
|
|
789
|
+
for (const item of reversedArr)
|
|
790
|
+
yield item;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* (Protected) Iterate nodes from head to tail.
|
|
794
|
+
* @remarks Time O(N), Space O(1)
|
|
795
|
+
* @returns Iterator of nodes.
|
|
796
|
+
*/
|
|
797
|
+
*_getNodeIterator() {
|
|
798
|
+
let current = this.head;
|
|
799
|
+
while (current) {
|
|
800
|
+
yield current;
|
|
801
|
+
current = current.next;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* (Protected) Create an empty instance of the same concrete class.
|
|
806
|
+
* @remarks Time O(1), Space O(1)
|
|
807
|
+
* @param [options] - Options forwarded to the constructor.
|
|
808
|
+
* @returns An empty like-kind list instance.
|
|
809
|
+
*/
|
|
810
|
+
_createInstance(options) {
|
|
811
|
+
const Ctor = this.constructor;
|
|
812
|
+
return new Ctor([], options);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* (Protected) Create a like-kind instance and seed it from an iterable.
|
|
816
|
+
* @remarks Time O(N), Space O(N)
|
|
817
|
+
* @template EM
|
|
818
|
+
* @template RM
|
|
819
|
+
* @param [elements] - Iterable used to seed the new list.
|
|
820
|
+
* @param [options] - Options forwarded to the constructor.
|
|
821
|
+
* @returns A like-kind SinglyLinkedList instance.
|
|
822
|
+
*/
|
|
823
|
+
_createLike(elements = [], options) {
|
|
824
|
+
const Ctor = this.constructor;
|
|
825
|
+
return new Ctor(elements, options);
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* (Protected) Spawn an empty like-kind list instance.
|
|
829
|
+
* @remarks Time O(1), Space O(1)
|
|
830
|
+
* @template EM
|
|
831
|
+
* @template RM
|
|
832
|
+
* @param [options] - Options forwarded to the constructor.
|
|
833
|
+
* @returns An empty like-kind SinglyLinkedList instance.
|
|
834
|
+
*/
|
|
835
|
+
_spawnLike(options) {
|
|
836
|
+
return this._createLike([], options);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
function elementOrPredicate(input, equals) {
|
|
840
|
+
if (input instanceof SinglyLinkedListNode)
|
|
841
|
+
return (node) => node === input;
|
|
842
|
+
if (typeof input === 'function')
|
|
843
|
+
return input;
|
|
844
|
+
const value = input;
|
|
845
|
+
return (node) => equals(node.value, value);
|
|
865
846
|
}
|
|
866
847
|
//# sourceMappingURL=singly-linked-list.js.map
|