data-structure-typed 2.5.3 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/.github/workflows/ci.yml +7 -2
  2. package/.github/workflows/release-package.yml +9 -2
  3. package/.husky/pre-commit +3 -0
  4. package/CHANGELOG.md +1 -1
  5. package/MIGRATION.md +48 -0
  6. package/README.md +20 -2
  7. package/README_CN.md +20 -2
  8. package/SPECIFICATION.md +24 -0
  9. package/SPECIFICATION.zh-CN.md +24 -0
  10. package/dist/cjs/binary-tree.cjs +1897 -19
  11. package/dist/cjs/graph.cjs +174 -0
  12. package/dist/cjs/hash.cjs +33 -0
  13. package/dist/cjs/heap.cjs +71 -0
  14. package/dist/cjs/index.cjs +2383 -3
  15. package/dist/cjs/linked-list.cjs +224 -2
  16. package/dist/cjs/matrix.cjs +24 -0
  17. package/dist/cjs/priority-queue.cjs +71 -0
  18. package/dist/cjs/queue.cjs +221 -1
  19. package/dist/cjs/stack.cjs +59 -0
  20. package/dist/cjs/trie.cjs +62 -0
  21. package/dist/cjs-legacy/binary-tree.cjs +1897 -19
  22. package/dist/cjs-legacy/graph.cjs +174 -0
  23. package/dist/cjs-legacy/hash.cjs +33 -0
  24. package/dist/cjs-legacy/heap.cjs +71 -0
  25. package/dist/cjs-legacy/index.cjs +2383 -3
  26. package/dist/cjs-legacy/linked-list.cjs +224 -2
  27. package/dist/cjs-legacy/matrix.cjs +24 -0
  28. package/dist/cjs-legacy/priority-queue.cjs +71 -0
  29. package/dist/cjs-legacy/queue.cjs +221 -1
  30. package/dist/cjs-legacy/stack.cjs +59 -0
  31. package/dist/cjs-legacy/trie.cjs +62 -0
  32. package/dist/esm/binary-tree.mjs +1897 -19
  33. package/dist/esm/graph.mjs +174 -0
  34. package/dist/esm/hash.mjs +33 -0
  35. package/dist/esm/heap.mjs +71 -0
  36. package/dist/esm/index.mjs +2383 -3
  37. package/dist/esm/linked-list.mjs +224 -2
  38. package/dist/esm/matrix.mjs +24 -0
  39. package/dist/esm/priority-queue.mjs +71 -0
  40. package/dist/esm/queue.mjs +221 -1
  41. package/dist/esm/stack.mjs +59 -0
  42. package/dist/esm/trie.mjs +62 -0
  43. package/dist/esm-legacy/binary-tree.mjs +1897 -19
  44. package/dist/esm-legacy/graph.mjs +174 -0
  45. package/dist/esm-legacy/hash.mjs +33 -0
  46. package/dist/esm-legacy/heap.mjs +71 -0
  47. package/dist/esm-legacy/index.mjs +2383 -3
  48. package/dist/esm-legacy/linked-list.mjs +224 -2
  49. package/dist/esm-legacy/matrix.mjs +24 -0
  50. package/dist/esm-legacy/priority-queue.mjs +71 -0
  51. package/dist/esm-legacy/queue.mjs +221 -1
  52. package/dist/esm-legacy/stack.mjs +59 -0
  53. package/dist/esm-legacy/trie.mjs +62 -0
  54. package/dist/types/data-structures/base/iterable-element-base.d.ts +17 -0
  55. package/dist/types/data-structures/base/linear-base.d.ts +6 -0
  56. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +36 -0
  57. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +42 -0
  58. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +75 -0
  59. package/dist/types/data-structures/binary-tree/bst.d.ts +72 -0
  60. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +57 -0
  61. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +18 -0
  62. package/dist/types/data-structures/binary-tree/tree-map.d.ts +375 -0
  63. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +389 -0
  64. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +330 -0
  65. package/dist/types/data-structures/binary-tree/tree-set.d.ts +438 -0
  66. package/dist/types/data-structures/graph/directed-graph.d.ts +30 -0
  67. package/dist/types/data-structures/graph/undirected-graph.d.ts +27 -0
  68. package/dist/types/data-structures/hash/hash-map.d.ts +33 -0
  69. package/dist/types/data-structures/heap/heap.d.ts +42 -0
  70. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +75 -2
  71. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +45 -0
  72. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +54 -0
  73. package/dist/types/data-structures/matrix/matrix.d.ts +24 -0
  74. package/dist/types/data-structures/queue/deque.d.ts +90 -1
  75. package/dist/types/data-structures/queue/queue.d.ts +36 -0
  76. package/dist/types/data-structures/stack/stack.d.ts +30 -0
  77. package/dist/types/data-structures/trie/trie.d.ts +36 -0
  78. package/dist/umd/data-structure-typed.js +2383 -3
  79. package/dist/umd/data-structure-typed.min.js +3 -3
  80. package/docs-site-docusaurus/docs/api/classes/AVLTree.md +108 -108
  81. package/docs-site-docusaurus/docs/api/classes/BST.md +101 -101
  82. package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +13 -13
  83. package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +66 -66
  84. package/docs-site-docusaurus/docs/api/classes/Deque.md +235 -51
  85. package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +21 -21
  86. package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +231 -67
  87. package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +9 -9
  88. package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
  89. package/docs-site-docusaurus/docs/api/classes/HashMap.md +14 -14
  90. package/docs-site-docusaurus/docs/api/classes/Heap.md +117 -34
  91. package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +83 -13
  92. package/docs-site-docusaurus/docs/api/classes/LinearBase.md +124 -20
  93. package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +140 -32
  94. package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +30 -26
  95. package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +159 -51
  96. package/docs-site-docusaurus/docs/api/classes/MapGraph.md +20 -20
  97. package/docs-site-docusaurus/docs/api/classes/Matrix.md +23 -23
  98. package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +117 -34
  99. package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +117 -34
  100. package/docs-site-docusaurus/docs/api/classes/MinHeap.md +117 -34
  101. package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +117 -34
  102. package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +117 -34
  103. package/docs-site-docusaurus/docs/api/classes/Queue.md +142 -34
  104. package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +117 -117
  105. package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +8 -8
  106. package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +158 -50
  107. package/docs-site-docusaurus/docs/api/classes/SkipList.md +21 -21
  108. package/docs-site-docusaurus/docs/api/classes/Stack.md +108 -26
  109. package/docs-site-docusaurus/docs/api/classes/TreeMap.md +33 -33
  110. package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +75 -39
  111. package/docs-site-docusaurus/docs/api/classes/TreeSet.md +301 -39
  112. package/docs-site-docusaurus/docs/api/classes/Trie.md +110 -28
  113. package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +20 -20
  114. package/jest.integration.config.js +1 -2
  115. package/package.json +51 -50
  116. package/src/common/error.ts +15 -32
  117. package/src/common/index.ts +0 -3
  118. package/src/data-structures/base/iterable-element-base.ts +32 -3
  119. package/src/data-structures/base/linear-base.ts +13 -36
  120. package/src/data-structures/binary-tree/avl-tree.ts +31 -493
  121. package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -530
  122. package/src/data-structures/binary-tree/binary-tree.ts +326 -1236
  123. package/src/data-structures/binary-tree/bst.ts +158 -1010
  124. package/src/data-structures/binary-tree/red-black-tree.ts +451 -1233
  125. package/src/data-structures/binary-tree/segment-tree.ts +73 -333
  126. package/src/data-structures/binary-tree/tree-map.ts +462 -4749
  127. package/src/data-structures/binary-tree/tree-multi-map.ts +310 -4530
  128. package/src/data-structures/binary-tree/tree-multi-set.ts +300 -3652
  129. package/src/data-structures/binary-tree/tree-set.ts +437 -4443
  130. package/src/data-structures/graph/abstract-graph.ts +98 -167
  131. package/src/data-structures/graph/directed-graph.ts +137 -532
  132. package/src/data-structures/graph/map-graph.ts +0 -3
  133. package/src/data-structures/graph/undirected-graph.ts +132 -484
  134. package/src/data-structures/hash/hash-map.ts +154 -549
  135. package/src/data-structures/heap/heap.ts +200 -753
  136. package/src/data-structures/linked-list/doubly-linked-list.ts +153 -809
  137. package/src/data-structures/linked-list/singly-linked-list.ts +122 -749
  138. package/src/data-structures/linked-list/skip-linked-list.ts +211 -864
  139. package/src/data-structures/matrix/matrix.ts +179 -494
  140. package/src/data-structures/matrix/navigator.ts +0 -1
  141. package/src/data-structures/priority-queue/max-priority-queue.ts +1 -6
  142. package/src/data-structures/priority-queue/min-priority-queue.ts +6 -11
  143. package/src/data-structures/priority-queue/priority-queue.ts +1 -2
  144. package/src/data-structures/queue/deque.ts +241 -807
  145. package/src/data-structures/queue/queue.ts +102 -589
  146. package/src/data-structures/stack/stack.ts +76 -475
  147. package/src/data-structures/trie/trie.ts +98 -592
  148. package/src/types/common.ts +0 -10
  149. package/src/types/data-structures/binary-tree/bst.ts +0 -7
  150. package/src/types/data-structures/binary-tree/red-black-tree.ts +0 -1
  151. package/src/types/data-structures/graph/abstract-graph.ts +0 -2
  152. package/src/types/data-structures/hash/hash-map.ts +0 -3
  153. package/src/types/data-structures/hash/index.ts +0 -1
  154. package/src/types/data-structures/matrix/navigator.ts +0 -2
  155. package/src/types/utils/utils.ts +0 -7
  156. package/src/types/utils/validate-type.ts +0 -7
  157. package/src/utils/number.ts +0 -2
  158. package/src/utils/utils.ts +0 -5
