binary-tree-typed 2.5.0 → 2.5.2

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 (90) hide show
  1. package/dist/cjs/index.cjs +771 -68
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs-legacy/index.cjs +771 -68
  4. package/dist/cjs-legacy/index.cjs.map +1 -1
  5. package/dist/esm/index.mjs +771 -69
  6. package/dist/esm/index.mjs.map +1 -1
  7. package/dist/esm-legacy/index.mjs +771 -69
  8. package/dist/esm-legacy/index.mjs.map +1 -1
  9. package/dist/types/common/error.d.ts +9 -0
  10. package/dist/types/common/index.d.ts +1 -1
  11. package/dist/types/data-structures/base/index.d.ts +1 -0
  12. package/dist/types/data-structures/base/iterable-entry-base.d.ts +8 -8
  13. package/dist/types/data-structures/base/linear-base.d.ts +3 -3
  14. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +288 -0
  15. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +336 -0
  16. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +618 -18
  17. package/dist/types/data-structures/binary-tree/bst.d.ts +676 -1
  18. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +456 -0
  19. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +144 -1
  20. package/dist/types/data-structures/binary-tree/tree-map.d.ts +3307 -399
  21. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +3285 -360
  22. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +2674 -325
  23. package/dist/types/data-structures/binary-tree/tree-set.d.ts +3072 -287
  24. package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -4
  25. package/dist/types/data-structures/graph/directed-graph.d.ts +240 -0
  26. package/dist/types/data-structures/graph/undirected-graph.d.ts +216 -0
  27. package/dist/types/data-structures/hash/hash-map.d.ts +274 -10
  28. package/dist/types/data-structures/heap/heap.d.ts +336 -0
  29. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +411 -3
  30. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +363 -3
  31. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +434 -2
  32. package/dist/types/data-structures/matrix/matrix.d.ts +192 -0
  33. package/dist/types/data-structures/queue/deque.d.ts +364 -4
  34. package/dist/types/data-structures/queue/queue.d.ts +288 -0
  35. package/dist/types/data-structures/stack/stack.d.ts +240 -0
  36. package/dist/types/data-structures/trie/trie.d.ts +292 -4
  37. package/dist/types/interfaces/graph.d.ts +1 -1
  38. package/dist/types/types/common.d.ts +2 -2
  39. package/dist/types/types/data-structures/binary-tree/bst.d.ts +1 -0
  40. package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +5 -0
  41. package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +4 -0
  42. package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +4 -0
  43. package/dist/types/types/data-structures/heap/heap.d.ts +1 -0
  44. package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +1 -0
  45. package/dist/types/types/utils/validate-type.d.ts +4 -4
  46. package/dist/umd/binary-tree-typed.js +773 -71
  47. package/dist/umd/binary-tree-typed.js.map +1 -1
  48. package/dist/umd/binary-tree-typed.min.js +5 -5
  49. package/dist/umd/binary-tree-typed.min.js.map +1 -1
  50. package/package.json +2 -2
  51. package/src/common/error.ts +19 -1
  52. package/src/common/index.ts +1 -1
  53. package/src/data-structures/base/index.ts +1 -0
  54. package/src/data-structures/base/iterable-element-base.ts +3 -2
  55. package/src/data-structures/base/iterable-entry-base.ts +8 -8
  56. package/src/data-structures/base/linear-base.ts +3 -3
  57. package/src/data-structures/binary-tree/avl-tree.ts +299 -0
  58. package/src/data-structures/binary-tree/binary-indexed-tree.ts +341 -5
  59. package/src/data-structures/binary-tree/binary-tree.ts +606 -6
  60. package/src/data-structures/binary-tree/bst.ts +946 -7
  61. package/src/data-structures/binary-tree/red-black-tree.ts +472 -0
  62. package/src/data-structures/binary-tree/segment-tree.ts +145 -2
  63. package/src/data-structures/binary-tree/tree-map.ts +3423 -499
  64. package/src/data-structures/binary-tree/tree-multi-map.ts +3537 -596
  65. package/src/data-structures/binary-tree/tree-multi-set.ts +2855 -495
  66. package/src/data-structures/binary-tree/tree-set.ts +3209 -413
  67. package/src/data-structures/graph/abstract-graph.ts +6 -6
  68. package/src/data-structures/graph/directed-graph.ts +240 -0
  69. package/src/data-structures/graph/undirected-graph.ts +216 -0
  70. package/src/data-structures/hash/hash-map.ts +281 -19
  71. package/src/data-structures/heap/heap.ts +340 -4
  72. package/src/data-structures/heap/max-heap.ts +2 -2
  73. package/src/data-structures/linked-list/doubly-linked-list.ts +411 -3
  74. package/src/data-structures/linked-list/singly-linked-list.ts +363 -3
  75. package/src/data-structures/linked-list/skip-linked-list.ts +439 -7
  76. package/src/data-structures/matrix/matrix.ts +202 -10
  77. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -2
  78. package/src/data-structures/queue/deque.ts +365 -5
  79. package/src/data-structures/queue/queue.ts +288 -0
  80. package/src/data-structures/stack/stack.ts +240 -0
  81. package/src/data-structures/trie/trie.ts +295 -7
  82. package/src/interfaces/graph.ts +1 -1
  83. package/src/types/common.ts +2 -2
  84. package/src/types/data-structures/binary-tree/bst.ts +1 -0
  85. package/src/types/data-structures/binary-tree/tree-map.ts +6 -0
  86. package/src/types/data-structures/binary-tree/tree-multi-set.ts +5 -0
  87. package/src/types/data-structures/binary-tree/tree-set.ts +5 -0
  88. package/src/types/data-structures/heap/heap.ts +1 -0
  89. package/src/types/data-structures/priority-queue/priority-queue.ts +1 -0
  90. package/src/types/utils/validate-type.ts +4 -4
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import type { Comparator, TreeMultiMapOptions } from '../../types';
10
- import { ERR, Range } from '../../common';
10
+ import { ERR, raise, Range } from '../../common';
11
11
  import { RedBlackTree, RedBlackTreeNode } from './red-black-tree';
12
12
  import { TreeSet } from './tree-set';
13
13
 
@@ -49,7 +49,7 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
49
49
  const comparator = options.comparator ?? TreeSet.createDefaultComparator<K>();
50
50
  this.#isDefaultComparator = options.comparator === undefined;
51
51
  const toEntryFn = options.toEntryFn;
52
- this.#core = new RedBlackTree<K, V[], R>([], { ...options, comparator, isMapMode: options.isMapMode });
52
+ this.#core = new RedBlackTree<K, V[], R>([], { ...options, comparator, isMapMode: options.isMapMode, enableOrderStatistic: options.enableOrderStatistic });
53
53
 
54
54
  for (const x of keysNodesEntriesOrRaws) {
55
55
  if (x === null || x === undefined) continue;
@@ -91,15 +91,15 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
91
91
  // reuse TreeSet strict validation (same policy)
92
92
  // NOTE: TreeSet._validateKey is private, so we replicate the checks.
93
93
  if (typeof key === 'number') {
94
- if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN('TreeMultiMap'));
94
+ if (Number.isNaN(key)) raise(TypeError, ERR.invalidNaN('TreeMultiMap'));
95
95
  return;
96
96
  }
97
97
  if (typeof key === 'string') return;
98
98
  if (key instanceof Date) {
99
- if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate('TreeMultiMap'));
99
+ if (Number.isNaN(key.getTime())) raise(TypeError, ERR.invalidDate('TreeMultiMap'));
100
100
  return;
101
101
  }
102
- throw new TypeError(ERR.comparatorRequired('TreeMultiMap'));
102
+ raise(TypeError, ERR.comparatorRequired('TreeMultiMap'));
103
103
  }
104
104
 
