data-structure-typed 2.6.0 → 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 (80) hide show
  1. package/.github/workflows/ci.yml +7 -2
  2. package/.github/workflows/release-package.yml +9 -2
  3. package/docs-site-docusaurus/docs/api/classes/AVLTree.md +108 -108
  4. package/docs-site-docusaurus/docs/api/classes/BST.md +101 -101
  5. package/docs-site-docusaurus/docs/api/classes/BinaryIndexedTree.md +13 -13
  6. package/docs-site-docusaurus/docs/api/classes/BinaryTree.md +66 -66
  7. package/docs-site-docusaurus/docs/api/classes/Deque.md +235 -51
  8. package/docs-site-docusaurus/docs/api/classes/DirectedGraph.md +21 -21
  9. package/docs-site-docusaurus/docs/api/classes/DoublyLinkedList.md +231 -67
  10. package/docs-site-docusaurus/docs/api/classes/FibonacciHeap.md +9 -9
  11. package/docs-site-docusaurus/docs/api/classes/FibonacciHeapNode.md +1 -1
  12. package/docs-site-docusaurus/docs/api/classes/HashMap.md +14 -14
  13. package/docs-site-docusaurus/docs/api/classes/Heap.md +117 -34
  14. package/docs-site-docusaurus/docs/api/classes/IterableElementBase.md +83 -13
  15. package/docs-site-docusaurus/docs/api/classes/LinearBase.md +124 -20
  16. package/docs-site-docusaurus/docs/api/classes/LinearLinkedBase.md +140 -32
  17. package/docs-site-docusaurus/docs/api/classes/LinkedHashMap.md +23 -23
  18. package/docs-site-docusaurus/docs/api/classes/LinkedListQueue.md +159 -51
  19. package/docs-site-docusaurus/docs/api/classes/MapGraph.md +20 -20
  20. package/docs-site-docusaurus/docs/api/classes/Matrix.md +23 -23
  21. package/docs-site-docusaurus/docs/api/classes/MaxHeap.md +117 -34
  22. package/docs-site-docusaurus/docs/api/classes/MaxPriorityQueue.md +117 -34
  23. package/docs-site-docusaurus/docs/api/classes/MinHeap.md +117 -34
  24. package/docs-site-docusaurus/docs/api/classes/MinPriorityQueue.md +117 -34
  25. package/docs-site-docusaurus/docs/api/classes/PriorityQueue.md +117 -34
  26. package/docs-site-docusaurus/docs/api/classes/Queue.md +142 -34
  27. package/docs-site-docusaurus/docs/api/classes/RedBlackTree.md +117 -117
  28. package/docs-site-docusaurus/docs/api/classes/SegmentTree.md +8 -8
  29. package/docs-site-docusaurus/docs/api/classes/SinglyLinkedList.md +158 -50
  30. package/docs-site-docusaurus/docs/api/classes/SkipList.md +21 -21
  31. package/docs-site-docusaurus/docs/api/classes/Stack.md +108 -26
  32. package/docs-site-docusaurus/docs/api/classes/TreeMap.md +33 -33
  33. package/docs-site-docusaurus/docs/api/classes/TreeMultiMap.md +75 -39
  34. package/docs-site-docusaurus/docs/api/classes/TreeSet.md +301 -39
  35. package/docs-site-docusaurus/docs/api/classes/Trie.md +110 -28
  36. package/docs-site-docusaurus/docs/api/classes/UndirectedGraph.md +20 -20
  37. package/package.json +45 -46
  38. package/src/common/error.ts +15 -32
  39. package/src/common/index.ts +0 -3
  40. package/src/data-structures/base/iterable-element-base.ts +0 -3
  41. package/src/data-structures/base/linear-base.ts +2 -36
  42. package/src/data-structures/binary-tree/avl-tree.ts +31 -529
  43. package/src/data-structures/binary-tree/binary-indexed-tree.ts +47 -572
  44. package/src/data-structures/binary-tree/binary-tree.ts +326 -1311
  45. package/src/data-structures/binary-tree/bst.ts +158 -1082
  46. package/src/data-structures/binary-tree/red-black-tree.ts +451 -1290
  47. package/src/data-structures/binary-tree/segment-tree.ts +73 -351
  48. package/src/data-structures/binary-tree/tree-map.ts +462 -5124
  49. package/src/data-structures/binary-tree/tree-multi-map.ts +302 -4914
  50. package/src/data-structures/binary-tree/tree-multi-set.ts +284 -3972
  51. package/src/data-structures/binary-tree/tree-set.ts +338 -4836
  52. package/src/data-structures/graph/abstract-graph.ts +98 -167
  53. package/src/data-structures/graph/directed-graph.ts +137 -562
  54. package/src/data-structures/graph/map-graph.ts +0 -3
  55. package/src/data-structures/graph/undirected-graph.ts +132 -511
  56. package/src/data-structures/hash/hash-map.ts +154 -582
  57. package/src/data-structures/heap/heap.ts +200 -795
  58. package/src/data-structures/linked-list/doubly-linked-list.ts +121 -865
  59. package/src/data-structures/linked-list/singly-linked-list.ts +122 -794
  60. package/src/data-structures/linked-list/skip-linked-list.ts +211 -918
  61. package/src/data-structures/matrix/matrix.ts +179 -518
  62. package/src/data-structures/matrix/navigator.ts +0 -1
  63. package/src/data-structures/priority-queue/max-priority-queue.ts +1 -6
  64. package/src/data-structures/priority-queue/min-priority-queue.ts +6 -11
  65. package/src/data-structures/priority-queue/priority-queue.ts +1 -2
  66. package/src/data-structures/queue/deque.ts +214 -882
  67. package/src/data-structures/queue/queue.ts +102 -625
  68. package/src/data-structures/stack/stack.ts +76 -505
  69. package/src/data-structures/trie/trie.ts +98 -628
  70. package/src/types/common.ts +0 -10
  71. package/src/types/data-structures/binary-tree/bst.ts +0 -7
  72. package/src/types/data-structures/binary-tree/red-black-tree.ts +0 -1
  73. package/src/types/data-structures/graph/abstract-graph.ts +0 -2
  74. package/src/types/data-structures/hash/hash-map.ts +0 -3
  75. package/src/types/data-structures/hash/index.ts +0 -1
  76. package/src/types/data-structures/matrix/navigator.ts +0 -2
  77. package/src/types/utils/utils.ts +0 -7
  78. package/src/types/utils/validate-type.ts +0 -7
  79. package/src/utils/number.ts +0 -2
  80. 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,132 +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