@@ -5,7 +5,6 @@
5
5
  * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
-
9
8
  import type { Comparator, EntryCallback } from '../../types';
10
9
  import { ERR, raise } from '../../common';
11
10
  import { IterableEntryBase } from '../base';
@@ -28,13 +27,11 @@ export type SkipListOptions<K, V, R = [K, V]> = {
28
27
  maxLevel?: number;
29
28
  probability?: number;
30
29
  };
31
-
32
30
  export type SkipListRangeOptions = {
33
31
  lowInclusive?: boolean;
34
32
  highInclusive?: boolean;
35
33
  };
36
34
 
37
-
38
35
  /**
39
36
  * SkipList — a probabilistic sorted key-value container.
40
37
  *
@@ -47,24 +44,20 @@ export type SkipListRangeOptions = {
47
44
  * expect(() => sl.print()).not.toThrow();
48
45
  */
49
46
  export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V | undefined> {
47
+ // ─── Internal state ──────────────────────────────────────────
48
+ protected _head: SkipListNode<K, V>;
49
+ protected _level: number = 0;
50
50
  readonly #comparator: Comparator<K>;
51
51
  readonly #isDefaultComparator: boolean;
52
52
 
53
- constructor(
54
- entries: Iterable<R> | Iterable<[K, V | undefined]> = [],
55
- options: SkipListOptions<K, V, R> = {}
56
- ) {
53
+ constructor(entries: Iterable<R> | Iterable<[K, V | undefined]> = [], options: SkipListOptions<K, V, R> = {}) {
57
54
  super();
58
55
  const { comparator, toEntryFn, maxLevel, probability } = options;
59
-
60
56
  if (typeof maxLevel === 'number' && maxLevel > 0) this._maxLevel = maxLevel;
61
57
  if (typeof probability === 'number' && probability > 0 && probability < 1) this._probability = probability;
62
-
63
58
  this.#isDefaultComparator = comparator === undefined;
64
59
  this.#comparator = comparator ?? SkipList.createDefaultComparator<K>();
65
-
66
60
  this._head = new SkipListNode<K, V>(undefined as K, undefined as V, this._maxLevel);
67
-
68
61
  for (const item of entries) {
69
62
  let k: K;
70
63
  let v: V | undefined;
@@ -80,6 +73,29 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
80
73
  }
81
74
  }
82
75
 
76
+ protected _size: number = 0;
77
+
78
+ // ─── Size & lifecycle ────────────────────────────────────────
79
+ get size(): number {
80
+ return this._size;
81
+ }
82
+
83
+ protected _maxLevel: number = 16;
84
+
85
+ get maxLevel(): number {
86
+ return this._maxLevel;
87
+ }
88
+
89
+ protected _probability: number = 0.5;
90
+
91
+ get probability(): number {
92
+ return this._probability;
93
+ }
94
+
95
+ get comparator(): Comparator<K> {
96
+ return this.#comparator;
97
+ }
98
+
83
99
  /**
84
100
  * Creates a default comparator supporting number, string, Date, and bigint.
85
101
  */
@@ -105,126 +121,27 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
105
121
  };
106
122
  }