105
105
  /**
@@ -151,22 +151,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
151
151
 
152
152
 
153
153
 
154
- * @example
155
- * // Check if empty
156
- * console.log(new TreeMultiMap().isEmpty()); // true;
157
- */
158
- isEmpty(): boolean {
159
- return this.size === 0;
160
- }
161
-
162
- /**
163
- * Removes all entries from the map.
164
- * @remarks Time O(1), Space O(1)
165
-
166
-
167
-
168
-
169
-
170
154
 
171
155
 
172
156
 
@@ -199,57 +183,8 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
199
183
 
200
184
 
201
185
 
202
-
203
- * @example
204
- * // Remove all entries
205
- * const mm = new TreeMultiMap<number, string>();
206
- * mm.add(1, 'a');
207
- * mm.clear();
208
- * console.log(mm.isEmpty()); // true;
209
- */
210
- clear(): void {
211
- this.#core.clear();
212
- }
213
-
214
- /**
215
- * Bucket length for a key (missing => 0).
216
- * @remarks Time O(log n), Space O(1)
217
-
218
-
219
- * @example
220
- * // Count values for key
221
- * const mm = new TreeMultiMap<number, string>();
222
- * mm.add(1, 'a');
223
- * mm.add(1, 'b');
224
- * console.log(mm.count(1)); // 2;
225
- */
226
- count(key: K): number {
227
- const b = this.get(key);
228
- return Array.isArray(b) ? b.length : 0;
229
- }
230
-
231
- /**
232
- * Total number of values across all buckets (Σ bucket.length).
233
- * @remarks Time O(n), Space O(1)
234
186
 
235
187
 
236
- * @example
237
- * // Total number of values
238
- * const mm = new TreeMultiMap<number, string>();
239
- * mm.add(1, 'a');
240
- * mm.add(1, 'b');
241
- * mm.add(2, 'c');
242
- * console.log(mm.totalSize); // 3;
243
- */
244
- get totalSize(): number {
245
- let sum = 0;
246
- for (const [, bucket] of this) sum += bucket.length;
247
- return sum;
248
- }
249
-
250
- /**
251
- * Whether the map contains the given key.
252
- * @remarks Time O(log n), Space O(1)
253
188
 
254
189
 
255
190
 
@@ -302,21 +237,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
302
237
 
303
238
 
304
239
 
305
- * @example
306
- * // Check key existence
307
- * const mm = new TreeMultiMap<number, string>();
308
- * mm.add(1, 'a');
309
- * console.log(mm.has(1)); // true;
310
- * console.log(mm.has(2)); // false;
311
- */
312
- has(key: K): boolean {
313
- this._validateKey(key);
314
- return this.#core.has(key);
315
- }
316
-
317
- /**
318
- * Live bucket reference (do not auto-delete key if bucket becomes empty via mutation).
319
- * @remarks Time O(log n), Space O(1)
320
240
 
321
241
 
322
242
 
@@ -351,6 +271,17 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
351
271
 
352
272
 
353
273
 
274
+ * @example
275
+ * // Check if empty
276
+ * console.log(new TreeMultiMap().isEmpty()); // true;
277
+ */
278
+ isEmpty(): boolean {
279
+ return this.size === 0;
280
+ }
281
+
282
+ /**
283
+ * Removes all entries from the map.
284
+ * @remarks Time O(1), Space O(1)
354
285
 
355
286
 
356
287
 
@@ -369,21 +300,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
369
300
 
370
301
 
371
302
 
372
- * @example
373
- * // Get values for key
374
- * const mm = new TreeMultiMap<number, string>();
375
- * mm.add(1, 'a');
376
- * mm.add(1, 'b');
377
- * console.log(mm.get(1)); // ['a', 'b'];
378
- */
379
- get(key: K): V[] | undefined {
380
- this._validateKey(key);
381
- return this.#core.get(key);
382
- }
383
-
384
- /**
385
- * Append a single value.
386
- * @remarks Time O(log n), Space O(1)
387
303
 
388
304
 
389
305
 
@@ -416,27 +332,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
416
332
 
417
333
 
418
334
 
419
- * @example
420
- * // Add key-value pair
421
- * const mm = new TreeMultiMap<number, string>();
422
- * mm.add(1, 'a');
423
- * mm.add(1, 'b');
424
- * mm.add(2, 'c');
425
- * console.log(mm.get(1)); // ['a', 'b'];
426
- */
427
- add(key: K, value: V): boolean {
428
- this._validateKey(key);
429
- const bucket = this.#core.get(key);
430
- if (bucket) {
431
- bucket.push(value);
432
- return true;
433
- }
434
- return this.#core.set(key, [value]);
435
- }
436
-
437
- /**
438
- * Alias for compatibility with existing TreeMultiMap semantics.
439
- * @remarks Time O(log n), Space O(1) for single value; O(log n + m) for bucket append
440
335
 
441
336
 
442
337
 
@@ -487,41 +382,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
487
382
 
488
383
 
489
384
 
490
- * @example
491
- * // Set values for key
492
- * const mm = new TreeMultiMap<number, string>();
493
- * mm.set(1, 'a');
494
- * mm.set(1, 'b');
495
- * console.log(mm.get(1)); // ['a', 'b'];
496
- */
497
- set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean;
498
- set(key: K, value: V): boolean;
499
- set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean {
500
- if (entry === null || entry === undefined) return false;
501
- if (Array.isArray(entry)) {
502
- const [k, bucket] = entry;
503
- if (k === null || k === undefined) return false;
504
- if (value !== undefined) return this.add(k as K, value);
505
- if (bucket === undefined) {
506
- // ensure key exists
507
- return this.#core.set(k as K, [] as V[]);
508
- }
509
- // append bucket
510
- const existing = this.#core.get(k as K);
511
- if (existing) {
512
- existing.push(...bucket);
513
- return true;
514
- }
515
- return this.#core.set(k as K, [...bucket] as V[]);
516
- }
517
- // key-only or key+value
518
- if (value !== undefined) return this.add(entry as K, value);
519
- return this.#core.set(entry as K, [] as V[]);
520
- }
521
-
522
- /**
523
- * Deletes a key and its entire bucket.
524
- * @remarks Time O(log n), Space O(1)
525
385
 
526
386
 
527
387
 
@@ -574,106 +434,26 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
574
434
 
575
435
 
576
436
 
577
- * @example
578
- * // Remove key
579
- * const mm = new TreeMultiMap<number, string>();
580
- * mm.add(1, 'a');
581
- * mm.add(2, 'b');
582
- * mm.delete(1);
583
- * console.log(mm.has(1)); // false;
584
- */
585
- delete(key: K): boolean {
586
- this._validateKey(key);
587
- return this.#core.delete(key).length > 0;
588
- }
589
-
590
- /**
591
- * Check if a specific value exists in a key's bucket.
592
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
593
437
 
594
438
 
595
- * @example
596
- * // Check specific key-value
597
- * const mm = new TreeMultiMap<number, string>();
598
- * mm.add(1, 'a');
599
- * console.log(mm.hasEntry(1, 'a')); // true;
600
- * console.log(mm.hasEntry(1, 'z')); // false;
601
- */
602
- hasEntry(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
603
- const bucket = this.get(key);
604
- if (!Array.isArray(bucket)) return false;
605
- return bucket.some(v => eq(v, value));
606
- }
607
-
608
- /**
609
- * Delete a single occurrence of a value from a key's bucket.
610
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
611
439
 
612
440
 
613
- * @example
614
- * // Delete specific value
615
- * const mm = new TreeMultiMap<number, string>();
616
- * mm.add(1, 'a');
617
- * mm.add(1, 'b');
618
- * mm.deleteValue(1, 'a');
619
- * console.log(mm.get(1)); // ['b'];
620
- */
621
- deleteValue(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
622
- const bucket = this.get(key);
623
- if (!Array.isArray(bucket)) return false;
624
- const idx = bucket.findIndex(v => eq(v, value));
625
- if (idx === -1) return false;
626
- bucket.splice(idx, 1);
627
- if (bucket.length === 0) this.delete(key);
628
- return true;
629
- }
630
-
631
- /**
632
- * Delete all occurrences of a value from a key's bucket.
633
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
634
441
 
635
442
 
636
443
  * @example
637
- * // Delete all matching values
444
+ * // Remove all entries
638
445
  * const mm = new TreeMultiMap<number, string>();
639
446
  * mm.add(1, 'a');
640
- * mm.add(1, 'a');
641
- * mm.add(1, 'b');
642
- * const count = mm.deleteValues(1, 'a');
643
- * console.log(count); // 2;
644
- */
645
- deleteValues(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): number {
646
- const bucket = this.get(key);
647
- if (!Array.isArray(bucket) || bucket.length === 0) return 0;
648
- let removed = 0;
649
- for (let i = bucket.length - 1; i >= 0; i--) {
650
- if (eq(bucket[i] as V, value)) {
651
- bucket.splice(i, 1);
652
- removed++;
653
- }
654
- }
655
- if (bucket.length === 0 && removed > 0) this.delete(key);
656
- return removed;
657
- }
658
-
659
- // ---- iteration (bucket view) ----
660
-
661
- /**
662
- * Iterates over all entries as [key, bucket] pairs.
663
- * @remarks Time O(n), Space O(1)
447
+ * mm.clear();
448
+ * console.log(mm.isEmpty()); // true;
664
449
  */