-
177
-
178
-
179
- * @example
180
- * // Check if empty
181
- * const sl = new SkipList<number, string>();
182
- * console.log(sl.isEmpty()); // true;
126
+ * @example
127
+ * // Check if empty
128
+ * const sl = new SkipList<number, string>();
129
+ * console.log(sl.isEmpty()); // true;
183
130
  */
184
131
  isEmpty(): boolean {
185
132
  return this._size === 0;
186
133
  }
187
134
 
188
- /**
135
+ /**
189
136
  * Remove all entries
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
-
224
-
225
-
226
-
227
-
228
-
229
- * @example
230
- * // Remove all entries
231
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
232
- * sl.clear();
233
- * 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;
234
145
  */
235
146
  clear(): void {
236
147
  this._head = new SkipListNode<K, V>(undefined as K, undefined as V, this._maxLevel);
@@ -238,53 +149,17 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
238
149
  this._size = 0;
239
150
  }
240
151
 
241
- /**
152
+ /**
242
153
  * Create independent copy
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
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282
- * @example
283
- * // Create independent copy
284
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
285
- * const copy = sl.clone();
286
- * copy.delete(1);
287
- * 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;
288
163
  */
289
164
  clone(): this {
290
165
  return new SkipList<K, V, R>(this as Iterable<[K, V | undefined]>, {
@@ -299,91 +174,44 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
299
174
  /**
300
175
  * Insert or update a key-value pair. Returns `this` for chaining.
301
176
  * Unique keys only — if key exists, value is updated in place.
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
-
333
-
334
-
335
-
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
- * @example
345
- * // In-memory sorted key-value store
346
- * const store = new SkipList<number, string>();
347
- *
348
- * store.set(3, 'three');
349
- * store.set(1, 'one');
350
- * store.set(5, 'five');
351
- * store.set(2, 'two');
352
- *
353
- * console.log(store.get(3)); // 'three';
354
- * console.log(store.get(1)); // 'one';
355
- * console.log(store.get(5)); // 'five';
356
- *
357
- * // Update existing key
358
- * store.set(3, 'THREE');
359
- * 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';
360
193
  */
361
194
  set(key: K, value: V): this {
362
195
  const cmp = this.#comparator;
363
196
  const update = this._findUpdate(key);
364
-
365
197
  // If key already exists, update value in place
366
198
  const existing = update[0].forward[0];
367
199
  if (existing && cmp(existing.key, key) === 0) {
368
200
  existing.value = value;
369
201
  return this;
370
202
  }
371
-
372
203
  const newLevel = this._randomLevel();
373
204
  const newNode = new SkipListNode(key, value, newLevel);
374
-
375
205
  if (newLevel > this._level) {
376
206
  for (let i = this._level; i < newLevel; i++) {
377
207
  update[i] = this._head;
378
208
  }
379
209
  this._level = newLevel;
380
210
  }
381
-
382
211
  for (let i = 0; i < newLevel; i++) {
383
212
  newNode.forward[i] = update[i].forward[i];
384
213
  update[i].forward[i] = newNode;
385
214
  }
386
-
387
215
  this._size++;
388
216
  return this;
389
217
  }
@@ -391,68 +219,26 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
391
219
  /**
392
220
  * Get the value for a key, or `undefined` if not found.
393
221
  * Overrides base O(n) with O(log n) skip-list search.
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
-
422
-
423
-
424
-
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
-
435
-
436
- * @example
437
- * // Building a sorted index
438
- * type Product = { id: number; name: string; price: number };
439
- * const products: Product[] = [
440
- * { id: 1, name: 'Widget', price: 25 },
441
- * { id: 2, name: 'Gadget', price: 50 },
442
- * { id: 3, name: 'Doohickey', price: 15 }
443
- * ];
444
- *
445
- * const index = new SkipList<number, Product, Product>(products, {
446
- * toEntryFn: (p: Product) => [p.price, p]
447
- * });
448
- *
449
- * // Iterate in sorted order by price
450
- * const names = [...index.values()].map(p => p!.name);
451
- * console.log(names); // ['Doohickey', 'Widget', 'Gadget'];
452
- *
453
- * // Range search: products between $20 and $60
454
- * const range = index.rangeSearch([20, 60]);
455
- * 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'];
456
242
  */
457
243
  override get(key: K): V | undefined {
458
244
  const node = this._findNode(key);
@@ -462,53 +248,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
462
248
  /**
463
249
  * Check if a key exists.
464
250
  * Overrides base O(n) with O(log n) skip-list search.
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
-
490
-
491
-
492
-
493
-
494
-
495
-
496
-
497
-
498
-
499
-
500
-
501
-
502
-
503
-
504
-
505
-
506
-
507
- * @example
508
- * // Check key existence
509
- * const sl = new SkipList<number, string>([[1, 'a'], [3, 'c'], [5, 'e']]);
510
- * console.log(sl.has(3)); // true;
511
- * 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;
512
260
  */
513
261
  override has(key: K): boolean {
514
262
  return this._findNode(key) !== undefined;
@@ -516,77 +264,31 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
516
264
 
517
265
  /**
518
266
  * Delete a key. Returns `true` if the key was found and removed.
519
-
520
-
521
-
522
-
523
-
524
-
525
-
526
-
527
-
528
-
529
-
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
-
541
-
542
-
543
-
544
-
545
-
546
-
547
-
548
-
549
-
550
-
551
-
552
-
553
-
554
-
555
-
556
-
557
-
558
-
559
-
560
-
561
- * @example
562
- * // Fast lookup with deletion
563
- * const cache = new SkipList<string, number>();
564
- *
565
- * cache.set('alpha', 1);
566
- * cache.set('beta', 2);
567
- * cache.set('gamma', 3);
568
- *
569
- * console.log(cache.has('beta')); // true;
570
- * cache.delete('beta');
571
- * console.log(cache.has('beta')); // false;
572
- * 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;
573
279
  */
574
280
  delete(key: K): boolean {
575
281
  const cmp = this.#comparator;
576
282
  const update = this._findUpdate(key);
577
-
578
283
  const target = update[0].forward[0];
579
284
  if (!target || cmp(target.key, key) !== 0) return false;
580
-
581
285
  for (let i = 0; i < this._level; i++) {
582
286
  if (update[i].forward[i] !== target) break;
583
287
  update[i].forward[i] = target.forward[i];
584
288
  }
585
-
586
289
  while (this._level > 0 && !this._head.forward[this._level - 1]) {
587
290
  this._level--;
588
291
  }
589
-
590
292
  this._size--;
591
293
  return true;
592
294
  }
@@ -595,52 +297,14 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
595
297
 
596
298
  /**
597
299
  * Returns the first (smallest key) entry, or `undefined` if empty.
598
-
599
-
600
-
601
-
602
-
603
-
604
-
605
-
606
-
607
-
608
-
609
-
610
-
611
-
612
-
613
-
614
-
615
-
616
-
617
-
618
-
619
-
620
-
621
-
622
-
623
-
624
-
625
-
626
-
627
-
628
-
629
-
630
-
631
-
632
-
633
-
634
-
635
-
636
-
637
-
638
-
639
-
640
- * @example
641
- * // Access the minimum entry
642
- * const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
643
- * 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'];
644
308
  */
645
309
  first(): [K, V | undefined] | undefined {
646
310
  const node = this._head.forward[0];
@@ -649,52 +313,14 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
649
313
 
650
314
  /**
651
315
  * Returns the last (largest key) entry, or `undefined` if empty.
652
-
653
-
654
-
655
-
656
-
657
-
658
-
659
-
660
-
661
-
662
-
663
-
664
-
665
-
666
-
667
-
668
-
669
-
670
-
671
-
672
-
673
-
674
-
675
-
676
-
677
-
678
-
679
-
680
-
681
-
682
-
683
-
684
-
685
-
686
-
687
-
688
-
689
-
690
-
691
-
692
-
693
-
694
- * @example
695
- * // Access the maximum entry
696
- * const sl = new SkipList<number, string>([[5, 'e'], [1, 'a'], [3, 'c']]);
697
- * 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'];
698
324
  */
699
325
  last(): [K, V | undefined] | undefined {
700
326
  let current = this._head;
@@ -708,50 +334,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
708
334
 
709
335
  /**
710
336
  * Remove and return the first (smallest key) entry.
711
-
712
-
713
-
714
-
715
-
716
-
717
-
718
-
719
-
720
-
721
-
722
-
723
-
724
-
725
-
726
-
727
-
728
-
729
-
730
-
731
-
732
-
733
-
734
-
735
-
736
-
737
-
738
-
739
-
740
-
741
-
742
-
743
-
744
-
745
-
746
-
747
-
748
-
749
-
750
- * @example
751
- * // Remove and return smallest
752
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
753
- * console.log(sl.pollFirst()); // [1, 'a'];
754
- * 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;
755
346
  */
756
347
  pollFirst(): [K, V | undefined] | undefined {
757
348
  const entry = this.first();
@@ -762,50 +353,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
762
353
 
763
354
  /**
764
355
  * Remove and return the last (largest key) entry.
765
-
766
-
767
-
768
-
769
-
770
-
771
-
772
-
773
-
774
-
775
-
776
-
777
-
778
-
779
-
780
-
781
-
782
-
783
-
784
-
785
-
786
-
787
-
788
-
789
-
790
-
791
-
792
-
793
-
794
-
795
-
796
-
797
-
798
-
799
-
800
-
801
-
802
-
803
-
804
- * @example
805
- * // Remove and return largest
806
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
807
- * console.log(sl.pollLast()); // [3, 'c'];
808
- * 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;
809
365
  */
810
366
  pollLast(): [K, V | undefined] | undefined {
811
367
  const entry = this.last();
@@ -816,53 +372,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
816
372
 
817
373
  /**
818
374
  * Least entry ≥ key, or `undefined`.
819
-
820
-
821
-
822
-
823
-
824
-
825
-
826
-
827
-
828
-
829
-
830
-
831
-
832
-
833
-
834
-
835
-
836
-
837
-
838
-
839
-
840
-
841
-
842
-
843
-
844
-
845
-
846
-
847
-
848
-
849
-
850
-
851
-
852
-
853
-
854
-
855
-
856
-
857
-
858
-
859
-
860
-
861
- * @example
862
- * // Least entry ≥ key
863
- * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
864
- * console.log(sl.ceiling(15)); // [20, 'b'];
865
- * 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'];
866
384
  */
867
385
  ceiling(key: K): [K, V | undefined] | undefined {
868
386
  const cmp = this.#comparator;
@@ -878,53 +396,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
878
396
 
879
397
  /**
880
398
  * Greatest entry ≤ key, or `undefined`.
881
-
882
-
883
-
884
-
885
-
886
-
887
-
888
-
889
-
890
-
891
-
892
-
893
-
894
-
895
-
896
-
897
-
898
-
899
-
900
-
901
-
902
-
903
-
904
-
905
-
906
-
907
-
908
-
909
-
910
-
911
-
912
-
913
-
914
-
915
-
916
-
917
-
918
-
919
-
920
-
921
-
922
-
923
- * @example
924
- * // Greatest entry ≤ key
925
- * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
926
- * console.log(sl.floor(25)); // [20, 'b'];
927
- * 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;
928
408
  */
929
409
  floor(key: K): [K, V | undefined] | undefined {
930
410
  const cmp = this.#comparator;
@@ -935,7 +415,6 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
935
415
  }
936
416
  }
937
417
  const result = current === this._head ? undefined : current;
938
-
939
418
  // Check if we're exactly at or before key
940
419
  if (result && cmp(result.key, key) <= 0) return [result.key, result.value];
941
420
  return undefined;
@@ -943,50 +422,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
943
422
 
944
423
  /**
945
424
  * Least entry strictly > key, or `undefined`.
946
-
947
-
948
-
949
-
950
-
951
-
952
-
953
-
954
-
955
-
956
-
957
-
958
-
959
-
960
-
961
-
962
-
963
-
964
-
965
-
966
-
967
-
968
-
969
-
970
-
971
-
972
-
973
-
974
-
975
-
976
-
977
-
978
-
979
-
980
-
981
-
982
-
983
-
984
-
985
- * @example
986
- * // Strictly greater entry
987
- * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
988
- * console.log(sl.higher(15)); // [20, 'b'];
989
- * 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;
990
434
  */
991
435
  higher(key: K): [K, V | undefined] | undefined {
992
436
  const cmp = this.#comparator;
@@ -1002,50 +446,15 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1002
446
 
1003
447
  /**
1004
448
  * Greatest entry strictly < key, or `undefined`.
1005
-
1006
-
1007
-
1008
-
1009
-
1010
-
1011
-
1012
-
1013
-
1014
-
1015
-
1016
-
1017
-
1018
-
1019
-
1020
-
1021
-
1022
-
1023
-
1024
-
1025
-
1026
-
1027
-
1028
-
1029
-
1030
-
1031
-
1032
-
1033
-
1034
-
1035
-
1036
-
1037
-
1038
-
1039
-
1040
-
1041
-
1042
-
1043
-
1044
- * @example
1045
- * // Strictly less entry
1046
- * const sl = new SkipList<number, string>([[10, 'a'], [20, 'b'], [30, 'c']]);
1047
- * console.log(sl.lower(25)); // [20, 'b'];
1048
- * 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;
1049
458
  */
1050
459
  lower(key: K): [K, V | undefined] | undefined {
1051
460
  const cmp = this.#comparator;
@@ -1064,60 +473,27 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1064
473
 
1065
474
  /**
1066
475
  * Returns entries within the given key range.
1067
-
1068
-
1069
-
1070
-
1071
-
1072
-
1073
-
1074
-
1075
-
1076
-
1077
-
1078
-
1079
-
1080
-
1081
-
1082
-
1083
-
1084
-
1085
-
1086
-
1087
-
1088
-
1089
-
1090
-
1091
-
1092
-
1093
-
1094
-
1095
-
1096
-
1097
-
1098
-
1099
-
1100
-
1101
-
1102
-
1103
-
1104
-
1105
-
1106
-
1107
-
1108
-
1109
- * @example
1110
- * // Find entries in a range
1111
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e']]);
1112
- * const result = sl.rangeSearch([2, 4]);
1113
- * 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
+ * // ];
1114
491
  */
1115
492
  rangeSearch(range: [K, K], options: SkipListRangeOptions = {}): Array<[K, V | undefined]> {
1116
493
  const { lowInclusive = true, highInclusive = true } = options;
1117
494
  const [low, high] = range;
1118
495
  const cmp = this.#comparator;
1119
496
  const out: Array<[K, V | undefined]> = [];
1120
-
1121
497
  // Start from the first node >= low
1122
498
  let current = this._head;
1123
499
  for (let i = this._level - 1; i >= 0; i--) {
@@ -1126,20 +502,16 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1126
502
  }
1127
503
  }
1128
504
  current = current.forward[0]!;
1129
-
1130
505
  while (current) {
1131
506
  const cmpHigh = cmp(current.key, high);
1132
507
  if (cmpHigh > 0) break;
1133
508
  if (cmpHigh === 0 && !highInclusive) break;
1134
-
1135
509
  const cmpLow = cmp(current.key, low);
1136
510
  if (cmpLow > 0 || (cmpLow === 0 && lowInclusive)) {
1137
511
  out.push([current.key, current.value]);
1138
512
  }
1139
-
1140
513
  current = current.forward[0]!;
1141
514
  }
1142
-
1143
515
  return out;
1144
516
  }
1145
517
 
@@ -1147,50 +519,14 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1147
519
 
1148
520
  /**
1149
521
  * Creates a new SkipList with entries transformed by callback.
1150
-
1151
-
1152
-
1153
-
1154
-
1155
-
1156
-
1157
-
1158
-
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
- * @example
1190
- * // Transform entries
1191
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b']]);
1192
- * const mapped = sl.map((v, k) => [k, v?.toUpperCase()] as [number, string]);
1193
- * 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'];
1194
530
  */
1195
531
  map<MK, MV>(
1196
532
  callback: EntryCallback<K, V | undefined, [MK, MV]>,
@@ -1207,55 +543,17 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1207
543
 
1208
544
  /**
1209
545
  * Creates a new SkipList with entries that pass the predicate.
1210
-
1211
-
1212
-
1213
-
1214
-
1215
-
1216
-
1217
-
1218
-
1219
-
1220
-
1221
-
1222
-
1223
-
1224
-
1225
-
1226
-
1227
-
1228
-
1229
-
1230
-
1231
-
1232
-
1233
-
1234
-
1235
-
1236
-
1237
-
1238
-
1239
-
1240
-
1241
-
1242
-
1243
-
1244
-
1245
-
1246
-
1247
-
1248
-
1249
- * @example
1250
- * // Filter entries
1251
- * const sl = new SkipList<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
1252
- * const result = sl.filter((v, k) => k > 1);
1253
- * 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;
1254
555
  */
1255
- filter(
1256
- callbackfn: EntryCallback<K, V | undefined, boolean>,
1257
- thisArg?: unknown
1258
- ): this {
556
+ filter(callbackfn: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): this {
1259
557
  const out = new SkipList<K, V, R>([], {
1260
558
  comparator: this.#isDefaultComparator ? undefined : this.#comparator,
1261
559
  maxLevel: this._maxLevel,
@@ -1270,7 +568,6 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1270
568
  }
1271
569
 
1272
570
  // ─── Iterator (required by IterableEntryBase) ────────────────
1273
-
1274
571
  protected _getIterator(): IterableIterator<[K, V | undefined]> {
1275
572
  const head = this._head;
1276
573
  return (function* () {
@@ -1291,14 +588,12 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1291
588
  const cmp = this.#comparator;
1292
589
  const update: SkipListNode<K, V>[] = new Array(this._maxLevel).fill(this._head);
1293
590
  let current = this._head;
1294
-
1295
591
  for (let i = this._level - 1; i >= 0; i--) {
1296
592
  while (current.forward[i] && cmp(current.forward[i]!.key, key) < 0) {
1297
593
  current = current.forward[i]!;
1298
594
  }
1299
595
  update[i] = current;
1300
596
  }
1301
-
1302
597
  return update;
1303
598
  }
1304
599
 
@@ -1308,13 +603,11 @@ export class SkipList<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
1308
603
  protected _findNode(key: K): SkipListNode<K, V> | undefined {
1309
604
  const cmp = this.#comparator;
1310
605
  let current = this._head;
1311
-
1312
606
  for (let i = this._level - 1; i >= 0; i--) {
1313
607
  while (current.forward[i] && cmp(current.forward[i]!.key, key) < 0) {
1314
608
  current = current.forward[i]!;
1315
609
  }
1316
610
  }
1317
-
1318
611
  const candidate = current.forward[0];
1319
612
  if (candidate && cmp(candidate.key, key) === 0) return candidate;
1320
613
  return undefined;