107
123
 
108
- // ─── Internal state ──────────────────────────────────────────
109
-
110
- protected _head: SkipListNode<K, V>;
111
-
112
- protected _level: number = 0;
113
-
114
- protected _size: number = 0;
115
-
116
- protected _maxLevel: number = 16;
117
-
118
- protected _probability: number = 0.5;
119
-
120
- // ─── Size & lifecycle ────────────────────────────────────────
121
-
122
- get size(): number {
123
- return this._size;
124
- }
125
-
126
- get maxLevel(): number {
127
- return this._maxLevel;
128
- }
129
-
130
- get probability(): number {
131
- return this._probability;
132
- }
133
-
134
- get comparator(): Comparator<K> {
135
- return this.#comparator;
136
- }
137
-
138
- /**
124
+ /**
139
125
  * Check if empty
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
- * @example
177
- * // Check if empty
178
- * const sl = new SkipList<number, string>();
179
- * console.log(sl.isEmpty()); // true;
126
+ * @example
127
+ * // Check if empty
128
+ * const sl = new SkipList<number, string>();
129
+ * console.log(sl.isEmpty()); // true;
180
130
  */
181
131
  isEmpty(): boolean {
182
132
  return this._size === 0;
183
133
  }
184
134
 
185
- /**
135
+ /**
186
136
  * Remove all entries
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
- * @example
224
- * // Remove all entries
225
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
226
- * sl.clear();
227
- * console.log(sl.isEmpty()); // true;
137
+ * @example
138
+ * // Remove all entries
139
+ * const sl = new SkipList<number, string>([
140
+ * [1, 'a'],
141
+ * [2, 'b']
142
+ * ]);
143
+ * sl.clear();
144
+ * console.log(sl.isEmpty()); // true;
228
145
  */
229
146
  clear(): void {
230
147
  this._head = new SkipListNode<K, V>(undefined as K, undefined as V, this._maxLevel);
@@ -232,50 +149,17 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
232
149
  this._size = 0;
233
150
  }
234
151
 
235
- /**
152
+ /**
236
153
  * Create independent copy
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
-
249
-
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
- * @example
274
- * // Create independent copy
275
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
276
- * const copy = sl.clone();
277
- * copy.delete(1);
278
- * console.log(sl.has(1)); // true;
154
+ * @example
155
+ * // Create independent copy
156
+ * const sl = new SkipList<number, string>([
157
+ * [1, 'a'],
158
+ * [2, 'b']
159
+ * ]);
160
+ * const copy = sl.clone();
161
+ * copy.delete(1);
162
+ * console.log(sl.has(1)); // true;
279
163
  */
