list-toolkit 2.2.5 → 2.3.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/README.md +40 -36
- package/llms-full.txt +743 -0
- package/llms.txt +100 -0
- package/package.json +40 -32
- package/src/cache/cache-fifo.d.ts +6 -0
- package/src/cache/cache-fifo.js +7 -4
- package/src/cache/cache-lfu.d.ts +18 -0
- package/src/cache/cache-lfu.js +18 -6
- package/src/cache/cache-lru.d.ts +74 -0
- package/src/cache/cache-lru.js +60 -5
- package/src/cache/cache-random.d.ts +20 -0
- package/src/cache/cache-random.js +17 -6
- package/src/cache/decorator.d.ts +46 -0
- package/src/cache/decorator.js +26 -2
- package/src/cache.d.ts +13 -0
- package/src/cache.js +7 -2
- package/src/ext-list.d.ts +3 -0
- package/src/ext-list.js +0 -2
- package/src/ext-slist.d.ts +3 -0
- package/src/ext-slist.js +0 -2
- package/src/ext-value-list.d.ts +3 -0
- package/src/ext-value-list.js +0 -2
- package/src/ext-value-slist.d.ts +3 -0
- package/src/ext-value-slist.js +0 -2
- package/src/heap/basics.d.ts +89 -0
- package/src/heap/basics.js +42 -5
- package/src/heap/leftist-heap.d.ts +107 -0
- package/src/heap/leftist-heap.js +54 -2
- package/src/heap/min-heap.d.ts +270 -0
- package/src/heap/min-heap.js +186 -2
- package/src/heap/skew-heap.d.ts +105 -0
- package/src/heap/skew-heap.js +54 -2
- package/src/heap.d.ts +3 -0
- package/src/heap.js +0 -2
- package/src/list/basics.d.ts +43 -0
- package/src/list/basics.js +26 -8
- package/src/list/core.d.ts +271 -0
- package/src/list/core.js +162 -7
- package/src/list/ext-value.d.ts +253 -0
- package/src/list/ext-value.js +40 -6
- package/src/list/ext.d.ts +242 -0
- package/src/list/ext.js +148 -10
- package/src/list/nodes.d.ts +336 -0
- package/src/list/nodes.js +141 -3
- package/src/list/ptr.d.ts +72 -0
- package/src/list/ptr.js +44 -2
- package/src/list/value.d.ts +292 -0
- package/src/list/value.js +47 -6
- package/src/list-helpers.d.ts +44 -0
- package/src/list-helpers.js +36 -3
- package/src/list-utils.d.ts +141 -0
- package/src/list-utils.js +89 -3
- package/src/list.d.ts +3 -0
- package/src/list.js +0 -2
- package/src/meta-utils.d.ts +212 -0
- package/src/meta-utils.js +152 -1
- package/src/nt-utils.d.ts +91 -0
- package/src/nt-utils.js +65 -4
- package/src/queue.d.ts +74 -0
- package/src/queue.js +28 -2
- package/src/slist/basics.d.ts +47 -0
- package/src/slist/basics.js +23 -8
- package/src/slist/core.d.ts +251 -0
- package/src/slist/core.js +151 -6
- package/src/slist/ext-value.d.ts +188 -0
- package/src/slist/ext-value.js +35 -6
- package/src/slist/ext.d.ts +182 -0
- package/src/slist/ext.js +114 -12
- package/src/slist/nodes.d.ts +361 -0
- package/src/slist/nodes.js +156 -3
- package/src/slist/ptr.d.ts +73 -0
- package/src/slist/ptr.js +45 -2
- package/src/slist/value.d.ts +246 -0
- package/src/slist/value.js +38 -6
- package/src/slist.d.ts +3 -0
- package/src/slist.js +0 -2
- package/src/stack.d.ts +59 -0
- package/src/stack.js +29 -3
- package/src/tree/splay-tree.d.ts +151 -0
- package/src/tree/splay-tree.js +94 -3
- package/src/value-list.d.ts +3 -0
- package/src/value-list.js +0 -2
- package/src/value-slist.d.ts +3 -0
- package/src/value-slist.js +0 -2
- package/cjs/cache/cache-fifo.js +0 -37
- package/cjs/cache/cache-lfu.js +0 -76
- package/cjs/cache/cache-lru.js +0 -100
- package/cjs/cache/cache-random.js +0 -77
- package/cjs/cache/decorator.js +0 -47
- package/cjs/cache.js +0 -27
- package/cjs/ext-list.js +0 -21
- package/cjs/ext-slist.js +0 -21
- package/cjs/ext-value-list.js +0 -21
- package/cjs/ext-value-slist.js +0 -21
- package/cjs/heap/basics.js +0 -63
- package/cjs/heap/leftist-heap.js +0 -124
- package/cjs/heap/min-heap.js +0 -294
- package/cjs/heap/skew-heap.js +0 -114
- package/cjs/heap.js +0 -21
- package/cjs/list/basics.js +0 -88
- package/cjs/list/core.js +0 -305
- package/cjs/list/ext-value.js +0 -88
- package/cjs/list/ext.js +0 -356
- package/cjs/list/nodes.js +0 -240
- package/cjs/list/ptr.js +0 -61
- package/cjs/list/value.js +0 -99
- package/cjs/list-helpers.js +0 -91
- package/cjs/list-utils.js +0 -141
- package/cjs/list.js +0 -21
- package/cjs/meta-utils.js +0 -171
- package/cjs/nt-utils.js +0 -132
- package/cjs/package.json +0 -1
- package/cjs/queue.js +0 -58
- package/cjs/slist/basics.js +0 -71
- package/cjs/slist/core.js +0 -362
- package/cjs/slist/ext-value.js +0 -82
- package/cjs/slist/ext.js +0 -336
- package/cjs/slist/nodes.js +0 -276
- package/cjs/slist/ptr.js +0 -87
- package/cjs/slist/value.js +0 -90
- package/cjs/slist.js +0 -21
- package/cjs/stack.js +0 -55
- package/cjs/tree/splay-tree.js +0 -362
- package/cjs/value-list.js +0 -21
- package/cjs/value-slist.js +0 -21
package/src/slist/basics.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Extract a range of nodes from a circular SLL.
|
|
3
|
+
* @param {object} options - Link property names.
|
|
4
|
+
* @param {object} range - Range descriptor with `prevFrom` and optional `to`.
|
|
5
|
+
* @returns {{extracted: {prevFrom: object, to: object}, rest: object|null}} The extracted sub-list and the remaining list.
|
|
6
|
+
*/
|
|
5
7
|
export const extract = ({nextName}, {prevFrom, to = prevFrom[nextName]}) => {
|
|
6
8
|
const node = prevFrom[nextName],
|
|
7
9
|
next = to[nextName];
|
|
@@ -15,8 +17,12 @@ export const extract = ({nextName}, {prevFrom, to = prevFrom[nextName]}) => {
|
|
|
15
17
|
return {extracted: {prevFrom: to, to}, rest: next === node ? null : next};
|
|
16
18
|
};
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Pop a single node out of its circular SLL.
|
|
22
|
+
* @param {object} options - Link property names.
|
|
23
|
+
* @param {object} prev - The node preceding the one to pop.
|
|
24
|
+
* @returns {{extracted: {prevFrom: object, to: object}, rest: object|null}} The popped node descriptor and the remaining list.
|
|
25
|
+
*/
|
|
20
26
|
export const pop = ({nextName}, prev) => {
|
|
21
27
|
const node = prev[nextName],
|
|
22
28
|
next = node[nextName];
|
|
@@ -30,6 +36,13 @@ export const pop = ({nextName}, prev) => {
|
|
|
30
36
|
return {extracted: {prevFrom: node, to: node}, rest: next === node ? null : next};
|
|
31
37
|
};
|
|
32
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Splice a range of nodes into a circular SLL after a target node.
|
|
41
|
+
* @param {object} options - Link property names.
|
|
42
|
+
* @param {object} target - Node after which to insert.
|
|
43
|
+
* @param {object} range - Range descriptor with `prevFrom` and optional `to`.
|
|
44
|
+
* @returns {object} The target node.
|
|
45
|
+
*/
|
|
33
46
|
export const splice = ({nextName}, target, {prevFrom, to = prevFrom[nextName]}) => {
|
|
34
47
|
// form the combined head
|
|
35
48
|
const next = target[nextName];
|
|
@@ -42,6 +55,8 @@ export const splice = ({nextName}, target, {prevFrom, to = prevFrom[nextName]})
|
|
|
42
55
|
return target;
|
|
43
56
|
};
|
|
44
57
|
|
|
45
|
-
|
|
46
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Alias for {@link splice}. Extract a range and splice it after a target node.
|
|
60
|
+
* @type {typeof splice}
|
|
61
|
+
*/
|
|
47
62
|
export const append = splice;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import {HeadNode, PtrBase, ExtListBase, SllOptions, SllRange, SllPtrRange} from './nodes.js';
|
|
2
|
+
import {Ptr} from './ptr.js';
|
|
3
|
+
|
|
4
|
+
/** Hosted node-based singly linked list. */
|
|
5
|
+
export class SList<T extends object = object> extends HeadNode {
|
|
6
|
+
/** The first node after the head. */
|
|
7
|
+
get front(): T;
|
|
8
|
+
|
|
9
|
+
/** The last node in the list. */
|
|
10
|
+
get back(): T;
|
|
11
|
+
|
|
12
|
+
/** A range spanning all nodes, or `null` if empty. */
|
|
13
|
+
get range(): SllRange<T> | null;
|
|
14
|
+
|
|
15
|
+
/** Pointer to the first node. */
|
|
16
|
+
get frontPtr(): Ptr<T>;
|
|
17
|
+
|
|
18
|
+
/** A pointer-based range spanning all nodes, or `null` if empty. */
|
|
19
|
+
get ptrRange(): SllPtrRange<T> | null;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a pointer to a node in this list.
|
|
23
|
+
* @param node - Target node, or `undefined` for the front.
|
|
24
|
+
* @returns A new Ptr.
|
|
25
|
+
*/
|
|
26
|
+
makePtr(node?: T): Ptr<T>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create a pointer to the node after `prev`.
|
|
30
|
+
* @param prev - Preceding node, or `undefined` for the front.
|
|
31
|
+
* @returns A new Ptr.
|
|
32
|
+
*/
|
|
33
|
+
makePtrFromPrev(prev?: T): Ptr<T>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Remove and return the front node.
|
|
37
|
+
* @returns The removed node, or `undefined` if empty.
|
|
38
|
+
*/
|
|
39
|
+
popFrontNode(): T | undefined;
|
|
40
|
+
|
|
41
|
+
/** Alias for {@link popFrontNode}. */
|
|
42
|
+
popFront(): T | undefined;
|
|
43
|
+
|
|
44
|
+
/** Alias for {@link popFrontNode}. */
|
|
45
|
+
pop(): T | undefined;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Insert a value at the front.
|
|
49
|
+
* @param value - Node or value to insert.
|
|
50
|
+
* @returns A Ptr to the front.
|
|
51
|
+
*/
|
|
52
|
+
pushFront(value: T | PtrBase<T>): Ptr<T>;
|
|
53
|
+
|
|
54
|
+
/** Alias for {@link pushFront}. */
|
|
55
|
+
push(value: T | PtrBase<T>): Ptr<T>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Insert a value at the back.
|
|
59
|
+
* @param value - Node or value to insert.
|
|
60
|
+
* @returns A Ptr to the inserted node.
|
|
61
|
+
*/
|
|
62
|
+
pushBack(value: T | PtrBase<T>): Ptr<T>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Insert an existing node at the front.
|
|
66
|
+
* @param nodeOrPtr - Node or pointer to insert.
|
|
67
|
+
* @returns A Ptr to the front.
|
|
68
|
+
*/
|
|
69
|
+
pushFrontNode(nodeOrPtr: T | PtrBase<T>): Ptr<T>;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Insert an existing node at the back.
|
|
73
|
+
* @param nodeOrPtr - Node or pointer to insert.
|
|
74
|
+
* @returns A Ptr to the inserted node.
|
|
75
|
+
*/
|
|
76
|
+
pushBackNode(nodeOrPtr: T | PtrBase<T>): Ptr<T>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Move all nodes from another list to the front.
|
|
80
|
+
* @param list - Compatible list to consume.
|
|
81
|
+
* @returns A Ptr to the new front.
|
|
82
|
+
*/
|
|
83
|
+
appendFront(list: HeadNode): Ptr<T>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Move all nodes from another list to the back.
|
|
87
|
+
* @param list - Compatible list to consume.
|
|
88
|
+
* @returns A Ptr to the first appended node.
|
|
89
|
+
*/
|
|
90
|
+
appendBack(list: HeadNode): Ptr<T>;
|
|
91
|
+
|
|
92
|
+
/** Alias for {@link appendBack}. */
|
|
93
|
+
append(list: HeadNode): Ptr<T>;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Move a pointed-to node to the front.
|
|
97
|
+
* @param ptr - Pointer to the node to move.
|
|
98
|
+
* @returns A Ptr to the front, or `this` if at head.
|
|
99
|
+
*/
|
|
100
|
+
moveToFront(ptr: PtrBase<T>): Ptr<T> | this;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Move a pointed-to node to the back.
|
|
104
|
+
* @param ptr - Pointer to the node to move.
|
|
105
|
+
* @returns A Ptr to the back, or `this` if at head.
|
|
106
|
+
*/
|
|
107
|
+
moveToBack(ptr: PtrBase<T>): Ptr<T> | this;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Remove all nodes.
|
|
111
|
+
* @param drop - If `true`, make each removed node stand-alone.
|
|
112
|
+
* @returns `this` for chaining.
|
|
113
|
+
*/
|
|
114
|
+
clear(drop?: boolean): this;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Remove a node via its pointer.
|
|
118
|
+
* @param ptr - Pointer to the node to remove.
|
|
119
|
+
* @returns The removed node, or `null` if at head.
|
|
120
|
+
*/
|
|
121
|
+
removeNode(ptr: PtrBase<T>): T | null;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Remove a pointer-based range and optionally drop nodes.
|
|
125
|
+
* @param ptrRange - Range to remove.
|
|
126
|
+
* @param drop - If `true`, make each removed node stand-alone.
|
|
127
|
+
* @returns A new SList containing the removed nodes.
|
|
128
|
+
*/
|
|
129
|
+
removeRange(ptrRange?: SllPtrRange<T>, drop?: boolean): SList<T>;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Extract a pointer-based range into a new list.
|
|
133
|
+
* @param ptrRange - Range to extract (defaults to the whole list).
|
|
134
|
+
* @returns A new SList containing the extracted nodes.
|
|
135
|
+
*/
|
|
136
|
+
extractRange(ptrRange?: SllPtrRange<T>): SList<T>;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Extract nodes that satisfy a condition into a new list.
|
|
140
|
+
* @param condition - Predicate receiving each node.
|
|
141
|
+
* @returns A new SList containing the extracted nodes.
|
|
142
|
+
*/
|
|
143
|
+
extractBy(condition: (node: T) => boolean): SList<T>;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Reverse the order of all nodes in place.
|
|
147
|
+
* @returns `this` for chaining.
|
|
148
|
+
*/
|
|
149
|
+
reverse(): this;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Sort nodes in place using merge sort.
|
|
153
|
+
* @param lessFn - Returns `true` if `a` should precede `b`.
|
|
154
|
+
* @returns `this` for chaining.
|
|
155
|
+
*/
|
|
156
|
+
sort(lessFn: (a: T, b: T) => boolean): this;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Detach all nodes as a pointer range.
|
|
160
|
+
* @returns A pointer range, or `null` if empty.
|
|
161
|
+
*/
|
|
162
|
+
releaseAsPtrRange(): SllPtrRange<T> | null;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Detach all nodes as a raw circular list.
|
|
166
|
+
* @returns Head of the raw circular list, or `null` if empty.
|
|
167
|
+
*/
|
|
168
|
+
releaseRawList(): T | null;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Detach all nodes as a null-terminated list.
|
|
172
|
+
* @returns Object with `head` and `tail`, or `null` if empty.
|
|
173
|
+
*/
|
|
174
|
+
releaseNTList(): { head: T; tail: T } | null;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Validate that a range is reachable within this list.
|
|
178
|
+
* @param range - Range to validate.
|
|
179
|
+
* @returns `true` if the range is valid.
|
|
180
|
+
*/
|
|
181
|
+
validateRange(range?: SllRange<T>): boolean;
|
|
182
|
+
|
|
183
|
+
/** Iterate over nodes from front to back. */
|
|
184
|
+
[Symbol.iterator](): IterableIterator<T>;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Get an iterable over nodes in a range.
|
|
188
|
+
* @param range - Sub-range to iterate.
|
|
189
|
+
* @returns An iterable iterator of nodes.
|
|
190
|
+
*/
|
|
191
|
+
getNodeIterator(range?: SllRange<T>): IterableIterator<T>;
|
|
192
|
+
|
|
193
|
+
/** Alias for {@link getNodeIterator}. */
|
|
194
|
+
getIterator(range?: SllRange<T>): IterableIterator<T>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get an iterable of Ptr objects over a pointer range.
|
|
198
|
+
* @param ptrRange - Sub-range to iterate.
|
|
199
|
+
* @returns An iterable iterator of Ptrs.
|
|
200
|
+
*/
|
|
201
|
+
getPtrIterator(ptrRange?: SllPtrRange<T>): IterableIterator<Ptr<T>>;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Create an empty list with the same options.
|
|
205
|
+
* @returns A new empty SList.
|
|
206
|
+
*/
|
|
207
|
+
make(): SList<T>;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Create a list from values with the same options.
|
|
211
|
+
* @param values - Iterable of node objects.
|
|
212
|
+
* @returns A new SList.
|
|
213
|
+
*/
|
|
214
|
+
makeFrom(values: Iterable<T>): SList<T>;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Create a list from a range with the same options.
|
|
218
|
+
* @param range - Range to copy.
|
|
219
|
+
* @returns A new SList.
|
|
220
|
+
*/
|
|
221
|
+
makeFromRange(range: SllRange<T>): SList<T>;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Build an SList from an iterable of node objects.
|
|
225
|
+
* @param values - Iterable of nodes.
|
|
226
|
+
* @param options - Link property names.
|
|
227
|
+
* @returns A new SList.
|
|
228
|
+
*/
|
|
229
|
+
static from<T extends object = object>(values: Iterable<T>, options?: SllOptions): SList<T>;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Build an SList from a pointer range.
|
|
233
|
+
* @param ptrRange - Pointer range to copy.
|
|
234
|
+
* @param options - Link property names.
|
|
235
|
+
* @returns A new SList.
|
|
236
|
+
*/
|
|
237
|
+
static fromPtrRange<T extends object = object>(ptrRange: SllPtrRange<T>, options?: SllOptions): SList<T>;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Build an SList from an external list, consuming it.
|
|
241
|
+
* @param extList - External list to consume.
|
|
242
|
+
* @returns A new SList.
|
|
243
|
+
*/
|
|
244
|
+
static fromExtList<T extends object = object>(extList: ExtListBase<T>): SList<T>;
|
|
245
|
+
|
|
246
|
+
/** The Ptr class associated with this list type. */
|
|
247
|
+
static Ptr: typeof Ptr;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export { Ptr };
|
|
251
|
+
export default SList;
|
package/src/slist/core.js
CHANGED
|
@@ -1,29 +1,44 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
import {addAliases, normalizeIterator} from '../meta-utils.js';
|
|
4
2
|
import {ExtListBase, HeadNode} from './nodes.js';
|
|
5
3
|
import {append} from './basics.js';
|
|
6
4
|
import Ptr from './ptr.js';
|
|
7
5
|
|
|
6
|
+
/** Hosted node-based singly linked list with a sentinel head. */
|
|
8
7
|
export class SList extends HeadNode {
|
|
8
|
+
/** Pointer to the first node. */
|
|
9
9
|
get frontPtr() {
|
|
10
10
|
return new Ptr(this);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/** A pointer-based range spanning all nodes, or `null` if empty. */
|
|
13
14
|
get ptrRange() {
|
|
14
15
|
return this.isEmpty ? null : {from: new Ptr(this), to: this.last};
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Create a pointer to a node in this list.
|
|
20
|
+
* @param {object} [node] - Target node, or `undefined` for the front.
|
|
21
|
+
* @returns {Ptr} A new Ptr.
|
|
22
|
+
*/
|
|
17
23
|
makePtr(node) {
|
|
18
24
|
if (node && !this.isNodeLike(node)) throw new Error('"node" is not a compatible node');
|
|
19
25
|
return new Ptr(this, node);
|
|
20
26
|
}
|
|
21
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Create a pointer to the node after `prev`.
|
|
30
|
+
* @param {object} [prev] - Preceding node, or `undefined` for the head.
|
|
31
|
+
* @returns {Ptr} A new Ptr.
|
|
32
|
+
*/
|
|
22
33
|
makePtrFromPrev(prev) {
|
|
23
34
|
if (prev && !this.isNodeLike(prev)) throw new Error('"prev" is not a compatible node');
|
|
24
35
|
return new Ptr(this, null, prev || this);
|
|
25
36
|
}
|
|
26
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Remove and return the front node.
|
|
40
|
+
* @returns {object|undefined} The removed node, or `undefined` if empty.
|
|
41
|
+
*/
|
|
27
42
|
popFrontNode() {
|
|
28
43
|
if (this[this.nextName] === this) return undefined;
|
|
29
44
|
const node = this[this.nextName];
|
|
@@ -32,6 +47,11 @@ export class SList extends HeadNode {
|
|
|
32
47
|
return (node[this.nextName] = node);
|
|
33
48
|
}
|
|
34
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Insert a value at the front.
|
|
52
|
+
* @param {*} value - Node or value to insert.
|
|
53
|
+
* @returns {Ptr} A Ptr to the front.
|
|
54
|
+
*/
|
|
35
55
|
pushFront(value) {
|
|
36
56
|
const node = this.adoptValue(value);
|
|
37
57
|
node[this.nextName] = this[this.nextName];
|
|
@@ -40,6 +60,11 @@ export class SList extends HeadNode {
|
|
|
40
60
|
return this.makePtr();
|
|
41
61
|
}
|
|
42
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Insert a value at the back.
|
|
65
|
+
* @param {*} value - Node or value to insert.
|
|
66
|
+
* @returns {Ptr} A Ptr to the inserted node.
|
|
67
|
+
*/
|
|
43
68
|
pushBack(value) {
|
|
44
69
|
const node = this.adoptValue(value);
|
|
45
70
|
node[this.nextName] = this;
|
|
@@ -48,6 +73,11 @@ export class SList extends HeadNode {
|
|
|
48
73
|
return this.makePtrFromPrev(last);
|
|
49
74
|
}
|
|
50
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Insert an existing node at the front.
|
|
78
|
+
* @param {object} nodeOrPtr - Node or pointer to insert.
|
|
79
|
+
* @returns {Ptr} A Ptr to the front.
|
|
80
|
+
*/
|
|
51
81
|
pushFrontNode(nodeOrPtr) {
|
|
52
82
|
const node = this.adoptNode(nodeOrPtr);
|
|
53
83
|
node[this.nextName] = this[this.nextName];
|
|
@@ -56,6 +86,11 @@ export class SList extends HeadNode {
|
|
|
56
86
|
return this.makePtr();
|
|
57
87
|
}
|
|
58
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Insert an existing node at the back.
|
|
91
|
+
* @param {object} nodeOrPtr - Node or pointer to insert.
|
|
92
|
+
* @returns {Ptr} A Ptr to the inserted node.
|
|
93
|
+
*/
|
|
59
94
|
pushBackNode(nodeOrPtr) {
|
|
60
95
|
const node = this.adoptNode(nodeOrPtr);
|
|
61
96
|
node[this.nextName] = this;
|
|
@@ -64,6 +99,11 @@ export class SList extends HeadNode {
|
|
|
64
99
|
return this.makePtrFromPrev(last);
|
|
65
100
|
}
|
|
66
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Move all nodes from another list to the front.
|
|
104
|
+
* @param {HeadNode} list - Compatible list to consume.
|
|
105
|
+
* @returns {Ptr} A Ptr to the new front.
|
|
106
|
+
*/
|
|
67
107
|
appendFront(list) {
|
|
68
108
|
if (!this.isCompatible(list)) throw new Error('Incompatible lists');
|
|
69
109
|
if (list.isEmpty) return this;
|
|
@@ -76,6 +116,11 @@ export class SList extends HeadNode {
|
|
|
76
116
|
return this.makePtr();
|
|
77
117
|
}
|
|
78
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Move all nodes from another list to the back.
|
|
121
|
+
* @param {HeadNode} list - Compatible list to consume.
|
|
122
|
+
* @returns {Ptr} A Ptr to the first appended node.
|
|
123
|
+
*/
|
|
79
124
|
appendBack(list) {
|
|
80
125
|
if (!this.isCompatible(list)) throw new Error('Incompatible lists');
|
|
81
126
|
if (list.isEmpty) return this;
|
|
@@ -90,6 +135,11 @@ export class SList extends HeadNode {
|
|
|
90
135
|
return this.makePtrFromPrev(last);
|
|
91
136
|
}
|
|
92
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Move a node (identified by pointer) to the front.
|
|
140
|
+
* @param {Ptr} ptr - Pointer to the node to move.
|
|
141
|
+
* @returns {Ptr|SList} A Ptr to the front, or `this` if at head.
|
|
142
|
+
*/
|
|
93
143
|
moveToFront(ptr) {
|
|
94
144
|
if (!this.isCompatiblePtr(ptr)) throw new Error('Incompatible pointer');
|
|
95
145
|
ptr.list = this;
|
|
@@ -99,6 +149,11 @@ export class SList extends HeadNode {
|
|
|
99
149
|
return this.pushFrontNode(node);
|
|
100
150
|
}
|
|
101
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Move a node (identified by pointer) to the back.
|
|
154
|
+
* @param {Ptr} ptr - Pointer to the node to move.
|
|
155
|
+
* @returns {Ptr|SList} A Ptr to the back, or `this` if at head.
|
|
156
|
+
*/
|
|
102
157
|
moveToBack(ptr) {
|
|
103
158
|
if (!this.isCompatiblePtr(ptr)) throw new Error('Incompatible pointer');
|
|
104
159
|
ptr.list = this;
|
|
@@ -108,6 +163,11 @@ export class SList extends HeadNode {
|
|
|
108
163
|
return this.pushBackNode(node);
|
|
109
164
|
}
|
|
110
165
|
|
|
166
|
+
/**
|
|
167
|
+
* Remove all nodes.
|
|
168
|
+
* @param {boolean} [drop] - If `true`, make each removed node stand-alone.
|
|
169
|
+
* @returns {SList} `this` for chaining.
|
|
170
|
+
*/
|
|
111
171
|
clear(drop) {
|
|
112
172
|
if (drop) {
|
|
113
173
|
let current = this;
|
|
@@ -123,6 +183,11 @@ export class SList extends HeadNode {
|
|
|
123
183
|
return this;
|
|
124
184
|
}
|
|
125
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Remove the node at a pointer position.
|
|
188
|
+
* @param {Ptr} ptr - Pointer whose current node to remove.
|
|
189
|
+
* @returns {object|null} The removed node, or `null` if at head.
|
|
190
|
+
*/
|
|
126
191
|
removeNode(ptr) {
|
|
127
192
|
if (!ptr.isPrevNodeValid()) throw new Error('Cannot remove node: "prevNode" is invalid');
|
|
128
193
|
if (!this.isCompatiblePtr(ptr)) throw new Error('Incompatible pointer');
|
|
@@ -135,10 +200,21 @@ export class SList extends HeadNode {
|
|
|
135
200
|
return node;
|
|
136
201
|
}
|
|
137
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Remove a pointer-based range and optionally drop nodes.
|
|
205
|
+
* @param {object} [ptrRange] - Range to remove.
|
|
206
|
+
* @param {boolean} [drop] - If `true`, make each removed node stand-alone.
|
|
207
|
+
* @returns {SList} A new SList containing the removed nodes.
|
|
208
|
+
*/
|
|
138
209
|
removeRange(ptrRange, drop) {
|
|
139
210
|
return this.extractRange(ptrRange).clear(drop);
|
|
140
211
|
}
|
|
141
212
|
|
|
213
|
+
/**
|
|
214
|
+
* Extract a pointer-based range into a new list.
|
|
215
|
+
* @param {object} [ptrRange={}] - Range to extract (defaults to the whole list).
|
|
216
|
+
* @returns {SList} A new SList containing the extracted nodes.
|
|
217
|
+
*/
|
|
142
218
|
extractRange(ptrRange = {}) {
|
|
143
219
|
const originalTo = ptrRange.to;
|
|
144
220
|
ptrRange = this.normalizePtrRange(ptrRange.from ? ptrRange : {...ptrRange, from: this.frontPtr});
|
|
@@ -156,6 +232,11 @@ export class SList extends HeadNode {
|
|
|
156
232
|
return extracted;
|
|
157
233
|
}
|
|
158
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Extract nodes that satisfy a condition into a new list.
|
|
237
|
+
* @param {Function} condition - Predicate receiving each node.
|
|
238
|
+
* @returns {SList} A new SList containing the extracted nodes.
|
|
239
|
+
*/
|
|
159
240
|
extractBy(condition) {
|
|
160
241
|
const extracted = this.make();
|
|
161
242
|
if (this.isEmpty) return extracted;
|
|
@@ -170,6 +251,10 @@ export class SList extends HeadNode {
|
|
|
170
251
|
return extracted;
|
|
171
252
|
}
|
|
172
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Reverse the order of all nodes in place.
|
|
256
|
+
* @returns {SList} `this` for chaining.
|
|
257
|
+
*/
|
|
173
258
|
reverse() {
|
|
174
259
|
if (this.isOneOrEmpty) return this;
|
|
175
260
|
this.last = this[this.nextName];
|
|
@@ -185,6 +270,11 @@ export class SList extends HeadNode {
|
|
|
185
270
|
return this;
|
|
186
271
|
}
|
|
187
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Sort nodes in place using merge sort.
|
|
275
|
+
* @param {Function} lessFn - Returns `true` if `a` should precede `b`.
|
|
276
|
+
* @returns {SList} `this` for chaining.
|
|
277
|
+
*/
|
|
188
278
|
sort(lessFn) {
|
|
189
279
|
if (this.isOneOrEmpty) return this;
|
|
190
280
|
|
|
@@ -211,6 +301,10 @@ export class SList extends HeadNode {
|
|
|
211
301
|
return this;
|
|
212
302
|
}
|
|
213
303
|
|
|
304
|
+
/**
|
|
305
|
+
* Detach all nodes as a pointer range.
|
|
306
|
+
* @returns {object|null} A pointer range, or `null` if empty.
|
|
307
|
+
*/
|
|
214
308
|
releaseAsPtrRange() {
|
|
215
309
|
if (this.isEmpty) return null;
|
|
216
310
|
const head = this[this.nextName],
|
|
@@ -220,6 +314,10 @@ export class SList extends HeadNode {
|
|
|
220
314
|
return {from: new Ptr(this, null, tail), to: tail};
|
|
221
315
|
}
|
|
222
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Detach all nodes as a raw circular list.
|
|
319
|
+
* @returns {object|null} Head of the raw circular list, or `null` if empty.
|
|
320
|
+
*/
|
|
223
321
|
releaseRawList() {
|
|
224
322
|
if (this.isEmpty) return null;
|
|
225
323
|
const head = this[this.nextName],
|
|
@@ -229,6 +327,10 @@ export class SList extends HeadNode {
|
|
|
229
327
|
return head;
|
|
230
328
|
}
|
|
231
329
|
|
|
330
|
+
/**
|
|
331
|
+
* Detach all nodes as a null-terminated list.
|
|
332
|
+
* @returns {{head: object, tail: object}|null} Object with `head` and `tail`, or `null` if empty.
|
|
333
|
+
*/
|
|
232
334
|
releaseNTList() {
|
|
233
335
|
if (this.isEmpty) return null;
|
|
234
336
|
const head = this[this.nextName],
|
|
@@ -238,6 +340,11 @@ export class SList extends HeadNode {
|
|
|
238
340
|
return {head, tail};
|
|
239
341
|
}
|
|
240
342
|
|
|
343
|
+
/**
|
|
344
|
+
* Validate that a range is reachable within this list.
|
|
345
|
+
* @param {object} [range={}] - Range to validate.
|
|
346
|
+
* @returns {boolean} `true` if the range is valid.
|
|
347
|
+
*/
|
|
241
348
|
validateRange(range = {}) {
|
|
242
349
|
range = this.normalizeRange(range);
|
|
243
350
|
let current = range.from;
|
|
@@ -248,8 +355,7 @@ export class SList extends HeadNode {
|
|
|
248
355
|
return true;
|
|
249
356
|
}
|
|
250
357
|
|
|
251
|
-
|
|
252
|
-
|
|
358
|
+
/** Iterate over nodes from front to back. */
|
|
253
359
|
[Symbol.iterator]() {
|
|
254
360
|
let current = this[this.nextName],
|
|
255
361
|
readyToStop = this.isEmpty;
|
|
@@ -264,6 +370,11 @@ export class SList extends HeadNode {
|
|
|
264
370
|
});
|
|
265
371
|
}
|
|
266
372
|
|
|
373
|
+
/**
|
|
374
|
+
* Get an iterable over nodes in a range.
|
|
375
|
+
* @param {object} [range={}] - Sub-range to iterate.
|
|
376
|
+
* @returns {Iterable} An iterable iterator of nodes.
|
|
377
|
+
*/
|
|
267
378
|
getNodeIterator(range = {}) {
|
|
268
379
|
range = this.normalizeRange(range);
|
|
269
380
|
const {from, to} = range;
|
|
@@ -285,6 +396,11 @@ export class SList extends HeadNode {
|
|
|
285
396
|
};
|
|
286
397
|
}
|
|
287
398
|
|
|
399
|
+
/**
|
|
400
|
+
* Get an iterable of Ptr objects over a pointer range.
|
|
401
|
+
* @param {object} [ptrRange={}] - Sub-range to iterate.
|
|
402
|
+
* @returns {Iterable} An iterable iterator of Ptrs.
|
|
403
|
+
*/
|
|
288
404
|
getPtrIterator(ptrRange = {}) {
|
|
289
405
|
if (!ptrRange.from) ptrRange = Object.assign({from: this.frontPtr}, ptrRange);
|
|
290
406
|
ptrRange = this.normalizePtrRange(ptrRange);
|
|
@@ -307,26 +423,50 @@ export class SList extends HeadNode {
|
|
|
307
423
|
};
|
|
308
424
|
}
|
|
309
425
|
|
|
310
|
-
|
|
311
|
-
|
|
426
|
+
/**
|
|
427
|
+
* Create an empty list with the same options.
|
|
428
|
+
* @returns {SList} A new empty SList.
|
|
429
|
+
*/
|
|
312
430
|
make() {
|
|
313
431
|
return new SList(this);
|
|
314
432
|
}
|
|
315
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Create a list from values with the same options.
|
|
436
|
+
* @param {Iterable} values - Iterable of node objects.
|
|
437
|
+
* @returns {SList} A new SList.
|
|
438
|
+
*/
|
|
316
439
|
makeFrom(values) {
|
|
317
440
|
return SList.from(values, this);
|
|
318
441
|
}
|
|
319
442
|
|
|
443
|
+
/**
|
|
444
|
+
* Create a list from a range with the same options.
|
|
445
|
+
* @param {object} range - Range to copy.
|
|
446
|
+
* @returns {SList} A new SList.
|
|
447
|
+
*/
|
|
320
448
|
makeFromRange(range) {
|
|
321
449
|
return SList.fromRange(range, this);
|
|
322
450
|
}
|
|
323
451
|
|
|
452
|
+
/**
|
|
453
|
+
* Build an SList from an iterable of node objects.
|
|
454
|
+
* @param {Iterable} values - Iterable of nodes.
|
|
455
|
+
* @param {object} [options] - Link property names.
|
|
456
|
+
* @returns {SList} A new SList.
|
|
457
|
+
*/
|
|
324
458
|
static from(values, options) {
|
|
325
459
|
const list = new SList(options);
|
|
326
460
|
for (const value of values) list.pushBack(value);
|
|
327
461
|
return list;
|
|
328
462
|
}
|
|
329
463
|
|
|
464
|
+
/**
|
|
465
|
+
* Build an SList from a pointer range.
|
|
466
|
+
* @param {object} ptrRange - Pointer range to copy.
|
|
467
|
+
* @param {object} [options] - Link property names.
|
|
468
|
+
* @returns {SList} A new SList.
|
|
469
|
+
*/
|
|
330
470
|
static fromPtrRange(ptrRange, options) {
|
|
331
471
|
const list = new SList(options);
|
|
332
472
|
if (!list.isCompatiblePtrRange(ptrRange)) throw new Error('"range" is not a compatible range');
|
|
@@ -334,6 +474,11 @@ export class SList extends HeadNode {
|
|
|
334
474
|
return list;
|
|
335
475
|
}
|
|
336
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Build an SList from an external list, consuming it.
|
|
479
|
+
* @param {ExtListBase} extList - External list to consume.
|
|
480
|
+
* @returns {SList} A new SList.
|
|
481
|
+
*/
|
|
337
482
|
static fromExtList(extList) {
|
|
338
483
|
if (!(extList instanceof ExtListBase)) throw new Error('Not a circular list');
|
|
339
484
|
|