665
- *[Symbol.iterator](): Iterator<[K, V[]]> {
666
- for (const [k, v] of this.#core) {
667
- // core always stores buckets, but guard anyway
668
- yield [k, v ?? /* istanbul ignore next */ ([] as V[])];
669
- }
450
+ clear(): void {
451
+ this.#core.clear();
670
452
  }
671
453
 
672
454
  /**
673
- * Iterates over all keys.
674
- * @remarks Time O(n), Space O(1)
675
-
676
-
455
+ * Bucket length for a key (missing => 0).
456
+ * @remarks Time O(log n), Space O(1)
677
457
 
678
458
 
679
459
 
@@ -694,6 +474,37 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
694
474
 
695
475
 
696
476
 
477
+
478
+
479
+
480
+
481
+
482
+
483
+ * @example
484
+ * // Count values for key
485
+ * const mm = new TreeMultiMap<number, string>();
486
+ * mm.add(1, 'a');
487
+ * mm.add(1, 'b');
488
+ * console.log(mm.count(1)); // 2;
489
+ */
490
+ count(key: K): number {
491
+ const b = this.get(key);
492
+ return Array.isArray(b) ? b.length : 0;
493
+ }
494
+
495
+ /**
496
+ * Total number of values across all buckets (Σ bucket.length).
497
+ * @remarks Time O(n), Space O(1)
498
+
499
+
500
+
501
+
502
+
503
+
504
+
505
+
506
+
507
+
697
508
 
698
509
 
699
510
 
@@ -711,19 +522,22 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
711
522
 
712
523
 
713
524
  * @example
714
- * // Iterate keys
525
+ * // Total number of values
715
526
  * const mm = new TreeMultiMap<number, string>();
716
- * mm.add(3, 'c');
717
527
  * mm.add(1, 'a');
718
- * console.log([...mm.keys()]); // [1, 3];
528
+ * mm.add(1, 'b');
529
+ * mm.add(2, 'c');
530
+ * console.log(mm.totalSize); // 3;
719
531
  */
720
- *keys(): IterableIterator<K> {
721
- yield* this.#core.keys();
532
+ get totalSize(): number {
533
+ let sum = 0;
534
+ for (const [, bucket] of this) sum += bucket.length;
535
+ return sum;
722
536
  }
723
537
 
724
538
  /**
725
- * Iterates over all buckets.
726
- * @remarks Time O(n), Space O(1)
539
+ * Whether the map contains the given key.
540
+ * @remarks Time O(log n), Space O(1)
727
541
 
728
542
 
729
543
 
@@ -762,80 +576,12 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
762
576
 
763
577
 
764
578
 
765
- * @example
766
- * // Iterate value arrays
767
- * const mm = new TreeMultiMap<number, string>();
768
- * mm.add(1, 'a');
769
- * mm.add(1, 'b');
770
- * console.log([...mm.values()]); // [['a', 'b']];
771
- */
772
- *values(): IterableIterator<V[]> {
773
- for (const [, bucket] of this) yield bucket;
774
- }
775
-
776
- // ---- entry-flat views ----
777
-
778
- /**
779
- * Iterates over all entries for a specific key.
780
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
781
579
 
782
580
 
783
- * @example
784
- * // Get entries for key
785
- * const mm = new TreeMultiMap<number, string>();
786
- * mm.add(1, 'a');
787
- * mm.add(1, 'b');
788
- * console.log([...mm.entriesOf(1)]); // [[1, 'a'], [1, 'b']];
789
- */
790
- *entriesOf(key: K): IterableIterator<[K, V]> {
791
- const bucket = this.get(key);
792
- if (!Array.isArray(bucket)) return;
793
- for (const v of bucket) yield [key, v];
794
- }
795
-
796
- /**
797
- * Iterates over all values for a specific key.
798
- * @remarks Time O(log n + m), Space O(1) where m is bucket size
799
581
 
800
582
 
801
- * @example
802
- * // Get flat values for key
803
- * const mm = new TreeMultiMap<number, string>();
804
- * mm.add(1, 'a');
805
- * mm.add(1, 'b');
806
- * console.log([...mm.valuesOf(1)]); // ['a', 'b'];
807
- */
808
- *valuesOf(key: K): IterableIterator<V> {
809
- const bucket = this.get(key);
810
- if (!Array.isArray(bucket)) return;
811
- yield* bucket;
812
- }
813
-
814
- /**
815
- * Iterates over all [key, value] pairs (flattened from buckets).
816
- * @remarks Time O(T), Space O(1) where T is totalSize
817
583
 
818
584
 
819
- * @example
820
- * // All key-value pairs flattened
821
- * const mm = new TreeMultiMap<number, string>();
822
- * mm.add(1, 'a');
823
- * mm.add(1, 'b');
824
- * mm.add(2, 'c');
825
- * console.log([...mm.flatEntries()]); // [[1, 'a'], [1, 'b'], [2, 'c']];
826
- */
827
- *flatEntries(): IterableIterator<[K, V]> {
828
- for (const [k, bucket] of this) {
829
- for (const v of bucket) yield [k, v];
830
- }
831
- }
832
-
833
- // ━━━ Navigable methods (return [K, V[]] | undefined) ━━━
834
-
835
- /**
836
- * Returns the entry with the smallest key.
837
- * @remarks Time O(log n), Space O(1)
838
-
839
585
 
840
586
 
841
587
 
@@ -849,24 +595,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
849
595
 
850
596
 
851
597
 
852
- * @example
853
- * // First entry
854
- * const mm = new TreeMultiMap<number, string>();
855
- * mm.add(3, 'c');
856
- * mm.add(1, 'a');
857
- * console.log(mm.first()?.[0]); // 1;
858
- */
859
- first(): [K, V[]] | undefined {
860
- const k = this.#core.getLeftMost();
861
- if (k === undefined) return undefined;
862
- const b = this.get(k);
863
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
864
- }
865
-
866
- /**
867
- * Returns the entry with the largest key.
868
- * @remarks Time O(log n), Space O(1)
869
-
870
598
 
871
599
 
872
600
 
@@ -880,67 +608,10 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
880
608
 
881
609
 
882
610
 
883
- * @example
884
- * // Last entry
885
- * const mm = new TreeMultiMap<number, string>();
886
- * mm.add(1, 'a');
887
- * mm.add(3, 'c');
888
- * console.log(mm.last()?.[0]); // 3;
889
- */
890
- last(): [K, V[]] | undefined {
891
- const k = this.#core.getRightMost();
892
- if (k === undefined) return undefined;
893
- const b = this.get(k);
894
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
895
- }
896
-
897
- /**
898
- * Removes and returns the entry with the smallest key.
899
- * @remarks Time O(log n), Space O(1)
900
-
901
611
 
902
612
 
903
- * @example
904
- * // Remove and return first
905
- * const mm = new TreeMultiMap<number, string>();
906
- * mm.add(2, 'b');
907
- * mm.add(1, 'a');
908
- * const first = mm.pollFirst();
909
- * console.log(first?.[0]); // 1;
910
- * console.log(mm.has(1)); // false;
911
- */
912
- pollFirst(): [K, V[]] | undefined {
913
- const e = this.first();
914
- if (!e) return undefined;
915
- this.delete(e[0]);
916
- return e;
917
- }
918
-
919
- /**
920
- * Removes and returns the entry with the largest key.
921
- * @remarks Time O(log n), Space O(1)
922
-
923
613
 
924
614
 
925
- * @example
926
- * // Remove and return last
927
- * const mm = new TreeMultiMap<number, string>();
928
- * mm.add(1, 'a');
929
- * mm.add(3, 'c');
930
- * const last = mm.pollLast();
931
- * console.log(last?.[0]); // 3;
932
- */
933
- pollLast(): [K, V[]] | undefined {
934
- const e = this.last();
935
- if (!e) return undefined;
936
- this.delete(e[0]);
937
- return e;
938
- }
939
-
940
- /**
941
- * Returns the entry with the smallest key >= given key.
942
- * @remarks Time O(log n), Space O(1)
943
-
944
615
 
945
616
 
946
617
 
@@ -981,26 +652,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
981
652
 
982
653
 
983
654
 
984
- * @example
985
- * // Least key ≥ target
986
- * const mm = new TreeMultiMap<number, string>();
987
- * mm.add(10, 'a');
988
- * mm.add(20, 'b');
989
- * mm.add(30, 'c');
990
- * console.log(mm.ceiling(15)?.[0]); // 20;
991
- */
992
- ceiling(key: K): [K, V[]] | undefined {
993
- this._validateKey(key);
994
- const k = this.#core.ceiling(key);
995
- if (k === undefined) return undefined;
996
- const b = this.get(k);
997
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
998
- }
999
-
1000
- /**
1001
- * Returns the entry with the largest key <= given key.
1002
- * @remarks Time O(log n), Space O(1)
1003
-
1004
655
 
1005
656
 
1006
657
 
@@ -1041,26 +692,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1041
692
 
1042
693
 
1043
694
 
1044
- * @example
1045
- * // Greatest key ≤ target
1046
- * const mm = new TreeMultiMap<number, string>();
1047
- * mm.add(10, 'a');
1048
- * mm.add(20, 'b');
1049
- * mm.add(30, 'c');
1050
- * console.log(mm.floor(25)?.[0]); // 20;
1051
- */
1052
- floor(key: K): [K, V[]] | undefined {
1053
- this._validateKey(key);
1054
- const k = this.#core.floor(key);
1055
- if (k === undefined) return undefined;
1056
- const b = this.get(k);
1057
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
1058
- }
1059
-
1060
- /**
1061
- * Returns the entry with the smallest key > given key.
1062
- * @remarks Time O(log n), Space O(1)
1063
-
1064
695
 
1065
696
 
1066
697
 
@@ -1090,25 +721,3388 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1090
721
 
1091
722
 
1092
723
 
1093
- * @example
1094
- * // Least key > target
1095
- * const mm = new TreeMultiMap<number, string>();
1096
- * mm.add(10, 'a');
1097
- * mm.add(20, 'b');
1098
- * console.log(mm.higher(10)?.[0]); // 20;
1099
- */
1100
- higher(key: K): [K, V[]] | undefined {
1101
- this._validateKey(key);
1102
- const k = this.#core.higher(key);
1103
- if (k === undefined) return undefined;
1104
- const b = this.get(k);
1105
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
1106
- }
1107
-
1108
- /**
1109
- * Returns the entry with the largest key < given key.
1110
- * @remarks Time O(log n), Space O(1)
1111
-
724
+
725
+
726
+
727
+
728
+
729
+
730
+
731
+
732
+
733
+
734
+
735
+
736
+
737
+ * @example
738
+ * // Check key existence
739
+ * const mm = new TreeMultiMap<number, string>();
740
+ * mm.add(1, 'a');
741
+ * console.log(mm.has(1)); // true;
742
+ * console.log(mm.has(2)); // false;
743
+ */
744
+ has(key: K): boolean {
745
+ this._validateKey(key);
746
+ return this.#core.has(key);
747
+ }
748
+
749
+ /**
750
+ * Live bucket reference (do not auto-delete key if bucket becomes empty via mutation).
751
+ * @remarks Time O(log n), Space O(1)
752
+
753
+
754
+
755
+
756
+
757
+
758
+
759
+
760
+
761
+
762
+
763
+
764
+
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
+
805
+
806
+
807
+
808
+
809
+
810
+
811
+
812
+
813
+
814
+
815
+
816
+
817
+
818
+
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
+
862
+
863
+
864
+
865
+
866
+
867
+
868
+
869
+
870
+
871
+
872
+
873
+
874
+
875
+
876
+
877
+
878
+
879
+
880
+
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
+
924
+
925
+
926
+
927
+
928
+
929
+
930
+
931
+
932
+
933
+
934
+
935
+
936
+
937
+
938
+
939
+
940
+
941
+
942
+
943
+
944
+
945
+
946
+
947
+
948
+ * @example
949
+ * // Get values for key
950
+ * const mm = new TreeMultiMap<number, string>();
951
+ * mm.add(1, 'a');
952
+ * mm.add(1, 'b');
953
+ * console.log(mm.get(1)); // ['a', 'b'];
954
+ */
955
+ get(key: K): V[] | undefined {
956
+ this._validateKey(key);
957
+ return this.#core.get(key);
958
+ }
959
+
960
+ /**
961
+ * Append a single value.
962
+ * @remarks Time O(log n), Space O(1)
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
+
1000
+
1001
+
1002
+
1003
+
1004
+
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
+
1045
+
1046
+
1047
+
1048
+
1049
+
1050
+
1051
+
1052
+
1053
+
1054
+
1055
+
1056
+
1057
+
1058
+
1059
+
1060
+
1061
+
1062
+
1063
+
1064
+
1065
+
1066
+
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
+
1110
+
1111
+
1112
+
1113
+
1114
+
1115
+ * @example
1116
+ * // Add key-value pair
1117
+ * const mm = new TreeMultiMap<number, string>();
1118
+ * mm.add(1, 'a');
1119
+ * mm.add(1, 'b');
1120
+ * mm.add(2, 'c');
1121
+ * console.log(mm.get(1)); // ['a', 'b'];
1122
+ */
1123
+ add(key: K, value: V): boolean {
1124
+ this._validateKey(key);
1125
+ const bucket = this.#core.get(key);
1126
+ if (bucket) {
1127
+ bucket.push(value);
1128
+ return true;
1129
+ }
1130
+ return this.#core.set(key, [value]);
1131
+ }
1132
+
1133
+ /**
1134
+ * Alias for compatibility with existing TreeMultiMap semantics.
1135
+ * @remarks Time O(log n), Space O(1) for single value; O(log n + m) for bucket append
1136
+
1137
+
1138
+
1139
+
1140
+
1141
+
1142
+
1143
+
1144
+
1145
+
1146
+
1147
+
1148
+
1149
+
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
+
1190
+
1191
+
1192
+
1193
+
1194
+
1195
+
1196
+
1197
+
1198
+
1199
+
1200
+
1201
+
1202
+
1203
+
1204
+
1205
+
1206
+
1207
+
1208
+
1209
+
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
+
1250
+
1251
+
1252
+
1253
+
1254
+
1255
+
1256
+
1257
+
1258
+
1259
+
1260
+
1261
+
1262
+
1263
+
1264
+
1265
+
1266
+
1267
+
1268
+
1269
+
1270
+
1271
+
1272
+
1273
+
1274
+
1275
+
1276
+
1277
+
1278
+
1279
+
1280
+
1281
+
1282
+
1283
+
1284
+
1285
+
1286
+
1287
+
1288
+
1289
+
1290
+
1291
+
1292
+
1293
+
1294
+
1295
+
1296
+
1297
+
1298
+
1299
+
1300
+
1301
+
1302
+
1303
+
1304
+
1305
+
1306
+
1307
+
1308
+
1309
+
1310
+
1311
+
1312
+
1313
+
1314
+
1315
+
1316
+
1317
+
1318
+
1319
+
1320
+
1321
+
1322
+
1323
+
1324
+
1325
+
1326
+
1327
+
1328
+
1329
+
1330
+ * @example
1331
+ * // Set values for key
1332
+ * const mm = new TreeMultiMap<number, string>();
1333
+ * mm.set(1, 'a');
1334
+ * mm.set(1, 'b');
1335
+ * console.log(mm.get(1)); // ['a', 'b'];
1336
+ */
1337
+ set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean;
1338
+ set(key: K, value: V): boolean;
1339
+ set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean {
1340
+ if (entry === null || entry === undefined) return false;
1341
+ if (Array.isArray(entry)) {
1342
+ const [k, bucket] = entry;
1343
+ if (k === null || k === undefined) return false;
1344
+ if (value !== undefined) return this.add(k as K, value);
1345
+ if (bucket === undefined) {
1346
+ // ensure key exists
1347
+ return this.#core.set(k as K, [] as V[]);
1348
+ }
1349
+ // append bucket
1350
+ const existing = this.#core.get(k as K);
1351
+ if (existing) {
1352
+ existing.push(...bucket);
1353
+ return true;
1354
+ }
1355
+ return this.#core.set(k as K, [...bucket] as V[]);
1356
+ }
1357
+ // key-only or key+value
1358
+ if (value !== undefined) return this.add(entry as K, value);
1359
+ return this.#core.set(entry as K, [] as V[]);
1360
+ }
1361
+
1362
+ /**
1363
+ * Deletes a key and its entire bucket.
1364
+ * @remarks Time O(log n), Space O(1)
1365
+
1366
+
1367
+
1368
+
1369
+
1370
+
1371
+
1372
+
1373
+
1374
+
1375
+
1376
+
1377
+
1378
+
1379
+
1380
+
1381
+
1382
+
1383
+
1384
+
1385
+
1386
+
1387
+
1388
+
1389
+
1390
+
1391
+
1392
+
1393
+
1394
+
1395
+
1396
+
1397
+
1398
+
1399
+
1400
+
1401
+
1402
+
1403
+
1404
+
1405
+
1406
+
1407
+
1408
+
1409
+
1410
+
1411
+
1412
+
1413
+
1414
+
1415
+
1416
+
1417
+
1418
+
1419
+
1420
+
1421
+
1422
+
1423
+
1424
+
1425
+
1426
+
1427
+
1428
+
1429
+
1430
+
1431
+
1432
+
1433
+
1434
+
1435
+
1436
+
1437
+
1438
+
1439
+
1440
+
1441
+
1442
+
1443
+
1444
+
1445
+
1446
+
1447
+
1448
+
1449
+
1450
+
1451
+
1452
+
1453
+
1454
+
1455
+
1456
+
1457
+
1458
+
1459
+
1460
+
1461
+
1462
+
1463
+
1464
+
1465
+
1466
+
1467
+
1468
+
1469
+
1470
+
1471
+
1472
+
1473
+
1474
+
1475
+
1476
+
1477
+
1478
+
1479
+
1480
+
1481
+
1482
+
1483
+
1484
+
1485
+
1486
+
1487
+
1488
+
1489
+
1490
+
1491
+
1492
+
1493
+
1494
+
1495
+
1496
+
1497
+
1498
+
1499
+
1500
+
1501
+
1502
+
1503
+
1504
+
1505
+
1506
+
1507
+
1508
+
1509
+
1510
+
1511
+
1512
+
1513
+
1514
+
1515
+
1516
+
1517
+
1518
+
1519
+
1520
+
1521
+
1522
+
1523
+
1524
+
1525
+
1526
+
1527
+
1528
+
1529
+
1530
+
1531
+
1532
+
1533
+
1534
+
1535
+
1536
+
1537
+
1538
+
1539
+
1540
+
1541
+
1542
+
1543
+
1544
+
1545
+
1546
+
1547
+
1548
+
1549
+
1550
+
1551
+
1552
+
1553
+
1554
+
1555
+
1556
+
1557
+
1558
+
1559
+
1560
+
1561
+ * @example
1562
+ * // Remove key
1563
+ * const mm = new TreeMultiMap<number, string>();
1564
+ * mm.add(1, 'a');
1565
+ * mm.add(2, 'b');
1566
+ * mm.delete(1);
1567
+ * console.log(mm.has(1)); // false;
1568
+ */
1569
+ delete(key: K): boolean {
1570
+ this._validateKey(key);
1571
+ return this.#core.delete(key).length > 0;
1572
+ }
1573
+
1574
+ /**
1575
+ * Check if a specific value exists in a key's bucket.
1576
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1577
+
1578
+
1579
+
1580
+
1581
+
1582
+
1583
+
1584
+
1585
+
1586
+
1587
+
1588
+
1589
+
1590
+
1591
+
1592
+
1593
+
1594
+
1595
+
1596
+
1597
+
1598
+
1599
+
1600
+
1601
+
1602
+
1603
+ * @example
1604
+ * // Check specific key-value
1605
+ * const mm = new TreeMultiMap<number, string>();
1606
+ * mm.add(1, 'a');
1607
+ * console.log(mm.hasEntry(1, 'a')); // true;
1608
+ * console.log(mm.hasEntry(1, 'z')); // false;
1609
+ */
1610
+ hasEntry(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
1611
+ const bucket = this.get(key);
1612
+ if (!Array.isArray(bucket)) return false;
1613
+ return bucket.some(v => eq(v, value));
1614
+ }
1615
+
1616
+ /**
1617
+ * Delete a single occurrence of a value from a key's bucket.
1618
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1619
+
1620
+
1621
+
1622
+
1623
+
1624
+
1625
+
1626
+
1627
+
1628
+
1629
+
1630
+
1631
+
1632
+
1633
+
1634
+
1635
+
1636
+
1637
+
1638
+
1639
+
1640
+
1641
+
1642
+
1643
+
1644
+
1645
+ * @example
1646
+ * // Delete specific value
1647
+ * const mm = new TreeMultiMap<number, string>();
1648
+ * mm.add(1, 'a');
1649
+ * mm.add(1, 'b');
1650
+ * mm.deleteValue(1, 'a');
1651
+ * console.log(mm.get(1)); // ['b'];
1652
+ */
1653
+ deleteValue(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
1654
+ const bucket = this.get(key);
1655
+ if (!Array.isArray(bucket)) return false;
1656
+ const idx = bucket.findIndex(v => eq(v, value));
1657
+ if (idx === -1) return false;
1658
+ bucket.splice(idx, 1);
1659
+ if (bucket.length === 0) this.delete(key);
1660
+ return true;
1661
+ }
1662
+
1663
+ /**
1664
+ * Delete all occurrences of a value from a key's bucket.
1665
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1666
+
1667
+
1668
+
1669
+
1670
+
1671
+
1672
+
1673
+
1674
+
1675
+
1676
+
1677
+
1678
+
1679
+
1680
+
1681
+
1682
+
1683
+
1684
+
1685
+
1686
+
1687
+
1688
+
1689
+
1690
+
1691
+
1692
+ * @example
1693
+ * // Delete all matching values
1694
+ * const mm = new TreeMultiMap<number, string>();
1695
+ * mm.add(1, 'a');
1696
+ * mm.add(1, 'a');
1697
+ * mm.add(1, 'b');
1698
+ * const count = mm.deleteValues(1, 'a');
1699
+ * console.log(count); // 2;
1700
+ */
1701
+ deleteValues(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): number {
1702
+ const bucket = this.get(key);
1703
+ if (!Array.isArray(bucket) || bucket.length === 0) return 0;
1704
+ let removed = 0;
1705
+ for (let i = bucket.length - 1; i >= 0; i--) {
1706
+ if (eq(bucket[i] as V, value)) {
1707
+ bucket.splice(i, 1);
1708
+ removed++;
1709
+ }
1710
+ }
1711
+ if (bucket.length === 0 && removed > 0) this.delete(key);
1712
+ return removed;
1713
+ }
1714
+
1715
+ // ---- iteration (bucket view) ----
1716
+
1717
+ /**
1718
+ * Iterates over all entries as [key, bucket] pairs.
1719
+ * @remarks Time O(n), Space O(1)
1720
+ */
1721
+ *[Symbol.iterator](): Iterator<[K, V[]]> {
1722
+ for (const [k, v] of this.#core) {
1723
+ // core always stores buckets, but guard anyway
1724
+ yield [k, v ?? /* istanbul ignore next */ ([] as V[])];
1725
+ }
1726
+ }
1727
+
1728
+ /**
1729
+ * Iterates over all keys.
1730
+ * @remarks Time O(n), Space O(1)
1731
+
1732
+
1733
+
1734
+
1735
+
1736
+
1737
+
1738
+
1739
+
1740
+
1741
+
1742
+
1743
+
1744
+
1745
+
1746
+
1747
+
1748
+
1749
+
1750
+
1751
+
1752
+
1753
+
1754
+
1755
+
1756
+
1757
+
1758
+
1759
+
1760
+
1761
+
1762
+
1763
+
1764
+
1765
+
1766
+
1767
+
1768
+
1769
+
1770
+
1771
+
1772
+
1773
+
1774
+
1775
+
1776
+
1777
+
1778
+
1779
+
1780
+
1781
+
1782
+
1783
+
1784
+
1785
+
1786
+
1787
+
1788
+
1789
+
1790
+
1791
+
1792
+
1793
+
1794
+
1795
+
1796
+
1797
+
1798
+
1799
+
1800
+
1801
+
1802
+
1803
+
1804
+
1805
+
1806
+
1807
+
1808
+
1809
+
1810
+
1811
+
1812
+
1813
+
1814
+
1815
+
1816
+
1817
+
1818
+
1819
+
1820
+
1821
+
1822
+
1823
+
1824
+
1825
+
1826
+
1827
+
1828
+
1829
+
1830
+
1831
+
1832
+
1833
+
1834
+
1835
+
1836
+
1837
+
1838
+
1839
+
1840
+
1841
+
1842
+
1843
+
1844
+
1845
+
1846
+
1847
+
1848
+
1849
+
1850
+
1851
+
1852
+
1853
+
1854
+
1855
+
1856
+
1857
+
1858
+
1859
+
1860
+
1861
+
1862
+
1863
+
1864
+
1865
+
1866
+
1867
+
1868
+
1869
+
1870
+
1871
+
1872
+
1873
+
1874
+
1875
+
1876
+
1877
+
1878
+
1879
+
1880
+
1881
+
1882
+
1883
+
1884
+
1885
+
1886
+
1887
+
1888
+
1889
+ * @example
1890
+ * // Iterate keys
1891
+ * const mm = new TreeMultiMap<number, string>();
1892
+ * mm.add(3, 'c');
1893
+ * mm.add(1, 'a');
1894
+ * console.log([...mm.keys()]); // [1, 3];
1895
+ */
1896
+ *keys(): IterableIterator<K> {
1897
+ yield* this.#core.keys();
1898
+ }
1899
+
1900
+ /**
1901
+ * Iterates over all buckets.
1902
+ * @remarks Time O(n), Space O(1)
1903
+
1904
+
1905
+
1906
+
1907
+
1908
+
1909
+
1910
+
1911
+
1912
+
1913
+
1914
+
1915
+
1916
+
1917
+
1918
+
1919
+
1920
+
1921
+
1922
+
1923
+
1924
+
1925
+
1926
+
1927
+
1928
+
1929
+
1930
+
1931
+
1932
+
1933
+
1934
+
1935
+
1936
+
1937
+
1938
+
1939
+
1940
+
1941
+
1942
+
1943
+
1944
+
1945
+
1946
+
1947
+
1948
+
1949
+
1950
+
1951
+
1952
+
1953
+
1954
+
1955
+
1956
+
1957
+
1958
+
1959
+
1960
+
1961
+
1962
+
1963
+
1964
+
1965
+
1966
+
1967
+
1968
+
1969
+
1970
+
1971
+
1972
+
1973
+
1974
+
1975
+
1976
+
1977
+
1978
+
1979
+
1980
+
1981
+
1982
+
1983
+
1984
+
1985
+
1986
+
1987
+
1988
+
1989
+
1990
+
1991
+
1992
+
1993
+
1994
+
1995
+
1996
+
1997
+
1998
+
1999
+
2000
+
2001
+
2002
+
2003
+
2004
+
2005
+
2006
+
2007
+
2008
+
2009
+
2010
+
2011
+
2012
+
2013
+
2014
+
2015
+
2016
+
2017
+
2018
+
2019
+
2020
+
2021
+
2022
+
2023
+
2024
+
2025
+
2026
+
2027
+
2028
+
2029
+
2030
+
2031
+
2032
+
2033
+
2034
+
2035
+
2036
+
2037
+
2038
+
2039
+
2040
+
2041
+
2042
+
2043
+
2044
+
2045
+
2046
+
2047
+
2048
+
2049
+
2050
+
2051
+
2052
+
2053
+
2054
+
2055
+
2056
+
2057
+
2058
+
2059
+
2060
+
2061
+ * @example
2062
+ * // Iterate value arrays
2063
+ * const mm = new TreeMultiMap<number, string>();
2064
+ * mm.add(1, 'a');
2065
+ * mm.add(1, 'b');
2066
+ * console.log([...mm.values()]); // [['a', 'b']];
2067
+ */
2068
+ *values(): IterableIterator<V[]> {
2069
+ for (const [, bucket] of this) yield bucket;
2070
+ }
2071
+
2072
+ // ---- entry-flat views ----
2073
+
2074
+ /**
2075
+ * Iterates over all entries for a specific key.
2076
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
2077
+
2078
+
2079
+
2080
+
2081
+
2082
+
2083
+
2084
+
2085
+
2086
+
2087
+
2088
+
2089
+
2090
+
2091
+
2092
+
2093
+
2094
+
2095
+
2096
+
2097
+
2098
+
2099
+
2100
+
2101
+
2102
+
2103
+ * @example
2104
+ * // Get entries for key
2105
+ * const mm = new TreeMultiMap<number, string>();
2106
+ * mm.add(1, 'a');
2107
+ * mm.add(1, 'b');
2108
+ * console.log([...mm.entriesOf(1)]); // [[1, 'a'], [1, 'b']];
2109
+ */
2110
+ *entriesOf(key: K): IterableIterator<[K, V]> {
2111
+ const bucket = this.get(key);
2112
+ if (!Array.isArray(bucket)) return;
2113
+ for (const v of bucket) yield [key, v];
2114
+ }
2115
+
2116
+ /**
2117
+ * Iterates over all values for a specific key.
2118
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
2119
+
2120
+
2121
+
2122
+
2123
+
2124
+
2125
+
2126
+
2127
+
2128
+
2129
+
2130
+
2131
+
2132
+
2133
+
2134
+
2135
+
2136
+
2137
+
2138
+
2139
+
2140
+
2141
+
2142
+
2143
+
2144
+
2145
+ * @example
2146
+ * // Get flat values for key
2147
+ * const mm = new TreeMultiMap<number, string>();
2148
+ * mm.add(1, 'a');
2149
+ * mm.add(1, 'b');
2150
+ * console.log([...mm.valuesOf(1)]); // ['a', 'b'];
2151
+ */
2152
+ *valuesOf(key: K): IterableIterator<V> {
2153
+ const bucket = this.get(key);
2154
+ if (!Array.isArray(bucket)) return;
2155
+ yield* bucket;
2156
+ }
2157
+
2158
+ /**
2159
+ * Iterates over all [key, value] pairs (flattened from buckets).
2160
+ * @remarks Time O(T), Space O(1) where T is totalSize
2161
+
2162
+
2163
+
2164
+
2165
+
2166
+
2167
+
2168
+
2169
+
2170
+
2171
+
2172
+
2173
+
2174
+
2175
+
2176
+
2177
+
2178
+
2179
+
2180
+
2181
+
2182
+
2183
+
2184
+
2185
+
2186
+
2187
+ * @example
2188
+ * // All key-value pairs flattened
2189
+ * const mm = new TreeMultiMap<number, string>();
2190
+ * mm.add(1, 'a');
2191
+ * mm.add(1, 'b');
2192
+ * mm.add(2, 'c');
2193
+ * console.log([...mm.flatEntries()]); // [[1, 'a'], [1, 'b'], [2, 'c']];
2194
+ */
2195
+ *flatEntries(): IterableIterator<[K, V]> {
2196
+ for (const [k, bucket] of this) {
2197
+ for (const v of bucket) yield [k, v];
2198
+ }
2199
+ }
2200
+
2201
+ // ━━━ Navigable methods (return [K, V[]] | undefined) ━━━
2202
+
2203
+ /**
2204
+ * Returns the entry with the smallest key.
2205
+ * @remarks Time O(log n), Space O(1)
2206
+
2207
+
2208
+
2209
+
2210
+
2211
+
2212
+
2213
+
2214
+
2215
+
2216
+
2217
+
2218
+
2219
+
2220
+
2221
+
2222
+
2223
+
2224
+
2225
+
2226
+
2227
+
2228
+
2229
+
2230
+
2231
+
2232
+
2233
+
2234
+
2235
+
2236
+
2237
+
2238
+
2239
+
2240
+
2241
+
2242
+
2243
+
2244
+
2245
+
2246
+
2247
+
2248
+
2249
+
2250
+
2251
+
2252
+
2253
+
2254
+
2255
+
2256
+
2257
+
2258
+
2259
+
2260
+
2261
+
2262
+
2263
+
2264
+
2265
+
2266
+
2267
+
2268
+ * @example
2269
+ * // First entry
2270
+ * const mm = new TreeMultiMap<number, string>();
2271
+ * mm.add(3, 'c');
2272
+ * mm.add(1, 'a');
2273
+ * console.log(mm.first()?.[0]); // 1;
2274
+ */
2275
+ first(): [K, V[]] | undefined {
2276
+ const k = this.#core.getLeftMost();
2277
+ if (k === undefined) return undefined;
2278
+ const b = this.get(k);
2279
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2280
+ }
2281
+
2282
+ /**
2283
+ * Returns the entry with the largest key.
2284
+ * @remarks Time O(log n), Space O(1)
2285
+
2286
+
2287
+
2288
+
2289
+
2290
+
2291
+
2292
+
2293
+
2294
+
2295
+
2296
+
2297
+
2298
+
2299
+
2300
+
2301
+
2302
+
2303
+
2304
+
2305
+
2306
+
2307
+
2308
+
2309
+
2310
+
2311
+
2312
+
2313
+
2314
+
2315
+
2316
+
2317
+
2318
+
2319
+
2320
+
2321
+
2322
+
2323
+
2324
+
2325
+
2326
+
2327
+
2328
+
2329
+
2330
+
2331
+
2332
+
2333
+
2334
+
2335
+
2336
+
2337
+
2338
+
2339
+
2340
+
2341
+
2342
+
2343
+
2344
+
2345
+
2346
+
2347
+ * @example
2348
+ * // Last entry
2349
+ * const mm = new TreeMultiMap<number, string>();
2350
+ * mm.add(1, 'a');
2351
+ * mm.add(3, 'c');
2352
+ * console.log(mm.last()?.[0]); // 3;
2353
+ */
2354
+ last(): [K, V[]] | undefined {
2355
+ const k = this.#core.getRightMost();
2356
+ if (k === undefined) return undefined;
2357
+ const b = this.get(k);
2358
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2359
+ }
2360
+
2361
+ /**
2362
+ * Removes and returns the entry with the smallest key.
2363
+ * @remarks Time O(log n), Space O(1)
2364
+
2365
+
2366
+
2367
+
2368
+
2369
+
2370
+
2371
+
2372
+
2373
+
2374
+
2375
+
2376
+
2377
+
2378
+
2379
+
2380
+
2381
+
2382
+
2383
+
2384
+
2385
+
2386
+
2387
+
2388
+
2389
+
2390
+
2391
+ * @example
2392
+ * // Remove and return first
2393
+ * const mm = new TreeMultiMap<number, string>();
2394
+ * mm.add(2, 'b');
2395
+ * mm.add(1, 'a');
2396
+ * const first = mm.pollFirst();
2397
+ * console.log(first?.[0]); // 1;
2398
+ * console.log(mm.has(1)); // false;
2399
+ */
2400
+ pollFirst(): [K, V[]] | undefined {
2401
+ const e = this.first();
2402
+ if (!e) return undefined;
2403
+ this.delete(e[0]);
2404
+ return e;
2405
+ }
2406
+
2407
+ /**
2408
+ * Removes and returns the entry with the largest key.
2409
+ * @remarks Time O(log n), Space O(1)
2410
+
2411
+
2412
+
2413
+
2414
+
2415
+
2416
+
2417
+
2418
+
2419
+
2420
+
2421
+
2422
+
2423
+
2424
+
2425
+
2426
+
2427
+
2428
+
2429
+
2430
+
2431
+
2432
+
2433
+
2434
+
2435
+
2436
+
2437
+ * @example
2438
+ * // Remove and return last
2439
+ * const mm = new TreeMultiMap<number, string>();
2440
+ * mm.add(1, 'a');
2441
+ * mm.add(3, 'c');
2442
+ * const last = mm.pollLast();
2443
+ * console.log(last?.[0]); // 3;
2444
+ */
2445
+ pollLast(): [K, V[]] | undefined {
2446
+ const e = this.last();
2447
+ if (!e) return undefined;
2448
+ this.delete(e[0]);
2449
+ return e;
2450
+ }
2451
+
2452
+ /**
2453
+ * Returns the entry with the smallest key >= given key.
2454
+ * @remarks Time O(log n), Space O(1)
2455
+
2456
+
2457
+
2458
+
2459
+
2460
+
2461
+
2462
+
2463
+
2464
+
2465
+
2466
+
2467
+
2468
+
2469
+
2470
+
2471
+
2472
+
2473
+
2474
+
2475
+
2476
+
2477
+
2478
+
2479
+
2480
+
2481
+
2482
+
2483
+
2484
+
2485
+
2486
+
2487
+
2488
+
2489
+
2490
+
2491
+
2492
+
2493
+
2494
+
2495
+
2496
+
2497
+
2498
+
2499
+
2500
+
2501
+
2502
+
2503
+
2504
+
2505
+
2506
+
2507
+
2508
+
2509
+
2510
+
2511
+
2512
+
2513
+
2514
+
2515
+
2516
+
2517
+
2518
+
2519
+
2520
+
2521
+
2522
+
2523
+
2524
+
2525
+
2526
+
2527
+
2528
+
2529
+
2530
+
2531
+
2532
+
2533
+
2534
+
2535
+
2536
+
2537
+
2538
+
2539
+
2540
+
2541
+
2542
+
2543
+
2544
+
2545
+
2546
+
2547
+
2548
+
2549
+
2550
+
2551
+
2552
+
2553
+
2554
+
2555
+
2556
+
2557
+
2558
+
2559
+
2560
+
2561
+
2562
+
2563
+
2564
+
2565
+
2566
+
2567
+
2568
+
2569
+
2570
+
2571
+
2572
+
2573
+
2574
+
2575
+
2576
+
2577
+
2578
+
2579
+
2580
+
2581
+
2582
+
2583
+
2584
+
2585
+
2586
+
2587
+
2588
+
2589
+
2590
+
2591
+
2592
+
2593
+
2594
+
2595
+
2596
+
2597
+
2598
+
2599
+
2600
+
2601
+
2602
+
2603
+
2604
+
2605
+
2606
+
2607
+
2608
+
2609
+
2610
+
2611
+
2612
+
2613
+
2614
+
2615
+
2616
+ * @example
2617
+ * // Least key ≥ target
2618
+ * const mm = new TreeMultiMap<number, string>();
2619
+ * mm.add(10, 'a');
2620
+ * mm.add(20, 'b');
2621
+ * mm.add(30, 'c');
2622
+ * console.log(mm.ceiling(15)?.[0]); // 20;
2623
+ */
2624
+ ceiling(key: K): [K, V[]] | undefined {
2625
+ this._validateKey(key);
2626
+ const k = this.#core.ceiling(key);
2627
+ if (k === undefined) return undefined;
2628
+ const b = this.get(k);
2629
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2630
+ }
2631
+
2632
+ /**
2633
+ * Returns the entry with the largest key <= given key.
2634
+ * @remarks Time O(log n), Space O(1)
2635
+
2636
+
2637
+
2638
+
2639
+
2640
+
2641
+
2642
+
2643
+
2644
+
2645
+
2646
+
2647
+
2648
+
2649
+
2650
+
2651
+
2652
+
2653
+
2654
+
2655
+
2656
+
2657
+
2658
+
2659
+
2660
+
2661
+
2662
+
2663
+
2664
+
2665
+
2666
+
2667
+
2668
+
2669
+
2670
+
2671
+
2672
+
2673
+
2674
+
2675
+
2676
+
2677
+
2678
+
2679
+
2680
+
2681
+
2682
+
2683
+
2684
+
2685
+
2686
+
2687
+
2688
+
2689
+
2690
+
2691
+
2692
+
2693
+
2694
+
2695
+
2696
+
2697
+
2698
+
2699
+
2700
+
2701
+
2702
+
2703
+
2704
+
2705
+
2706
+
2707
+
2708
+
2709
+
2710
+
2711
+
2712
+
2713
+
2714
+
2715
+
2716
+
2717
+
2718
+
2719
+
2720
+
2721
+
2722
+
2723
+
2724
+
2725
+
2726
+
2727
+
2728
+
2729
+
2730
+
2731
+
2732
+
2733
+
2734
+
2735
+
2736
+
2737
+
2738
+
2739
+
2740
+
2741
+
2742
+
2743
+
2744
+
2745
+
2746
+
2747
+
2748
+
2749
+
2750
+
2751
+
2752
+
2753
+
2754
+
2755
+
2756
+
2757
+
2758
+
2759
+
2760
+
2761
+
2762
+
2763
+
2764
+
2765
+
2766
+
2767
+
2768
+
2769
+
2770
+
2771
+
2772
+
2773
+
2774
+
2775
+
2776
+
2777
+
2778
+
2779
+
2780
+
2781
+
2782
+
2783
+
2784
+
2785
+
2786
+
2787
+
2788
+
2789
+
2790
+
2791
+
2792
+
2793
+
2794
+
2795
+
2796
+ * @example
2797
+ * // Greatest key ≤ target
2798
+ * const mm = new TreeMultiMap<number, string>();
2799
+ * mm.add(10, 'a');
2800
+ * mm.add(20, 'b');
2801
+ * mm.add(30, 'c');
2802
+ * console.log(mm.floor(25)?.[0]); // 20;
2803
+ */
2804
+ floor(key: K): [K, V[]] | undefined {
2805
+ this._validateKey(key);
2806
+ const k = this.#core.floor(key);
2807
+ if (k === undefined) return undefined;
2808
+ const b = this.get(k);
2809
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2810
+ }
2811
+
2812
+ /**
2813
+ * Returns the entry with the smallest key > given key.
2814
+ * @remarks Time O(log n), Space O(1)
2815
+
2816
+
2817
+
2818
+
2819
+
2820
+
2821
+
2822
+
2823
+
2824
+
2825
+
2826
+
2827
+
2828
+
2829
+
2830
+
2831
+
2832
+
2833
+
2834
+
2835
+
2836
+
2837
+
2838
+
2839
+
2840
+
2841
+
2842
+
2843
+
2844
+
2845
+
2846
+
2847
+
2848
+
2849
+
2850
+
2851
+
2852
+
2853
+
2854
+
2855
+
2856
+
2857
+
2858
+
2859
+
2860
+
2861
+
2862
+
2863
+
2864
+
2865
+
2866
+
2867
+
2868
+
2869
+
2870
+
2871
+
2872
+
2873
+
2874
+
2875
+
2876
+
2877
+
2878
+
2879
+
2880
+
2881
+
2882
+
2883
+
2884
+
2885
+
2886
+
2887
+
2888
+
2889
+
2890
+
2891
+
2892
+
2893
+
2894
+
2895
+
2896
+
2897
+
2898
+
2899
+
2900
+
2901
+
2902
+
2903
+
2904
+
2905
+
2906
+
2907
+
2908
+
2909
+
2910
+
2911
+
2912
+
2913
+
2914
+
2915
+
2916
+
2917
+
2918
+
2919
+
2920
+
2921
+
2922
+
2923
+
2924
+
2925
+
2926
+
2927
+
2928
+
2929
+
2930
+
2931
+
2932
+
2933
+
2934
+
2935
+
2936
+
2937
+
2938
+
2939
+
2940
+
2941
+ * @example
2942
+ * // Least key > target
2943
+ * const mm = new TreeMultiMap<number, string>();
2944
+ * mm.add(10, 'a');
2945
+ * mm.add(20, 'b');
2946
+ * console.log(mm.higher(10)?.[0]); // 20;
2947
+ */
2948
+ higher(key: K): [K, V[]] | undefined {
2949
+ this._validateKey(key);
2950
+ const k = this.#core.higher(key);
2951
+ if (k === undefined) return undefined;
2952
+ const b = this.get(k);
2953
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2954
+ }
2955
+
2956
+ /**
2957
+ * Returns the entry with the largest key < given key.
2958
+ * @remarks Time O(log n), Space O(1)
2959
+
2960
+
2961
+
2962
+
2963
+
2964
+
2965
+
2966
+
2967
+
2968
+
2969
+
2970
+
2971
+
2972
+
2973
+
2974
+
2975
+
2976
+
2977
+
2978
+
2979
+
2980
+
2981
+
2982
+
2983
+
2984
+
2985
+
2986
+
2987
+
2988
+
2989
+
2990
+
2991
+
2992
+
2993
+
2994
+
2995
+
2996
+
2997
+
2998
+
2999
+
3000
+
3001
+
3002
+
3003
+
3004
+
3005
+
3006
+
3007
+
3008
+
3009
+
3010
+
3011
+
3012
+
3013
+
3014
+
3015
+
3016
+
3017
+
3018
+
3019
+
3020
+
3021
+
3022
+
3023
+
3024
+
3025
+
3026
+
3027
+
3028
+
3029
+
3030
+
3031
+
3032
+
3033
+
3034
+
3035
+
3036
+
3037
+
3038
+
3039
+
3040
+
3041
+
3042
+
3043
+
3044
+
3045
+
3046
+
3047
+
3048
+
3049
+
3050
+
3051
+
3052
+
3053
+
3054
+
3055
+
3056
+
3057
+
3058
+
3059
+
3060
+
3061
+
3062
+
3063
+
3064
+
3065
+
3066
+
3067
+
3068
+
3069
+
3070
+
3071
+
3072
+
3073
+
3074
+
3075
+
3076
+
3077
+
3078
+
3079
+
3080
+
3081
+
3082
+
3083
+
3084
+
3085
+ * @example
3086
+ * // Greatest key < target
3087
+ * const mm = new TreeMultiMap<number, string>();
3088
+ * mm.add(10, 'a');
3089
+ * mm.add(20, 'b');
3090
+ * console.log(mm.lower(20)?.[0]); // 10;
3091
+ */
3092
+ lower(key: K): [K, V[]] | undefined {
3093
+ this._validateKey(key);
3094
+ const k = this.#core.lower(key);
3095
+ if (k === undefined) return undefined;
3096
+ const b = this.get(k);
3097
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
3098
+ }
3099
+
3100
+ // ━━━ Tree utilities ━━━
3101
+
3102
+ /**
3103
+ * Prints the internal tree structure (for debugging).
3104
+ * @remarks Time O(n), Space O(n)
3105
+
3106
+
3107
+
3108
+
3109
+
3110
+
3111
+
3112
+
3113
+
3114
+
3115
+
3116
+
3117
+
3118
+
3119
+
3120
+
3121
+
3122
+
3123
+
3124
+
3125
+
3126
+
3127
+
3128
+
3129
+
3130
+
3131
+
3132
+
3133
+
3134
+
3135
+
3136
+
3137
+
3138
+
3139
+
3140
+
3141
+
3142
+
3143
+
3144
+
3145
+
3146
+
3147
+
3148
+
3149
+
3150
+
3151
+
3152
+
3153
+
3154
+
3155
+
3156
+
3157
+
3158
+
3159
+
3160
+
3161
+
3162
+
3163
+
3164
+
3165
+
3166
+
3167
+
3168
+
3169
+
3170
+
3171
+
3172
+
3173
+
3174
+
3175
+
3176
+
3177
+
3178
+
3179
+
3180
+
3181
+
3182
+
3183
+
3184
+
3185
+
3186
+
3187
+
3188
+
3189
+
3190
+
3191
+
3192
+
3193
+
3194
+
3195
+
3196
+
3197
+
3198
+
3199
+
3200
+
3201
+
3202
+
3203
+
3204
+
3205
+
3206
+
3207
+
3208
+
3209
+
3210
+
3211
+
3212
+
3213
+
3214
+
3215
+
3216
+
3217
+
3218
+
3219
+
3220
+
3221
+
3222
+
3223
+
3224
+
3225
+
3226
+
3227
+
3228
+
3229
+
3230
+
3231
+
3232
+
3233
+
3234
+
3235
+
3236
+
3237
+
3238
+
3239
+
3240
+
3241
+
3242
+
3243
+
3244
+
3245
+
3246
+
3247
+
3248
+
3249
+
3250
+
3251
+
3252
+
3253
+
3254
+
3255
+
3256
+
3257
+
3258
+
3259
+
3260
+
3261
+
3262
+
3263
+ * @example
3264
+ * // Display tree
3265
+ * const mm = new TreeMultiMap<number, string>();
3266
+ * mm.add(1, 'a');
3267
+ * expect(() => mm.print()).not.toThrow();
3268
+ */
3269
+ print(): void {
3270
+ this.#core.print();
3271
+ }
3272
+
3273
+ /**
3274
+ * Executes a callback for each entry.
3275
+ * @remarks Time O(n), Space O(1)
3276
+
3277
+
3278
+
3279
+
3280
+
3281
+
3282
+
3283
+
3284
+
3285
+
3286
+
3287
+
3288
+
3289
+
3290
+
3291
+
3292
+
3293
+
3294
+
3295
+
3296
+
3297
+
3298
+
3299
+
3300
+
3301
+
3302
+
3303
+
3304
+
3305
+
3306
+
3307
+
3308
+
3309
+
3310
+
3311
+
3312
+
3313
+
3314
+
3315
+
3316
+
3317
+
3318
+
3319
+
3320
+
3321
+
3322
+
3323
+
3324
+
3325
+
3326
+
3327
+
3328
+
3329
+
3330
+
3331
+
3332
+
3333
+
3334
+
3335
+
3336
+
3337
+
3338
+
3339
+
3340
+
3341
+
3342
+
3343
+
3344
+
3345
+
3346
+
3347
+
3348
+
3349
+
3350
+
3351
+
3352
+
3353
+
3354
+
3355
+
3356
+
3357
+
3358
+
3359
+
3360
+
3361
+
3362
+
3363
+
3364
+
3365
+
3366
+
3367
+
3368
+
3369
+
3370
+
3371
+
3372
+
3373
+
3374
+
3375
+
3376
+
3377
+
3378
+
3379
+
3380
+
3381
+
3382
+
3383
+
3384
+
3385
+
3386
+
3387
+
3388
+
3389
+
3390
+
3391
+
3392
+
3393
+
3394
+
3395
+
3396
+
3397
+
3398
+
3399
+
3400
+
3401
+
3402
+
3403
+
3404
+
3405
+
3406
+
3407
+
3408
+
3409
+
3410
+
3411
+
3412
+
3413
+
3414
+
3415
+
3416
+
3417
+
3418
+
3419
+
3420
+
3421
+
3422
+
3423
+
3424
+
3425
+
3426
+
3427
+
3428
+
3429
+
3430
+
3431
+
3432
+
3433
+
3434
+ * @example
3435
+ * // Iterate entries
3436
+ * const mm = new TreeMultiMap<number, string>();
3437
+ * mm.add(1, 'a');
3438
+ * mm.add(2, 'b');
3439
+ * const keys: number[] = [];
3440
+ * mm.forEach((v, k) => keys.push(k));
3441
+ * console.log(keys); // [1, 2];
3442
+ */
3443
+ forEach(callback: (value: V[], key: K, map: this) => void): void {
3444
+ for (const [k, v] of this) {
3445
+ callback(v, k, this);
3446
+ }
3447
+ }
3448
+
3449
+ /**
3450
+ * Creates a new map with entries that pass the predicate.
3451
+ * @remarks Time O(n), Space O(n)
3452
+
3453
+
3454
+
3455
+
3456
+
3457
+
3458
+
3459
+
3460
+
3461
+
3462
+
3463
+
3464
+
3465
+
3466
+
3467
+
3468
+
3469
+
3470
+
3471
+
3472
+
3473
+
3474
+
3475
+
3476
+
3477
+
3478
+
3479
+
3480
+
3481
+
3482
+
3483
+
3484
+
3485
+
3486
+
3487
+
3488
+
3489
+
3490
+
3491
+
3492
+
3493
+
3494
+
3495
+
3496
+
3497
+
3498
+
3499
+
3500
+
3501
+
3502
+
3503
+
3504
+
3505
+
3506
+
3507
+
3508
+
3509
+
3510
+
3511
+
3512
+
3513
+
3514
+
3515
+
3516
+
3517
+
3518
+
3519
+
3520
+
3521
+
3522
+
3523
+
3524
+
3525
+
3526
+
3527
+
3528
+
3529
+
3530
+
3531
+
3532
+
3533
+
3534
+
3535
+
3536
+
3537
+
3538
+
3539
+
3540
+
3541
+
3542
+
3543
+
3544
+
3545
+
3546
+
3547
+
3548
+
3549
+
3550
+
3551
+
3552
+
3553
+
3554
+
3555
+
3556
+
3557
+
3558
+
3559
+
3560
+
3561
+
3562
+
3563
+
3564
+
3565
+
3566
+
3567
+
3568
+
3569
+
3570
+
3571
+
3572
+
3573
+
3574
+
3575
+
3576
+
3577
+
3578
+
3579
+
3580
+
3581
+
3582
+
3583
+
3584
+
3585
+
3586
+
3587
+
3588
+
3589
+
3590
+
3591
+
3592
+
3593
+
3594
+
3595
+
3596
+
3597
+
3598
+
3599
+
3600
+
3601
+
3602
+
3603
+
3604
+
3605
+
3606
+
3607
+
3608
+
3609
+
3610
+ * @example
3611
+ * // Filter entries
3612
+ * const mm = new TreeMultiMap<number, string>();
3613
+ * mm.add(1, 'a');
3614
+ * mm.add(2, 'b');
3615
+ * mm.add(3, 'c');
3616
+ * const filtered = mm.filter((v, k) => k > 1);
3617
+ * console.log([...filtered.keys()]); // [2, 3];
3618
+ */
3619
+ filter(predicate: (value: V[], key: K, map: this) => boolean): TreeMultiMap<K, V, R> {
3620
+ const filtered: [K, V[]][] = [];
3621
+ for (const [k, v] of this) {
3622
+ if (predicate(v, k, this)) filtered.push([k, v]);
3623
+ }
3624
+ return new TreeMultiMap<K, V, R>(filtered, { comparator: this.comparator });
3625
+ }
3626
+
3627
+ /**
3628
+ * Creates a new map by transforming each entry.
3629
+ * @remarks Time O(n log n), Space O(n)
3630
+
3631
+
3632
+
3633
+
3634
+
3635
+
3636
+
3637
+
3638
+
3639
+
3640
+
3641
+
3642
+
3643
+
3644
+
3645
+
3646
+
3647
+
3648
+
3649
+
3650
+
3651
+
3652
+
3653
+
3654
+
3655
+
3656
+
3657
+
3658
+
3659
+
3660
+
3661
+
3662
+
3663
+
3664
+
3665
+
3666
+
3667
+
3668
+
3669
+
3670
+
3671
+
3672
+
3673
+
3674
+
3675
+
3676
+
3677
+
3678
+
3679
+
3680
+
3681
+
3682
+
3683
+
3684
+
3685
+
3686
+
3687
+
3688
+
3689
+
3690
+
3691
+
3692
+
3693
+
3694
+
3695
+
3696
+
3697
+
3698
+
3699
+
3700
+
3701
+
3702
+
3703
+
3704
+
3705
+
3706
+
3707
+
3708
+
3709
+
3710
+
3711
+
3712
+
3713
+
3714
+
3715
+
3716
+
3717
+
3718
+
3719
+
3720
+
3721
+
3722
+
3723
+
3724
+
3725
+
3726
+
3727
+
3728
+
3729
+
3730
+
3731
+
3732
+
3733
+
3734
+
3735
+
3736
+
3737
+
3738
+
3739
+
3740
+
3741
+
3742
+
3743
+
3744
+
3745
+
3746
+
3747
+
3748
+
3749
+
3750
+
3751
+
3752
+
3753
+
3754
+
3755
+
3756
+
3757
+
3758
+
3759
+
3760
+
3761
+
3762
+
3763
+
3764
+
3765
+
3766
+
3767
+
3768
+
3769
+
3770
+
3771
+
3772
+
3773
+
3774
+
3775
+
3776
+
3777
+
3778
+
3779
+
3780
+
3781
+
3782
+
3783
+
3784
+
3785
+
3786
+
3787
+
3788
+ * @example
3789
+ * // Transform values
3790
+ * const mm = new TreeMultiMap<number, string>();
3791
+ * mm.add(1, 'a');
3792
+ * const mapped = mm.map((v, k) => [k, v.map(s => s.toUpperCase())] as [number, string[]]);
3793
+ * console.log(mapped.get(1)); // ['A'];
3794
+ */
3795
+ map<V2>(
3796
+ mapper: (value: V[], key: K, map: this) => [K, V2[]]
3797
+ ): TreeMultiMap<K, V2, R> {
3798
+ const mapped: [K, V2[]][] = [];
3799
+ for (const [k, v] of this) {
3800
+ mapped.push(mapper(v, k, this));
3801
+ }
3802
+ return new TreeMultiMap<K, V2, R>(mapped, { comparator: this.comparator });
3803
+ }
3804
+
3805
+ /**
3806
+ * Reduces all entries to a single value.
3807
+ * @remarks Time O(n), Space O(1)
3808
+
3809
+
3810
+
3811
+
3812
+
3813
+
3814
+
3815
+
3816
+
3817
+
3818
+
3819
+
3820
+
3821
+
3822
+
3823
+
3824
+
3825
+
3826
+
3827
+
3828
+
3829
+
3830
+
3831
+
3832
+
3833
+
3834
+
3835
+
3836
+
3837
+
3838
+
3839
+
3840
+
3841
+
3842
+
3843
+
3844
+
3845
+
3846
+
3847
+
3848
+
3849
+
3850
+
3851
+
3852
+
3853
+
3854
+
3855
+
3856
+
3857
+
3858
+
3859
+
3860
+
3861
+
3862
+
3863
+
3864
+
3865
+
3866
+
3867
+
3868
+
3869
+
3870
+
3871
+
3872
+
3873
+
3874
+
3875
+
3876
+
3877
+
3878
+
3879
+
3880
+
3881
+
3882
+
3883
+
3884
+
3885
+
3886
+
3887
+
3888
+
3889
+
3890
+
3891
+
3892
+
3893
+
3894
+
3895
+
3896
+
3897
+
3898
+
3899
+
3900
+
3901
+
3902
+
3903
+
3904
+
3905
+
3906
+
3907
+
3908
+
3909
+
3910
+
3911
+
3912
+
3913
+
3914
+
3915
+
3916
+
3917
+
3918
+
3919
+
3920
+
3921
+
3922
+
3923
+
3924
+
3925
+
3926
+
3927
+
3928
+
3929
+
3930
+
3931
+
3932
+
3933
+
3934
+
3935
+
3936
+
3937
+
3938
+
3939
+
3940
+
3941
+
3942
+
3943
+
3944
+
3945
+
3946
+
3947
+
3948
+
3949
+
3950
+
3951
+
3952
+
3953
+
3954
+
3955
+
3956
+
3957
+
3958
+
3959
+
3960
+
3961
+
3962
+
3963
+
3964
+
3965
+
3966
+ * @example
3967
+ * // Aggregate
3968
+ * const mm = new TreeMultiMap<number, number>();
3969
+ * mm.add(1, 10);
3970
+ * mm.add(2, 20);
3971
+ * const sum = mm.reduce((acc, v) => acc + v.reduce((a, b) => a + b, 0), 0);
3972
+ * console.log(sum); // 30;
3973
+ */
3974
+ reduce<U>(callback: (accumulator: U, value: V[], key: K, map: this) => U, initialValue: U): U {
3975
+ let acc = initialValue;
3976
+ for (const [k, v] of this) {
3977
+ acc = callback(acc, v, k, this);
3978
+ }
3979
+ return acc;
3980
+ }
3981
+
3982
+ /**
3983
+ * Sets multiple entries at once.
3984
+ * @remarks Time O(m log n), Space O(m) where m is input size
3985
+
3986
+
3987
+
3988
+
3989
+
3990
+
3991
+
3992
+
3993
+
3994
+
3995
+
3996
+
3997
+
3998
+
3999
+
4000
+
4001
+
4002
+
4003
+
4004
+
4005
+
4006
+
4007
+
4008
+
4009
+
4010
+
4011
+
4012
+
4013
+
4014
+
4015
+
4016
+
4017
+
4018
+
4019
+
4020
+
4021
+
4022
+
4023
+
4024
+
4025
+
4026
+
4027
+
4028
+
4029
+
4030
+
4031
+
4032
+
4033
+
4034
+
4035
+
4036
+
4037
+
4038
+
4039
+
4040
+
4041
+
4042
+
4043
+
4044
+
4045
+
4046
+
4047
+
4048
+
4049
+
4050
+
4051
+
4052
+
4053
+
4054
+
4055
+
4056
+
4057
+
4058
+
4059
+
4060
+
4061
+
4062
+
4063
+
4064
+
4065
+
4066
+
4067
+
4068
+
4069
+
4070
+
4071
+
4072
+
4073
+
4074
+
4075
+
4076
+
4077
+
4078
+
4079
+
4080
+
4081
+
4082
+
4083
+
4084
+
4085
+
4086
+
4087
+
4088
+
4089
+
4090
+
4091
+
4092
+
4093
+
4094
+
4095
+
4096
+
4097
+
4098
+
4099
+
4100
+
4101
+
4102
+
4103
+
4104
+
4105
+
1112
4106
 
1113
4107
 
1114
4108
 
@@ -1139,28 +4133,23 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1139
4133
 
1140
4134
 
1141
4135
  * @example
1142
- * // Greatest key < target
4136
+ * // Set multiple entries
1143
4137
  * const mm = new TreeMultiMap<number, string>();
1144
- * mm.add(10, 'a');
1145
- * mm.add(20, 'b');
1146
- * console.log(mm.lower(20)?.[0]); // 10;
4138
+ * mm.setMany([[1, ['a']], [2, ['b']]]);
4139
+ * console.log(mm.size); // 2;
1147
4140
  */
1148
- lower(key: K): [K, V[]] | undefined {
1149
- this._validateKey(key);
1150
- const k = this.#core.lower(key);
1151
- if (k === undefined) return undefined;
1152
- const b = this.get(k);
1153
- return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
4141
+ setMany(keysNodesEntriesOrRaws: Iterable<K | [K | null | undefined, V[] | undefined]>): boolean[] {
4142
+ const results: boolean[] = [];
4143
+ for (const x of keysNodesEntriesOrRaws) {
4144
+ // Call implementation directly: entry can be K or [K, V[]] or [K, undefined]
4145
+ results.push(this.set(x));
4146
+ }
4147
+ return results;
1154
4148
  }
1155
4149
 
1156
- // ━━━ Tree utilities ━━━
1157
-
1158
4150
  /**
1159
- * Prints the internal tree structure (for debugging).
1160
- * @remarks Time O(n), Space O(n)
1161
-
1162
-
1163
-
4151
+ * Searches for entries within a key range.
4152
+ * @remarks Time O(log n + k), Space O(k) where k is result size
1164
4153
 
1165
4154
 
1166
4155
 
@@ -1196,19 +4185,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1196
4185
 
1197
4186
 
1198
4187
 
1199
- * @example
1200
- * // Display tree
1201
- * const mm = new TreeMultiMap<number, string>();
1202
- * mm.add(1, 'a');
1203
- * expect(() => mm.print()).not.toThrow();
1204
- */
1205
- print(): void {
1206
- this.#core.print();
1207
- }
1208
-
1209
- /**
1210
- * Executes a callback for each entry.
1211
- * @remarks Time O(n), Space O(1)
1212
4188
 
1213
4189
 
1214
4190
 
@@ -1247,24 +4223,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1247
4223
 
1248
4224
 
1249
4225
 
1250
- * @example
1251
- * // Iterate entries
1252
- * const mm = new TreeMultiMap<number, string>();
1253
- * mm.add(1, 'a');
1254
- * mm.add(2, 'b');
1255
- * const keys: number[] = [];
1256
- * mm.forEach((v, k) => keys.push(k));
1257
- * console.log(keys); // [1, 2];
1258
- */
1259
- forEach(callback: (value: V[], key: K, map: this) => void): void {
1260
- for (const [k, v] of this) {
1261
- callback(v, k, this);
1262
- }
1263
- }
1264
-
1265
- /**
1266
- * Creates a new map with entries that pass the predicate.
1267
- * @remarks Time O(n), Space O(n)
1268
4226
 
1269
4227
 
1270
4228
 
@@ -1303,26 +4261,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1303
4261
 
1304
4262
 
1305
4263
 
1306
- * @example
1307
- * // Filter entries
1308
- * const mm = new TreeMultiMap<number, string>();
1309
- * mm.add(1, 'a');
1310
- * mm.add(2, 'b');
1311
- * mm.add(3, 'c');
1312
- * const filtered = mm.filter((v, k) => k > 1);
1313
- * console.log([...filtered.keys()]); // [2, 3];
1314
- */
1315
- filter(predicate: (value: V[], key: K, map: this) => boolean): TreeMultiMap<K, V, R> {
1316
- const filtered: [K, V[]][] = [];
1317
- for (const [k, v] of this) {
1318
- if (predicate(v, k, this)) filtered.push([k, v]);
1319
- }
1320
- return new TreeMultiMap<K, V, R>(filtered, { comparator: this.comparator });
1321
- }
1322
-
1323
- /**
1324
- * Creates a new map by transforming each entry.
1325
- * @remarks Time O(n log n), Space O(n)
1326
4264
 
1327
4265
 
1328
4266
 
@@ -1338,6 +4276,25 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1338
4276
 
1339
4277
 
1340
4278
 
4279
+ * @example
4280
+ * // Find keys in range
4281
+ * const mm = new TreeMultiMap<number, string>();
4282
+ * mm.add(10, 'a');
4283
+ * mm.add(20, 'b');
4284
+ * mm.add(30, 'c');
4285
+ * const result = mm.rangeSearch([15, 25]);
4286
+ * console.log(result.length); // 1;
4287
+ */
4288
+ rangeSearch<C extends (node: RedBlackTreeNode<K, V[]>) => unknown>(
4289
+ range: Range<K> | [K, K],
4290
+ callback?: C
4291
+ ): ReturnType<C>[] {
4292
+ return this.#core.rangeSearch(range, callback as (node: RedBlackTreeNode<K, V[]>) => ReturnType<C>);
4293
+ }
4294
+
4295
+ /**
4296
+ * Creates a shallow clone of this map.
4297
+ * @remarks Time O(n log n), Space O(n)
1341
4298
 
1342
4299
 
1343
4300
 
@@ -1361,26 +4318,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1361
4318
 
1362
4319
 
1363
4320
 
1364
- * @example
1365
- * // Transform values
1366
- * const mm = new TreeMultiMap<number, string>();
1367
- * mm.add(1, 'a');
1368
- * const mapped = mm.map((v, k) => [k, v.map(s => s.toUpperCase())] as [number, string[]]);
1369
- * console.log(mapped.get(1)); // ['A'];
1370
- */
1371
- map<V2>(
1372
- mapper: (value: V[], key: K, map: this) => [K, V2[]]
1373
- ): TreeMultiMap<K, V2, R> {
1374
- const mapped: [K, V2[]][] = [];
1375
- for (const [k, v] of this) {
1376
- mapped.push(mapper(v, k, this));
1377
- }
1378
- return new TreeMultiMap<K, V2, R>(mapped, { comparator: this.comparator });
1379
- }
1380
-
1381
- /**
1382
- * Reduces all entries to a single value.
1383
- * @remarks Time O(n), Space O(1)
1384
4321
 
1385
4322
 
1386
4323
 
@@ -1419,25 +4356,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1419
4356
 
1420
4357
 
1421
4358
 
1422
- * @example
1423
- * // Aggregate
1424
- * const mm = new TreeMultiMap<number, number>();
1425
- * mm.add(1, 10);
1426
- * mm.add(2, 20);
1427
- * const sum = mm.reduce((acc, v) => acc + v.reduce((a, b) => a + b, 0), 0);
1428
- * console.log(sum); // 30;
1429
- */
1430
- reduce<U>(callback: (accumulator: U, value: V[], key: K, map: this) => U, initialValue: U): U {
1431
- let acc = initialValue;
1432
- for (const [k, v] of this) {
1433
- acc = callback(acc, v, k, this);
1434
- }
1435
- return acc;
1436
- }
1437
-
1438
- /**
1439
- * Sets multiple entries at once.
1440
- * @remarks Time O(m log n), Space O(m) where m is input size
1441
4359
 
1442
4360
 
1443
4361
 
@@ -1468,24 +4386,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1468
4386
 
1469
4387
 
1470
4388
 
1471
- * @example
1472
- * // Set multiple entries
1473
- * const mm = new TreeMultiMap<number, string>();
1474
- * mm.setMany([[1, ['a']], [2, ['b']]]);
1475
- * console.log(mm.size); // 2;
1476
- */
1477
- setMany(keysNodesEntriesOrRaws: Iterable<K | [K | null | undefined, V[] | undefined]>): boolean[] {
1478
- const results: boolean[] = [];
1479
- for (const x of keysNodesEntriesOrRaws) {
1480
- // Call implementation directly: entry can be K or [K, V[]] or [K, undefined]
1481
- results.push(this.set(x));
1482
- }
1483
- return results;
1484
- }
1485
-
1486
- /**
1487
- * Searches for entries within a key range.
1488
- * @remarks Time O(log n + k), Space O(k) where k is result size
1489
4389
 
1490
4390
 
1491
4391
 
@@ -1516,25 +4416,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1516
4416
 
1517
4417
 
1518
4418
 
1519
- * @example
1520
- * // Find keys in range
1521
- * const mm = new TreeMultiMap<number, string>();
1522
- * mm.add(10, 'a');
1523
- * mm.add(20, 'b');
1524
- * mm.add(30, 'c');
1525
- * const result = mm.rangeSearch([15, 25]);
1526
- * console.log(result.length); // 1;
1527
- */
1528
- rangeSearch<C extends (node: RedBlackTreeNode<K, V[]>) => unknown>(
1529
- range: Range<K> | [K, K],
1530
- callback?: C
1531
- ): ReturnType<C>[] {
1532
- return this.#core.rangeSearch(range, callback as (node: RedBlackTreeNode<K, V[]>) => ReturnType<C>);
1533
- }
1534
-
1535
- /**
1536
- * Creates a shallow clone of this map.
1537
- * @remarks Time O(n log n), Space O(n)
1538
4419
 
1539
4420
 
1540
4421
 
@@ -1570,6 +4451,66 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1570
4451
 
1571
4452
 
1572
4453
 
4454
+ * @example
4455
+ * // Order-statistic on BST
4456
+ * const tree = new TreeMultiMap<number>([30, 10, 50, 20, 40], { enableOrderStatistic: true });
4457
+ * console.log(tree.getByRank(0)); // 10;
4458
+ * console.log(tree.getByRank(4)); // 50;
4459
+ * console.log(tree.getRank(30)); // 2;
4460
+ */
4461
+ // ─── Order-Statistic Methods ───────────────────────────
4462
+
4463
+ getByRank(k: number): [K, V[]] | undefined {
4464
+ const key = this.#core.getByRank(k);
4465
+ if (key === undefined) return undefined;
4466
+ return [key, this.#core.get(key) ?? []];
4467
+ }
4468
+
4469
+ /**
4470
+ * Get the rank of a key in sorted order
4471
+ * @example
4472
+ * // Get the rank of a key in sorted order
4473
+ * const tree = new TreeMultiMap<number>(
4474
+ * [10, 20, 30, 40, 50],
4475
+ * { enableOrderStatistic: true }
4476
+ * );
4477
+ * console.log(tree.getRank(10)); // 0; // smallest → rank 0
4478
+ * console.log(tree.getRank(30)); // 2; // 2 elements before 30 in tree order
4479
+ * console.log(tree.getRank(50)); // 4; // largest → rank 4
4480
+ * console.log(tree.getRank(25)); // 2;
4481
+ */
4482
+ getRank(key: K): number {
4483
+ return this.#core.getRank(key);
4484
+ }
4485
+
4486
+ /**
4487
+ * Get elements by rank range
4488
+
4489
+ * @example
4490
+ * // Pagination with rangeByRank
4491
+ * const tree = new TreeMultiMap<number>(
4492
+ * [10, 20, 30, 40, 50, 60, 70, 80, 90],
4493
+ * { enableOrderStatistic: true }
4494
+ * );
4495
+ * const pageSize = 3;
4496
+ *
4497
+ * // Page 1
4498
+ * console.log(tree.rangeByRank(0, pageSize - 1)); // [10, 20, 30];
4499
+ * // Page 2
4500
+ * console.log(tree.rangeByRank(pageSize, 2 * pageSize - 1)); // [40, 50, 60];
4501
+ * // Page 3
4502
+ * console.log(tree.rangeByRank(2 * pageSize, 3 * pageSize - 1)); // [70, 80, 90];
4503
+ */
4504
+ rangeByRank(start: number, end: number): Array<[K, V[]]> {
4505
+ const keys = this.#core.rangeByRank(start, end);
4506
+ return keys
4507
+ .filter((k): k is K => k !== undefined)
4508
+ .map(k => [k, this.#core.get(k) ?? []] as [K, V[]]);
4509
+ }
4510
+
4511
+ /**
4512
+ * Deep copy
4513
+
1573
4514
 
1574
4515
 
1575
4516