280
164
  clone(): this {
281
165
  return new SkipList<K, V, R>(this as Iterable<[K, V | undefined]>, {
@@ -290,88 +174,44 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
290
174
  /**
291
175
  * Insert or update a key-value pair. Returns `this` for chaining.
292
176
  * Unique keys only — if key exists, value is updated in place.
293
-
294
-
295
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
-
308
-
309
-
310
-
311
-
312
-
313
-
314
-
315
-
316
-
317
-
318
-
319
-
320
-
321
-
322
-
323
-
324
-
325
-
326
-
327
-
328
-
329
-
330
-
331
-
332
- * @example
333
- * // In-memory sorted key-value store
334
- * const store = new SkipList<number, string>();
335
- *
336
- * store.set(3, 'three');
337
- * store.set(1, 'one');
338
- * store.set(5, 'five');
339
- * store.set(2, 'two');
340
- *
341
- * console.log(store.get(3)); // 'three';
342
- * console.log(store.get(1)); // 'one';
343
- * console.log(store.get(5)); // 'five';
344
- *
345
- * // Update existing key
346
- * store.set(3, 'THREE');
347
- * console.log(store.get(3)); // 'THREE';
177
+ * @example
178
+ * // In-memory sorted key-value store
179
+ * const store = new SkipList<number, string>();
180
+ *
181
+ * store.set(3, 'three');
182
+ * store.set(1, 'one');
183
+ * store.set(5, 'five');
184
+ * store.set(2, 'two');
185
+ *
186
+ * console.log(store.get(3)); // 'three';
187
+ * console.log(store.get(1)); // 'one';
188
+ * console.log(store.get(5)); // 'five';
189
+ *
190
+ * // Update existing key
191
+ * store.set(3, 'THREE');
192
+ * console.log(store.get(3)); // 'THREE';
348
193
  */
349
194
  set(key: K, value: V): this {
350
195
  const cmp = this.#comparator;
351
196
  const update = this._findUpdate(key);
352
-
353
197
  // If key already exists, update value in place
354
198
  const existing = update[0].forward[0];
355
199
  if (existing && cmp(existing.key, key) === 0) {
356
200
  existing.value = value;
357
201
  return this;
358
202
  }
359
-
360
203
  const newLevel = this._randomLevel();
361
204
  const newNode = new SkipListNode(key, value, newLevel);
362
-
363
205
  if (newLevel > this._level) {
364
206
  for (let i = this._level; i < newLevel; i++) {
365
207
  update[i] = this._head;
366
208
  }
367
209
  this._level = newLevel;
368
210
  }
369
-
370
211
  for (let i = 0; i < newLevel; i++) {
371
212
  newNode.forward[i] = update[i].forward[i];
372
213
  update[i].forward[i] = newNode;
373
214
  }
374
-
375
215
  this._size++;
376
216
  return this;
377
217
  }
@@ -379,65 +219,26 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
379
219
  /**
380
220
  * Get the value for a key, or `undefined` if not found.
381
221
  * Overrides base O(n) with O(log n) skip-list search.
382
-
383
-
384
-
385
-
386
-
387
-
388
-
389
-
390
-
391
-
392
-
393
-
394
-
395
-
396
-
397
-
398
-
399
-
400
-
401
-
402
-
403
-
404
-
405
-
406
-
407
-
408
-
409
-
410
-
411
-
412
-
413
-
414
-
415
-
416
-
417
-
418
-
419
-
420
-
421
- * @example
422
- * // Building a sorted index
423
- * type Product = { id: number; name: string; price: number };
424
- * const products: Product[] = [
425
- * { id: 1, name: 'Widget', price: 25 },
426
- * { id: 2, name: 'Gadget', price: 50 },
427
- * { id: 3, name: 'Doohickey', price: 15 }
428
- * ];
429
- *
430
- * const index = new SkipList<number, Product, Product>(products, {
431
- * toEntryFn: (p: Product) => [p.price, p]
432
- * });
433
- *
434
- * // Iterate in sorted order by price
435
- * const names = [...index.values()].map(p => p!.name);
436
- * console.log(names); // ['Doohickey', 'Widget', 'Gadget'];
437
- *
438
- * // Range search: products between $20 and $60
439
- * const range = index.rangeSearch([20, 60]);
440
- * console.log(range.map(([, p]) => p!.name)); // ['Widget', 'Gadget'];
222
+ * @example
223
+ * // Building a sorted index
224
+ * type Product = { id: number; name: string; price: number };
225
+ * const products: Product[] = [
226
+ * { id: 1, name: 'Widget', price: 25 },
227
+ * { id: 2, name: 'Gadget', price: 50 },
228
+ * { id: 3, name: 'Doohickey', price: 15 }
229
+ * ];
230
+ *
231
+ * const index = new SkipList<number, Product, Product>(products, {
232
+ * toEntryFn: (p: Product) => [p.price, p]
233
+ * });
234
+ *
235
+ * // Iterate in sorted order by price
236
+ * const names = [...index.values()].map(p => p!.name);
237
+ * console.log(names); // ['Doohickey', 'Widget', 'Gadget'];
238
+ *
239
+ * // Range search: products between $20 and $60
240
+ * const range = index.rangeSearch([20, 60]);
241
+ * console.log(range.map(([, p]) => p!.name)); // ['Widget', 'Gadget'];
441
242
  */
442
243
  override get(key: K): V | undefined {
443
244
  const node = this._findNode(key);
@@ -447,50 +248,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
447
248
  /**
448
249
  * Check if a key exists.
449
250
  * Overrides base O(n) with O(log n) skip-list search.
450
-
451
-
452
-
453
-
454
-
455
-
456
-
457
-
458
-
459
-
460
-
461
-
462
-
463
-
464
-
465
-
466
-
467
-
468
-
469
-
470
-
471
-
472
-
473
-
474
-
475
-
476
-
477
-
478
-
479
-
480
-
481
-
482
-
483
-
484
-
485
-
486
-
487
-
488
-
489
- * @example
490
- * // Check key existence
491
- * const sl = new SkipList<number, string>([[1, 'a'], [3, 'c'], [5, 'e']]);
492
- * console.log(sl.has(3)); // true;
493
- * console.log(sl.has(4)); // false;
251
+ * @example
252
+ * // Check key existence
253
+ * const sl = new SkipList<number, string>([
254
+ * [1, 'a'],
255
+ * [3, 'c'],
256
+ * [5, 'e']
257
+ * ]);
258
+ * console.log(sl.has(3)); // true;
259
+ * console.log(sl.has(4)); // false;
494
260
  */
495
261
  override has(key: K): boolean {
496
262
  return this._findNode(key) !== undefined;
@@ -498,74 +264,31 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
498
264
 
499
265
  /**
500
266
  * Delete a key. Returns `true` if the key was found and removed.
501
-
502
-
503
-
504
-
505
-
506
-
507
-
508
-
509
-
510
-
511
-
512
-
513
-
514
-
515
-
516
-
517
-
518
-
519
-
520
-
521
-
522
-
523
-
524
-
525
-
526
-
527
-
528
-
529
-
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
- * @example
541
- * // Fast lookup with deletion
542
- * const cache = new SkipList<string, number>();
543
- *
544
- * cache.set('alpha', 1);
545
- * cache.set('beta', 2);
546
- * cache.set('gamma', 3);
547
- *
548
- * console.log(cache.has('beta')); // true;
549
- * cache.delete('beta');
550
- * console.log(cache.has('beta')); // false;
551
- * console.log(cache.size); // 2;
267
+ * @example
268
+ * // Fast lookup with deletion
269
+ * const cache = new SkipList<string, number>();
270
+ *
271
+ * cache.set('alpha', 1);
272
+ * cache.set('beta', 2);
273
+ * cache.set('gamma', 3);
274
+ *
275
+ * console.log(cache.has('beta')); // true;
276
+ * cache.delete('beta');
277
+ * console.log(cache.has('beta')); // false;
278
+ * console.log(cache.size); // 2;
552
279
  */
553
280
  delete(key: K): boolean {
554
281
  const cmp = this.#comparator;
555
282
  const update = this._findUpdate(key);
556
-
557
283
  const target = update[0].forward[0];
558
284
  if (!target || cmp(target.key, key) !== 0) return false;
559
-
560
285
  for (let i = 0; i < this._level; i++) {
561
286
  if (update[i].forward[i] !== target) break;
562
287
  update[i].forward[i] = target.forward[i];
563
288
  }
564
-
565
289
  while (this._level > 0 && !this._head.forward[this._level - 1]) {
566
290
  this._level--;
567
291
  }
568
-
569
292
  this._size--;
570
293
  return true;
571
294
  }
@@ -574,49 +297,14 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
574
297
 
575
298
  /**
576
299
  * Returns the first (smallest key) entry, or `undefined` if empty.
577
-
578
-
579
-
580
-
581
-
582
-
583
-
584
-
585
-
586
-
587
-
588
-
589
-
590
-
591
-
592
-
593
-
594
-
595
-
596
-
597
-
598
-
599
-
600
-
601
-
602
-
603
-
604
-
605
-
606
-
607
-
608
-
609
-
610
-
611
-
612
-
613
-
614
-
615
-
616
- * @example
617
- * // Access the minimum entry
618
- * const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
619
- * console.log(sl.first()); // [1, 'a'];
300
+ * @example
301
+ * // Access the minimum entry
302
+ * const sl = new SkipList<number, string>([
303
+ * [5, 'e'],
304
+ * [1, 'a'],
305
+ * [3, 'c']
306
+ * ]);
307
+ * console.log(sl.first()); // [1, 'a'];
620
308
  */
621
309
  first(): [K, V | undefined] | undefined {
622
310
  const node = this._head.forward[0];
@@ -625,49 +313,14 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
625
313
 
626
314
  /**
627
315
  * Returns the last (largest key) entry, or `undefined` if empty.
628
-
629
-
630
-
631
-
632
-
633
-
634
-
635
-
636
-
637
-
638
-
639
-
640
-
641
-
642
-
643
-
644
-
645
-
646
-
647
-
648
-
649
-
650
-
651
-
652
-
653
-
654
-
655
-
656
-
657
-
658
-
659
-
660
-
661
-
662
-
663
-
664
-
665
-
666
-
667
- * @example
668
- * // Access the maximum entry
669
- * const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
670
- * console.log(sl.last()); // [5, 'e'];
316
+ * @example
317
+ * // Access the maximum entry
318
+ * const sl = new SkipList<number, string>([
319
+ * [5, 'e'],
320
+ * [1, 'a'],
321
+ * [3, 'c']
322
+ * ]);
323
+ * console.log(sl.last()); // [5, 'e'];
671
324
  */
672
325
  last(): [K, V | undefined] | undefined {
673
326
  let current = this._head;
@@ -681,47 +334,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
681
334
 
682
335
  /**
683
336
  * Remove and return the first (smallest key) entry.
684
-
685
-
686
-
687
-
688
-
689
-
690
-
691
-
692
-
693
-
694
-
695
-
696
-
697
-
698
-
699
-
700
-
701
-
702
-
703
-
704
-
705
-
706
-
707
-
708
-
709
-
710
-
711
-
712
-
713
-
714
-
715
-
716
-
717
-
718
-
719
-
720
- * @example
721
- * // Remove and return smallest
722
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
723
- * console.log(sl.pollFirst()); // [1, 'a'];
724
- * console.log(sl.size); // 2;
337
+ * @example
338
+ * // Remove and return smallest
339
+ * const sl = new SkipList<number, string>([
340
+ * [1, 'a'],
341
+ * [2, 'b'],
342
+ * [3, 'c']
343
+ * ]);
344
+ * console.log(sl.pollFirst()); // [1, 'a'];
345
+ * console.log(sl.size); // 2;
725
346
  */
726
347
  pollFirst(): [K, V | undefined] | undefined {
727
348
  const entry = this.first();
@@ -732,47 +353,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
732
353
 
733
354
  /**
734
355
  * Remove and return the last (largest key) entry.
735
-
736
-
737
-
738
-
739
-
740
-
741
-
742
-
743
-
744
-
745
-
746
-
747
-
748
-
749
-
750
-
751
-
752
-
753
-
754
-
755
-
756
-
757
-
758
-
759
-
760
-
761
-
762
-
763
-
764
-
765
-
766
-
767
-
768
-
769
-
770
-
771
- * @example
772
- * // Remove and return largest
773
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
774
- * console.log(sl.pollLast()); // [3, 'c'];
775
- * console.log(sl.size); // 2;
356
+ * @example
357
+ * // Remove and return largest
358
+ * const sl = new SkipList<number, string>([
359
+ * [1, 'a'],
360
+ * [2, 'b'],
361
+ * [3, 'c']
362
+ * ]);
363
+ * console.log(sl.pollLast()); // [3, 'c'];
364
+ * console.log(sl.size); // 2;
776
365
  */
777
366
  pollLast(): [K, V | undefined] | undefined {
778
367
  const entry = this.last();
@@ -783,50 +372,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
783
372
 
784
373
  /**
785
374
  * Least entry ≥ key, or `undefined`.
786
-
787
-
788
-
789
-
790
-
791
-
792
-
793
-
794
-
795
-
796
-
797
-
798
-
799
-
800
-
801
-
802
-
803
-
804
-
805
-
806
-
807
-
808
-
809
-
810
-
811
-
812
-
813
-
814
-
815
-
816
-
817
-
818
-
819
-
820
-
821
-
822
-
823
-
824
-
825
- * @example
826
- * // Least entry ≥ key
827
- * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
828
- * console.log(sl.ceiling(15)); // [20, 'b'];
829
- * console.log(sl.ceiling(20)); // [20, 'b'];
375
+ * @example
376
+ * // Least entry ≥ key
377
+ * const sl = new SkipList<number, string>([
378
+ * [10, 'a'],
379
+ * [20, 'b'],
380
+ * [30, 'c']
381
+ * ]);
382
+ * console.log(sl.ceiling(15)); // [20, 'b'];
383
+ * console.log(sl.ceiling(20)); // [20, 'b'];
830
384
  */
831
385
  ceiling(key: K): [K, V | undefined] | undefined {
832
386
  const cmp = this.#comparator;
@@ -842,50 +396,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
842
396
 
843
397
  /**
844
398
  * Greatest entry ≤ key, or `undefined`.
845
-
846
-
847
-
848
-
849
-
850
-
851
-
852
-
853
-
854
-
855
-
856
-
857
-
858
-
859
-
860
-
861
-
862
-
863
-
864
-
865
-
866
-
867
-
868
-
869
-
870
-
871
-
872
-
873
-
874
-
875
-
876
-
877
-
878
-
879
-
880
-
881
-
882
-
883
-
884
- * @example
885
- * // Greatest entry ≤ key
886
- * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
887
- * console.log(sl.floor(25)); // [20, 'b'];
888
- * console.log(sl.floor(5)); // undefined;
399
+ * @example
400
+ * // Greatest entry ≤ key
401
+ * const sl = new SkipList<number, string>([
402
+ * [10, 'a'],
403
+ * [20, 'b'],
404
+ * [30, 'c']
405
+ * ]);
406
+ * console.log(sl.floor(25)); // [20, 'b'];
407
+ * console.log(sl.floor(5)); // undefined;
889
408
  */
890
409
  floor(key: K): [K, V | undefined] | undefined {
891
410
  const cmp = this.#comparator;
@@ -896,7 +415,6 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
896
415
  }
897
416
  }
898
417
  const result = current === this._head ? undefined : current;
899
-
900
418
  // Check if we're exactly at or before key
901
419
  if (result && cmp(result.key, key) <= 0) return [result.key, result.value];
902
420
  return undefined;
@@ -904,47 +422,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
904
422
 
905
423
  /**
906
424
  * Least entry strictly > key, or `undefined`.
907
-
908
-
909
-
910
-
911
-
912
-
913
-
914
-
915
-
916
-
917
-
918
-
919
-
920
-
921
-
922
-
923
-
924
-
925
-
926
-
927
-
928
-
929
-
930
-
931
-
932
-
933
-
934
-
935
-
936
-
937
-
938
-
939
-
940
-
941
-
942
-
943
- * @example
944
- * // Strictly greater entry
945
- * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
946
- * console.log(sl.higher(15)); // [20, 'b'];
947
- * console.log(sl.higher(30)); // undefined;
425
+ * @example
426
+ * // Strictly greater entry
427
+ * const sl = new SkipList<number, string>([
428
+ * [10, 'a'],
429
+ * [20, 'b'],
430
+ * [30, 'c']
431
+ * ]);
432
+ * console.log(sl.higher(15)); // [20, 'b'];
433
+ * console.log(sl.higher(30)); // undefined;
948
434
  */
949
435
  higher(key: K): [K, V | undefined] | undefined {
950
436
  const cmp = this.#comparator;
@@ -960,47 +446,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
960
446
 
961
447
  /**
962
448
  * Greatest entry strictly < key, or `undefined`.
963
-
964
-
965
-
966
-
967
-
968
-
969
-
970
-
971
-
972
-
973
-
974
-
975
-
976
-
977
-
978
-
979
-
980
-
981
-
982
-
983
-
984
-
985
-
986
-
987
-
988
-
989
-
990
-
991
-
992
-
993
-
994
-
995
-
996
-
997
-
998
-
999
- * @example
1000
- * // Strictly less entry
1001
- * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
1002
- * console.log(sl.lower(25)); // [20, 'b'];
1003
- * console.log(sl.lower(10)); // undefined;
449
+ * @example
450
+ * // Strictly less entry
451
+ * const sl = new SkipList<number, string>([
452
+ * [10, 'a'],
453
+ * [20, 'b'],
454
+ * [30, 'c']
455
+ * ]);
456
+ * console.log(sl.lower(25)); // [20, 'b'];
457
+ * console.log(sl.lower(10)); // undefined;
1004
458
  */
1005
459
  lower(key: K): [K, V | undefined] | undefined {
1006
460
  const cmp = this.#comparator;
@@ -1019,57 +473,27 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1019
473
 
1020
474
  /**
1021
475
  * Returns entries within the given key range.
1022
-
1023
-
1024
-
1025
-
1026
-
1027
-
1028
-
1029
-
1030
-
1031
-
1032
-
1033
-
1034
-
1035
-
1036
-
1037
-
1038
-
1039
-
1040
-
1041
-
1042
-
1043
-
1044
-
1045
-
1046
-
1047
-
1048
-
1049
-
1050
-
1051
-
1052
-
1053
-
1054
-
1055
-
1056
-
1057
-
1058
-
1059
-
1060
-
1061
- * @example
1062
- * // Find entries in a range
1063
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e']]);
1064
- * const result = sl.rangeSearch([2, 4]);
1065
- * console.log(result); // [[2, 'b'], [3, 'c'], [4, 'd']];
476
+ * @example
477
+ * // Find entries in a range
478
+ * const sl = new SkipList<number, string>([
479
+ * [1, 'a'],
480
+ * [2, 'b'],
481
+ * [3, 'c'],
482
+ * [4, 'd'],
483
+ * [5, 'e']
484
+ * ]);
485
+ * const result = sl.rangeSearch([2, 4]);
486
+ * console.log(result); // [
487
+ * // [2, 'b'],
488
+ * // [3, 'c'],
489
+ * // [4, 'd']
490
+ * // ];
1066
491
  */
1067
492
  rangeSearch(range: [K, K], options: SkipListRangeOptions = {}): Array<[K, V | undefined]> {
1068
493
  const { lowInclusive = true, highInclusive = true } = options;
1069
494
  const [low, high] = range;
1070
495
  const cmp = this.#comparator;
1071
496
  const out: Array<[K, V | undefined]> = [];
1072
-
1073
497
  // Start from the first node >= low
1074
498
  let current = this._head;
1075
499
  for (let i = this._level - 1; i >= 0; i--) {
@@ -1078,20 +502,16 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1078
502
  }
1079
503
  }
1080
504
  current = current.forward[0]!;
1081
-
1082
505
  while (current) {
1083
506
  const cmpHigh = cmp(current.key, high);
1084
507
  if (cmpHigh > 0) break;
1085
508
  if (cmpHigh === 0 && !highInclusive) break;
1086
-
1087
509
  const cmpLow = cmp(current.key, low);
1088
510
  if (cmpLow > 0 || (cmpLow === 0 && lowInclusive)) {
1089
511
  out.push([current.key, current.value]);
1090
512
  }
1091
-
1092
513
  current = current.forward[0]!;
1093
514
  }
1094
-
1095
515
  return out;
1096
516
  }
1097
517
 
@@ -1099,47 +519,14 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1099
519
 
1100
520
  /**
1101
521
  * Creates a new SkipList with entries transformed by callback.
1102
-
1103
-
1104
-
1105
-
1106
-
1107
-
1108
-
1109
-
1110
-
1111
-
1112
-
1113
-
1114
-
1115
-
1116
-
1117
-
1118
-
1119
-
1120
-
1121
-
1122
-
1123
-
1124
-
1125
-
1126
-
1127
-
1128
-
1129
-
1130
-
1131
-
1132
-
1133
-
1134
-
1135
-
1136
-
1137
-
1138
- * @example
1139
- * // Transform entries
1140
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
1141
- * const mapped = sl.map((v, k) => [k, v?.toUpperCase()] as [number, string]);
1142
- * console.log([...mapped.values()]); // ['A', 'B'];
522
+ * @example
523
+ * // Transform entries
524
+ * const sl = new SkipList<number, string>([
525
+ * [1, 'a'],
526
+ * [2, 'b']
527
+ * ]);
528
+ * const mapped = sl.map((v, k) => [k, v?.toUpperCase()] as [number, string]);
529
+ * console.log([...mapped.values()]); // ['A', 'B'];
1143
530
  */
1144
531
  map<MK, MV>(
1145
532
  callback: EntryCallback<K, V | undefined, [MK, MV]>,
@@ -1156,52 +543,17 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1156
543
 
1157
544
  /**
1158
545
  * Creates a new SkipList with entries that pass the predicate.
1159
-
1160
-
1161
-
1162
-
1163
-
1164
-
1165
-
1166
-
1167
-
1168
-
1169
-
1170
-
1171
-
1172
-
1173
-
1174
-
1175
-
1176
-
1177
-
1178
-
1179
-
1180
-
1181
-
1182
-
1183
-
1184
-
1185
-
1186
-
1187
-
1188
-
1189
-
1190
-
1191
-
1192
-
1193
-
1194
-
1195
- * @example
1196
- * // Filter entries
1197
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
1198
- * const result = sl.filter((v, k) => k > 1);
1199
- * console.log(result.size); // 2;
546
+ * @example
547
+ * // Filter entries
548
+ * const sl = new SkipList<number, string>([
549
+ * [1, 'a'],
550
+ * [2, 'b'],
551
+ * [3, 'c']
552
+ * ]);
553
+ * const result = sl.filter((v, k) => k > 1);
554
+ * console.log(result.size); // 2;
1200
555
  */
1201
- filter(
1202
- callbackfn: EntryCallback<K, V | undefined, boolean>,
1203
- thisArg?: unknown
1204
- ): this {
556
+ filter(callbackfn: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): this {
1205
557
  const out = new SkipList<K, V, R>([], {
1206
558
  comparator: this.#isDefaultComparator ? undefined : this.#comparator,
1207
559
  maxLevel: this._maxLevel,
@@ -1216,7 +568,6 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1216
568
  }
1217
569
 
1218
570
  // ─── Iterator (required by IterableEntryBase) ────────────────
1219
-
1220
571
  protected _getIterator(): IterableIterator<[K, V | undefined]> {
1221
572
  const head = this._head;
1222
573
  return (function* () {
@@ -1237,14 +588,12 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1237
588
  const cmp = this.#comparator;
1238
589
  const update: SkipListNode<K, V>[] = new Array(this._maxLevel).fill(this._head);
1239
590
  let current = this._head;
1240
-
1241
591
  for (let i = this._level - 1; i >= 0; i--) {
1242
592
  while (current.forward[i] && cmp(current.forward[i]!.key, key) < 0) {
1243
593
  current = current.forward[i]!;
1244
594
  }
1245
595
  update[i] = current;
1246
596
  }
1247
-
1248
597
  return update;
1249
598
  }
1250
599
 
@@ -1254,13 +603,11 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1254
603
  protected _findNode(key: K): SkipListNode<K, V> | undefined {
1255
604
  const cmp = this.#comparator;
1256
605
  let current = this._head;
1257
-
1258
606
  for (let i = this._level - 1; i >= 0; i--) {
1259
607
  while (current.forward[i] && cmp(current.forward[i]!.key, key) < 0) {
1260
608
  current = current.forward[i]!;
1261
609
  }
1262
610
  }
1263
-
1264
611
  const candidate = current.forward[0];
1265
612
  if (candidate && cmp(candidate.key, key) === 0) return candidate;
1266
613
  return undefined;