max-priority-queue-typed 2.5.0 → 2.5.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 (74) hide show
  1. package/dist/cjs/index.cjs +294 -0
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs-legacy/index.cjs +294 -0
  4. package/dist/cjs-legacy/index.cjs.map +1 -1
  5. package/dist/esm/index.mjs +294 -0
  6. package/dist/esm/index.mjs.map +1 -1
  7. package/dist/esm-legacy/index.mjs +294 -0
  8. package/dist/esm-legacy/index.mjs.map +1 -1
  9. package/dist/types/data-structures/base/index.d.ts +1 -0
  10. package/dist/types/data-structures/base/iterable-entry-base.d.ts +8 -8
  11. package/dist/types/data-structures/base/linear-base.d.ts +3 -3
  12. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +252 -0
  13. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +294 -0
  14. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +527 -2
  15. package/dist/types/data-structures/binary-tree/bst.d.ts +505 -1
  16. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +399 -0
  17. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +126 -1
  18. package/dist/types/data-structures/binary-tree/tree-map.d.ts +2881 -382
  19. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2867 -347
  20. package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +2328 -312
  21. package/dist/types/data-structures/binary-tree/tree-set.d.ts +2671 -277
  22. package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -4
  23. package/dist/types/data-structures/graph/directed-graph.d.ts +210 -0
  24. package/dist/types/data-structures/graph/undirected-graph.d.ts +189 -0
  25. package/dist/types/data-structures/hash/hash-map.d.ts +241 -10
  26. package/dist/types/data-structures/heap/heap.d.ts +294 -0
  27. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +360 -3
  28. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +318 -3
  29. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +380 -2
  30. package/dist/types/data-structures/matrix/matrix.d.ts +168 -0
  31. package/dist/types/data-structures/queue/deque.d.ts +319 -4
  32. package/dist/types/data-structures/queue/queue.d.ts +252 -0
  33. package/dist/types/data-structures/stack/stack.d.ts +210 -0
  34. package/dist/types/data-structures/trie/trie.d.ts +256 -4
  35. package/dist/types/interfaces/graph.d.ts +1 -1
  36. package/dist/types/types/common.d.ts +2 -2
  37. package/dist/types/types/data-structures/heap/heap.d.ts +1 -0
  38. package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +1 -0
  39. package/dist/types/types/utils/validate-type.d.ts +4 -4
  40. package/dist/umd/max-priority-queue-typed.js +294 -0
  41. package/dist/umd/max-priority-queue-typed.js.map +1 -1
  42. package/dist/umd/max-priority-queue-typed.min.js.map +1 -1
  43. package/package.json +2 -2
  44. package/src/data-structures/base/index.ts +1 -0
  45. package/src/data-structures/base/iterable-entry-base.ts +8 -8
  46. package/src/data-structures/base/linear-base.ts +3 -3
  47. package/src/data-structures/binary-tree/avl-tree.ts +252 -0
  48. package/src/data-structures/binary-tree/binary-indexed-tree.ts +295 -1
  49. package/src/data-structures/binary-tree/binary-tree.ts +527 -2
  50. package/src/data-structures/binary-tree/bst.ts +505 -1
  51. package/src/data-structures/binary-tree/red-black-tree.ts +399 -0
  52. package/src/data-structures/binary-tree/segment-tree.ts +127 -2
  53. package/src/data-structures/binary-tree/tree-map.ts +2958 -459
  54. package/src/data-structures/binary-tree/tree-multi-map.ts +3069 -549
  55. package/src/data-structures/binary-tree/tree-multi-set.ts +2476 -460
  56. package/src/data-structures/binary-tree/tree-set.ts +2816 -422
  57. package/src/data-structures/graph/abstract-graph.ts +4 -4
  58. package/src/data-structures/graph/directed-graph.ts +210 -0
  59. package/src/data-structures/graph/undirected-graph.ts +189 -0
  60. package/src/data-structures/hash/hash-map.ts +246 -15
  61. package/src/data-structures/heap/heap.ts +294 -0
  62. package/src/data-structures/linked-list/doubly-linked-list.ts +360 -3
  63. package/src/data-structures/linked-list/singly-linked-list.ts +318 -3
  64. package/src/data-structures/linked-list/skip-linked-list.ts +380 -2
  65. package/src/data-structures/matrix/matrix.ts +169 -1
  66. package/src/data-structures/queue/deque.ts +320 -5
  67. package/src/data-structures/queue/queue.ts +252 -0
  68. package/src/data-structures/stack/stack.ts +210 -0
  69. package/src/data-structures/trie/trie.ts +257 -5
  70. package/src/interfaces/graph.ts +1 -1
  71. package/src/types/common.ts +2 -2
  72. package/src/types/data-structures/heap/heap.ts +1 -0
  73. package/src/types/data-structures/priority-queue/priority-queue.ts +1 -0
  74. package/src/types/utils/validate-type.ts +4 -4
@@ -151,17 +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
154
 
166
155
 
167
156
 
@@ -200,56 +189,21 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
200
189
 
201
190
 
202
191
 
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
192
 
218
193
 
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
194
 
235
195
 
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)
196
+
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
253
207
 
254
208
 
255
209
 
@@ -303,20 +257,25 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
303
257
 
304
258
 
305
259
  * @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;
260
+ * // Check if empty
261
+ * console.log(new TreeMultiMap().isEmpty()); // true;
311
262
  */
312
- has(key: K): boolean {
313
- this._validateKey(key);
314
- return this.#core.has(key);
263
+ isEmpty(): boolean {
264
+ return this.size === 0;
315
265
  }
316
266
 
317
267
  /**
318
- * Live bucket reference (do not auto-delete key if bucket becomes empty via mutation).
319
- * @remarks Time O(log n), Space O(1)
268
+ * Removes all entries from the map.
269
+ * @remarks Time O(1), Space O(1)
270
+
271
+
272
+
273
+
274
+
275
+
276
+
277
+
278
+
320
279
 
321
280
 
322
281
 
@@ -369,21 +328,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
369
328
 
370
329
 
371
330
 
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
331
 
388
332
 
389
333
 
@@ -416,27 +360,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
416
360
 
417
361
 
418
362
 
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
363
 
441
364
 
442
365
 
@@ -488,39 +411,18 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
488
411
 
489
412
 
490
413
  * @example
491
- * // Set values for key
414
+ * // Remove all entries
492
415
  * const mm = new TreeMultiMap<number, string>();
493
- * mm.set(1, 'a');
494
- * mm.set(1, 'b');
495
- * console.log(mm.get(1)); // ['a', 'b'];
416
+ * mm.add(1, 'a');
417
+ * mm.clear();
418
+ * console.log(mm.isEmpty()); // true;
496
419
  */
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[]);
420
+ clear(): void {
421
+ this.#core.clear();
520
422
  }
521
423
 
522
424
  /**
523
- * Deletes a key and its entire bucket.
425
+ * Bucket length for a key (missing => 0).
524
426
  * @remarks Time O(log n), Space O(1)
525
427
 
526
428
 
@@ -545,12 +447,21 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
545
447
 
546
448
 
547
449
 
548
-
549
-
550
-
551
-
552
-
553
-
450
+ * @example
451
+ * // Count values for key
452
+ * const mm = new TreeMultiMap<number, string>();
453
+ * mm.add(1, 'a');
454
+ * mm.add(1, 'b');
455
+ * console.log(mm.count(1)); // 2;
456
+ */
457
+ count(key: K): number {
458
+ const b = this.get(key);
459
+ return Array.isArray(b) ? b.length : 0;
460
+ }
461
+
462
+ /**
463
+ * Total number of values across all buckets (Σ bucket.length).
464
+ * @remarks Time O(n), Space O(1)
554
465
 
555
466
 
556
467
 
@@ -575,103 +486,2920 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
575
486
 
576
487
 
577
488
  * @example
578
- * // Remove key
489
+ * // Total number of values
579
490
  * const mm = new TreeMultiMap<number, string>();
580
491
  * mm.add(1, 'a');
581
- * mm.add(2, 'b');
582
- * mm.delete(1);
583
- * console.log(mm.has(1)); // false;
492
+ * mm.add(1, 'b');
493
+ * mm.add(2, 'c');
494
+ * console.log(mm.totalSize); // 3;
584
495
  */
585
- delete(key: K): boolean {
586
- this._validateKey(key);
587
- return this.#core.delete(key).length > 0;
496
+ get totalSize(): number {
497
+ let sum = 0;
498
+ for (const [, bucket] of this) sum += bucket.length;
499
+ return sum;
588
500
  }
589
501
 
590
502
  /**
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
503
+ * Whether the map contains the given key.
504
+ * @remarks Time O(log n), Space O(1)
593
505
 
594
506
 
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
507
 
612
508
 
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
509
 
635
510
 
636
- * @example
637
- * // Delete all matching values
638
- * const mm = new TreeMultiMap<number, string>();
639
- * 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)) {
511
+
512
+
513
+
514
+
515
+
516
+
517
+
518
+
519
+
520
+
521
+
522
+
523
+
524
+
525
+
526
+
527
+
528
+
529
+
530
+
531
+
532
+
533
+
534
+
535
+
536
+
537
+
538
+
539
+
540
+
541
+
542
+
543
+
544
+
545
+
546
+
547
+
548
+
549
+
550
+
551
+
552
+
553
+
554
+
555
+
556
+
557
+
558
+
559
+
560
+
561
+
562
+
563
+
564
+
565
+
566
+
567
+
568
+
569
+
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+
598
+
599
+
600
+
601
+
602
+
603
+
604
+
605
+
606
+
607
+
608
+
609
+
610
+
611
+
612
+
613
+
614
+
615
+
616
+
617
+
618
+
619
+
620
+
621
+
622
+
623
+
624
+
625
+
626
+
627
+
628
+
629
+
630
+
631
+
632
+
633
+
634
+
635
+
636
+
637
+
638
+
639
+
640
+
641
+
642
+
643
+
644
+
645
+
646
+
647
+
648
+
649
+
650
+
651
+
652
+
653
+
654
+
655
+
656
+
657
+
658
+
659
+
660
+
661
+
662
+
663
+
664
+
665
+
666
+
667
+
668
+
669
+
670
+
671
+
672
+
673
+
674
+
675
+
676
+
677
+
678
+
679
+
680
+
681
+
682
+
683
+ * @example
684
+ * // Check key existence
685
+ * const mm = new TreeMultiMap<number, string>();
686
+ * mm.add(1, 'a');
687
+ * console.log(mm.has(1)); // true;
688
+ * console.log(mm.has(2)); // false;
689
+ */
690
+ has(key: K): boolean {
691
+ this._validateKey(key);
692
+ return this.#core.has(key);
693
+ }
694
+
695
+ /**
696
+ * Live bucket reference (do not auto-delete key if bucket becomes empty via mutation).
697
+ * @remarks Time O(log n), Space O(1)
698
+
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+
707
+
708
+
709
+
710
+
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
+
751
+
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
+ * @example
877
+ * // Get values for key
878
+ * const mm = new TreeMultiMap<number, string>();
879
+ * mm.add(1, 'a');
880
+ * mm.add(1, 'b');
881
+ * console.log(mm.get(1)); // ['a', 'b'];
882
+ */
883
+ get(key: K): V[] | undefined {
884
+ this._validateKey(key);
885
+ return this.#core.get(key);
886
+ }
887
+
888
+ /**
889
+ * Append a single value.
890
+ * @remarks Time O(log n), Space O(1)
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
+
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
+
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
+ * @example
1029
+ * // Add key-value pair
1030
+ * const mm = new TreeMultiMap<number, string>();
1031
+ * mm.add(1, 'a');
1032
+ * mm.add(1, 'b');
1033
+ * mm.add(2, 'c');
1034
+ * console.log(mm.get(1)); // ['a', 'b'];
1035
+ */
1036
+ add(key: K, value: V): boolean {
1037
+ this._validateKey(key);
1038
+ const bucket = this.#core.get(key);
1039
+ if (bucket) {
1040
+ bucket.push(value);
1041
+ return true;
1042
+ }
1043
+ return this.#core.set(key, [value]);
1044
+ }
1045
+
1046
+ /**
1047
+ * Alias for compatibility with existing TreeMultiMap semantics.
1048
+ * @remarks Time O(log n), Space O(1) for single value; O(log n + m) for bucket append
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
+
1116
+
1117
+
1118
+
1119
+
1120
+
1121
+
1122
+
1123
+
1124
+
1125
+
1126
+
1127
+
1128
+
1129
+
1130
+
1131
+
1132
+
1133
+
1134
+
1135
+
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
+ * @example
1226
+ * // Set values for key
1227
+ * const mm = new TreeMultiMap<number, string>();
1228
+ * mm.set(1, 'a');
1229
+ * mm.set(1, 'b');
1230
+ * console.log(mm.get(1)); // ['a', 'b'];
1231
+ */
1232
+ set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean;
1233
+ set(key: K, value: V): boolean;
1234
+ set(entry: [K | null | undefined, V[] | undefined] | K | null | undefined, value?: V): boolean {
1235
+ if (entry === null || entry === undefined) return false;
1236
+ if (Array.isArray(entry)) {
1237
+ const [k, bucket] = entry;
1238
+ if (k === null || k === undefined) return false;
1239
+ if (value !== undefined) return this.add(k as K, value);
1240
+ if (bucket === undefined) {
1241
+ // ensure key exists
1242
+ return this.#core.set(k as K, [] as V[]);
1243
+ }
1244
+ // append bucket
1245
+ const existing = this.#core.get(k as K);
1246
+ if (existing) {
1247
+ existing.push(...bucket);
1248
+ return true;
1249
+ }
1250
+ return this.#core.set(k as K, [...bucket] as V[]);
1251
+ }
1252
+ // key-only or key+value
1253
+ if (value !== undefined) return this.add(entry as K, value);
1254
+ return this.#core.set(entry as K, [] as V[]);
1255
+ }
1256
+
1257
+ /**
1258
+ * Deletes a key and its entire bucket.
1259
+ * @remarks Time O(log n), Space O(1)
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
+
1331
+
1332
+
1333
+
1334
+
1335
+
1336
+
1337
+
1338
+
1339
+
1340
+
1341
+
1342
+
1343
+
1344
+
1345
+
1346
+
1347
+
1348
+
1349
+
1350
+
1351
+
1352
+
1353
+
1354
+
1355
+
1356
+
1357
+
1358
+
1359
+
1360
+
1361
+
1362
+
1363
+
1364
+
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
+ * @example
1439
+ * // Remove key
1440
+ * const mm = new TreeMultiMap<number, string>();
1441
+ * mm.add(1, 'a');
1442
+ * mm.add(2, 'b');
1443
+ * mm.delete(1);
1444
+ * console.log(mm.has(1)); // false;
1445
+ */
1446
+ delete(key: K): boolean {
1447
+ this._validateKey(key);
1448
+ return this.#core.delete(key).length > 0;
1449
+ }
1450
+
1451
+ /**
1452
+ * Check if a specific value exists in a key's bucket.
1453
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1454
+
1455
+
1456
+
1457
+
1458
+
1459
+
1460
+
1461
+
1462
+
1463
+
1464
+
1465
+
1466
+
1467
+
1468
+
1469
+
1470
+
1471
+
1472
+
1473
+
1474
+
1475
+
1476
+
1477
+ * @example
1478
+ * // Check specific key-value
1479
+ * const mm = new TreeMultiMap<number, string>();
1480
+ * mm.add(1, 'a');
1481
+ * console.log(mm.hasEntry(1, 'a')); // true;
1482
+ * console.log(mm.hasEntry(1, 'z')); // false;
1483
+ */
1484
+ hasEntry(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
1485
+ const bucket = this.get(key);
1486
+ if (!Array.isArray(bucket)) return false;
1487
+ return bucket.some(v => eq(v, value));
1488
+ }
1489
+
1490
+ /**
1491
+ * Delete a single occurrence of a value from a key's bucket.
1492
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1493
+
1494
+
1495
+
1496
+
1497
+
1498
+
1499
+
1500
+
1501
+
1502
+
1503
+
1504
+
1505
+
1506
+
1507
+
1508
+
1509
+
1510
+
1511
+
1512
+
1513
+
1514
+
1515
+
1516
+ * @example
1517
+ * // Delete specific value
1518
+ * const mm = new TreeMultiMap<number, string>();
1519
+ * mm.add(1, 'a');
1520
+ * mm.add(1, 'b');
1521
+ * mm.deleteValue(1, 'a');
1522
+ * console.log(mm.get(1)); // ['b'];
1523
+ */
1524
+ deleteValue(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): boolean {
1525
+ const bucket = this.get(key);
1526
+ if (!Array.isArray(bucket)) return false;
1527
+ const idx = bucket.findIndex(v => eq(v, value));
1528
+ if (idx === -1) return false;
1529
+ bucket.splice(idx, 1);
1530
+ if (bucket.length === 0) this.delete(key);
1531
+ return true;
1532
+ }
1533
+
1534
+ /**
1535
+ * Delete all occurrences of a value from a key's bucket.
1536
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1537
+
1538
+
1539
+
1540
+
1541
+
1542
+
1543
+
1544
+
1545
+
1546
+
1547
+
1548
+
1549
+
1550
+
1551
+
1552
+
1553
+
1554
+
1555
+
1556
+
1557
+
1558
+
1559
+
1560
+ * @example
1561
+ * // Delete all matching values
1562
+ * const mm = new TreeMultiMap<number, string>();
1563
+ * mm.add(1, 'a');
1564
+ * mm.add(1, 'a');
1565
+ * mm.add(1, 'b');
1566
+ * const count = mm.deleteValues(1, 'a');
1567
+ * console.log(count); // 2;
1568
+ */
1569
+ deleteValues(key: K, value: V, eq: (a: V, b: V) => boolean = Object.is): number {
1570
+ const bucket = this.get(key);
1571
+ if (!Array.isArray(bucket) || bucket.length === 0) return 0;
1572
+ let removed = 0;
1573
+ for (let i = bucket.length - 1; i >= 0; i--) {
1574
+ if (eq(bucket[i] as V, value)) {
651
1575
  bucket.splice(i, 1);
652
1576
  removed++;
653
1577
  }
654
1578
  }
655
- if (bucket.length === 0 && removed > 0) this.delete(key);
656
- return removed;
1579
+ if (bucket.length === 0 && removed > 0) this.delete(key);
1580
+ return removed;
1581
+ }
1582
+
1583
+ // ---- iteration (bucket view) ----
1584
+
1585
+ /**
1586
+ * Iterates over all entries as [key, bucket] pairs.
1587
+ * @remarks Time O(n), Space O(1)
1588
+ */
1589
+ *[Symbol.iterator](): Iterator<[K, V[]]> {
1590
+ for (const [k, v] of this.#core) {
1591
+ // core always stores buckets, but guard anyway
1592
+ yield [k, v ?? /* istanbul ignore next */ ([] as V[])];
1593
+ }
1594
+ }
1595
+
1596
+ /**
1597
+ * Iterates over all keys.
1598
+ * @remarks Time O(n), Space O(1)
1599
+
1600
+
1601
+
1602
+
1603
+
1604
+
1605
+
1606
+
1607
+
1608
+
1609
+
1610
+
1611
+
1612
+
1613
+
1614
+
1615
+
1616
+
1617
+
1618
+
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
+
1646
+
1647
+
1648
+
1649
+
1650
+
1651
+
1652
+
1653
+
1654
+
1655
+
1656
+
1657
+
1658
+
1659
+
1660
+
1661
+
1662
+
1663
+
1664
+
1665
+
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
+
1693
+
1694
+
1695
+
1696
+
1697
+
1698
+
1699
+
1700
+
1701
+
1702
+
1703
+
1704
+
1705
+
1706
+
1707
+
1708
+
1709
+
1710
+
1711
+
1712
+
1713
+
1714
+
1715
+
1716
+
1717
+
1718
+
1719
+
1720
+
1721
+
1722
+
1723
+
1724
+
1725
+
1726
+
1727
+
1728
+
1729
+
1730
+
1731
+
1732
+
1733
+
1734
+
1735
+
1736
+
1737
+
1738
+
1739
+
1740
+
1741
+
1742
+ * @example
1743
+ * // Iterate keys
1744
+ * const mm = new TreeMultiMap<number, string>();
1745
+ * mm.add(3, 'c');
1746
+ * mm.add(1, 'a');
1747
+ * console.log([...mm.keys()]); // [1, 3];
1748
+ */
1749
+ *keys(): IterableIterator<K> {
1750
+ yield* this.#core.keys();
1751
+ }
1752
+
1753
+ /**
1754
+ * Iterates over all buckets.
1755
+ * @remarks Time O(n), Space O(1)
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
+
1890
+
1891
+
1892
+
1893
+
1894
+
1895
+
1896
+
1897
+
1898
+
1899
+ * @example
1900
+ * // Iterate value arrays
1901
+ * const mm = new TreeMultiMap<number, string>();
1902
+ * mm.add(1, 'a');
1903
+ * mm.add(1, 'b');
1904
+ * console.log([...mm.values()]); // [['a', 'b']];
1905
+ */
1906
+ *values(): IterableIterator<V[]> {
1907
+ for (const [, bucket] of this) yield bucket;
1908
+ }
1909
+
1910
+ // ---- entry-flat views ----
1911
+
1912
+ /**
1913
+ * Iterates over all entries for a specific key.
1914
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1915
+
1916
+
1917
+
1918
+
1919
+
1920
+
1921
+
1922
+
1923
+
1924
+
1925
+
1926
+
1927
+
1928
+
1929
+
1930
+
1931
+
1932
+
1933
+
1934
+
1935
+
1936
+
1937
+
1938
+ * @example
1939
+ * // Get entries for key
1940
+ * const mm = new TreeMultiMap<number, string>();
1941
+ * mm.add(1, 'a');
1942
+ * mm.add(1, 'b');
1943
+ * console.log([...mm.entriesOf(1)]); // [[1, 'a'], [1, 'b']];
1944
+ */
1945
+ *entriesOf(key: K): IterableIterator<[K, V]> {
1946
+ const bucket = this.get(key);
1947
+ if (!Array.isArray(bucket)) return;
1948
+ for (const v of bucket) yield [key, v];
1949
+ }
1950
+
1951
+ /**
1952
+ * Iterates over all values for a specific key.
1953
+ * @remarks Time O(log n + m), Space O(1) where m is bucket size
1954
+
1955
+
1956
+
1957
+
1958
+
1959
+
1960
+
1961
+
1962
+
1963
+
1964
+
1965
+
1966
+
1967
+
1968
+
1969
+
1970
+
1971
+
1972
+
1973
+
1974
+
1975
+
1976
+
1977
+ * @example
1978
+ * // Get flat values for key
1979
+ * const mm = new TreeMultiMap<number, string>();
1980
+ * mm.add(1, 'a');
1981
+ * mm.add(1, 'b');
1982
+ * console.log([...mm.valuesOf(1)]); // ['a', 'b'];
1983
+ */
1984
+ *valuesOf(key: K): IterableIterator<V> {
1985
+ const bucket = this.get(key);
1986
+ if (!Array.isArray(bucket)) return;
1987
+ yield* bucket;
1988
+ }
1989
+
1990
+ /**
1991
+ * Iterates over all [key, value] pairs (flattened from buckets).
1992
+ * @remarks Time O(T), Space O(1) where T is totalSize
1993
+
1994
+
1995
+
1996
+
1997
+
1998
+
1999
+
2000
+
2001
+
2002
+
2003
+
2004
+
2005
+
2006
+
2007
+
2008
+
2009
+
2010
+
2011
+
2012
+
2013
+
2014
+
2015
+
2016
+ * @example
2017
+ * // All key-value pairs flattened
2018
+ * const mm = new TreeMultiMap<number, string>();
2019
+ * mm.add(1, 'a');
2020
+ * mm.add(1, 'b');
2021
+ * mm.add(2, 'c');
2022
+ * console.log([...mm.flatEntries()]); // [[1, 'a'], [1, 'b'], [2, 'c']];
2023
+ */
2024
+ *flatEntries(): IterableIterator<[K, V]> {
2025
+ for (const [k, bucket] of this) {
2026
+ for (const v of bucket) yield [k, v];
2027
+ }
2028
+ }
2029
+
2030
+ // ━━━ Navigable methods (return [K, V[]] | undefined) ━━━
2031
+
2032
+ /**
2033
+ * Returns the entry with the smallest key.
2034
+ * @remarks Time O(log n), Space O(1)
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
+
2062
+
2063
+
2064
+
2065
+
2066
+
2067
+
2068
+
2069
+
2070
+
2071
+
2072
+
2073
+
2074
+
2075
+
2076
+
2077
+
2078
+
2079
+
2080
+
2081
+
2082
+
2083
+
2084
+
2085
+
2086
+
2087
+
2088
+
2089
+
2090
+
2091
+ * @example
2092
+ * // First entry
2093
+ * const mm = new TreeMultiMap<number, string>();
2094
+ * mm.add(3, 'c');
2095
+ * mm.add(1, 'a');
2096
+ * console.log(mm.first()?.[0]); // 1;
2097
+ */
2098
+ first(): [K, V[]] | undefined {
2099
+ const k = this.#core.getLeftMost();
2100
+ if (k === undefined) return undefined;
2101
+ const b = this.get(k);
2102
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2103
+ }
2104
+
2105
+ /**
2106
+ * Returns the entry with the largest key.
2107
+ * @remarks Time O(log n), Space O(1)
2108
+
2109
+
2110
+
2111
+
2112
+
2113
+
2114
+
2115
+
2116
+
2117
+
2118
+
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
+
2146
+
2147
+
2148
+
2149
+
2150
+
2151
+
2152
+
2153
+
2154
+
2155
+
2156
+
2157
+
2158
+
2159
+
2160
+
2161
+
2162
+
2163
+
2164
+ * @example
2165
+ * // Last entry
2166
+ * const mm = new TreeMultiMap<number, string>();
2167
+ * mm.add(1, 'a');
2168
+ * mm.add(3, 'c');
2169
+ * console.log(mm.last()?.[0]); // 3;
2170
+ */
2171
+ last(): [K, V[]] | undefined {
2172
+ const k = this.#core.getRightMost();
2173
+ if (k === undefined) return undefined;
2174
+ const b = this.get(k);
2175
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2176
+ }
2177
+
2178
+ /**
2179
+ * Removes and returns the entry with the smallest key.
2180
+ * @remarks Time O(log n), Space O(1)
2181
+
2182
+
2183
+
2184
+
2185
+
2186
+
2187
+
2188
+
2189
+
2190
+
2191
+
2192
+
2193
+
2194
+
2195
+
2196
+
2197
+
2198
+
2199
+
2200
+
2201
+
2202
+
2203
+
2204
+
2205
+ * @example
2206
+ * // Remove and return first
2207
+ * const mm = new TreeMultiMap<number, string>();
2208
+ * mm.add(2, 'b');
2209
+ * mm.add(1, 'a');
2210
+ * const first = mm.pollFirst();
2211
+ * console.log(first?.[0]); // 1;
2212
+ * console.log(mm.has(1)); // false;
2213
+ */
2214
+ pollFirst(): [K, V[]] | undefined {
2215
+ const e = this.first();
2216
+ if (!e) return undefined;
2217
+ this.delete(e[0]);
2218
+ return e;
2219
+ }
2220
+
2221
+ /**
2222
+ * Removes and returns the entry with the largest key.
2223
+ * @remarks Time O(log n), Space O(1)
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
+ * @example
2249
+ * // Remove and return last
2250
+ * const mm = new TreeMultiMap<number, string>();
2251
+ * mm.add(1, 'a');
2252
+ * mm.add(3, 'c');
2253
+ * const last = mm.pollLast();
2254
+ * console.log(last?.[0]); // 3;
2255
+ */
2256
+ pollLast(): [K, V[]] | undefined {
2257
+ const e = this.last();
2258
+ if (!e) return undefined;
2259
+ this.delete(e[0]);
2260
+ return e;
2261
+ }
2262
+
2263
+ /**
2264
+ * Returns the entry with the smallest key >= given key.
2265
+ * @remarks Time O(log n), Space O(1)
2266
+
2267
+
2268
+
2269
+
2270
+
2271
+
2272
+
2273
+
2274
+
2275
+
2276
+
2277
+
2278
+
2279
+
2280
+
2281
+
2282
+
2283
+
2284
+
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
+
2348
+
2349
+
2350
+
2351
+
2352
+
2353
+
2354
+
2355
+
2356
+
2357
+
2358
+
2359
+
2360
+
2361
+
2362
+
2363
+
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
+
2392
+
2393
+
2394
+
2395
+
2396
+
2397
+
2398
+
2399
+
2400
+
2401
+
2402
+
2403
+
2404
+
2405
+
2406
+
2407
+
2408
+
2409
+
2410
+
2411
+
2412
+ * @example
2413
+ * // Least key ≥ target
2414
+ * const mm = new TreeMultiMap<number, string>();
2415
+ * mm.add(10, 'a');
2416
+ * mm.add(20, 'b');
2417
+ * mm.add(30, 'c');
2418
+ * console.log(mm.ceiling(15)?.[0]); // 20;
2419
+ */
2420
+ ceiling(key: K): [K, V[]] | undefined {
2421
+ this._validateKey(key);
2422
+ const k = this.#core.ceiling(key);
2423
+ if (k === undefined) return undefined;
2424
+ const b = this.get(k);
2425
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2426
+ }
2427
+
2428
+ /**
2429
+ * Returns the entry with the largest key <= given key.
2430
+ * @remarks Time O(log n), Space O(1)
2431
+
2432
+
2433
+
2434
+
2435
+
2436
+
2437
+
2438
+
2439
+
2440
+
2441
+
2442
+
2443
+
2444
+
2445
+
2446
+
2447
+
2448
+
2449
+
2450
+
2451
+
2452
+
2453
+
2454
+
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
+ * @example
2578
+ * // Greatest key ≤ target
2579
+ * const mm = new TreeMultiMap<number, string>();
2580
+ * mm.add(10, 'a');
2581
+ * mm.add(20, 'b');
2582
+ * mm.add(30, 'c');
2583
+ * console.log(mm.floor(25)?.[0]); // 20;
2584
+ */
2585
+ floor(key: K): [K, V[]] | undefined {
2586
+ this._validateKey(key);
2587
+ const k = this.#core.floor(key);
2588
+ if (k === undefined) return undefined;
2589
+ const b = this.get(k);
2590
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2591
+ }
2592
+
2593
+ /**
2594
+ * Returns the entry with the smallest key > given key.
2595
+ * @remarks Time O(log n), Space O(1)
2596
+
2597
+
2598
+
2599
+
2600
+
2601
+
2602
+
2603
+
2604
+
2605
+
2606
+
2607
+
2608
+
2609
+
2610
+
2611
+
2612
+
2613
+
2614
+
2615
+
2616
+
2617
+
2618
+
2619
+
2620
+
2621
+
2622
+
2623
+
2624
+
2625
+
2626
+
2627
+
2628
+
2629
+
2630
+
2631
+
2632
+
2633
+
2634
+
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
+ * @example
2711
+ * // Least key > target
2712
+ * const mm = new TreeMultiMap<number, string>();
2713
+ * mm.add(10, 'a');
2714
+ * mm.add(20, 'b');
2715
+ * console.log(mm.higher(10)?.[0]); // 20;
2716
+ */
2717
+ higher(key: K): [K, V[]] | undefined {
2718
+ this._validateKey(key);
2719
+ const k = this.#core.higher(key);
2720
+ if (k === undefined) return undefined;
2721
+ const b = this.get(k);
2722
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2723
+ }
2724
+
2725
+ /**
2726
+ * Returns the entry with the largest key < given key.
2727
+ * @remarks Time O(log n), Space O(1)
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
+
2797
+
2798
+
2799
+
2800
+
2801
+
2802
+
2803
+
2804
+
2805
+
2806
+
2807
+
2808
+
2809
+
2810
+
2811
+
2812
+
2813
+
2814
+
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
+ * @example
2843
+ * // Greatest key < target
2844
+ * const mm = new TreeMultiMap<number, string>();
2845
+ * mm.add(10, 'a');
2846
+ * mm.add(20, 'b');
2847
+ * console.log(mm.lower(20)?.[0]); // 10;
2848
+ */
2849
+ lower(key: K): [K, V[]] | undefined {
2850
+ this._validateKey(key);
2851
+ const k = this.#core.lower(key);
2852
+ if (k === undefined) return undefined;
2853
+ const b = this.get(k);
2854
+ return b === undefined ? /* istanbul ignore next -- defensive: key in core always has bucket */ undefined : [k, b];
2855
+ }
2856
+
2857
+ // ━━━ Tree utilities ━━━
2858
+
2859
+ /**
2860
+ * Prints the internal tree structure (for debugging).
2861
+ * @remarks Time O(n), Space O(n)
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
+
2942
+
2943
+
2944
+
2945
+
2946
+
2947
+
2948
+
2949
+
2950
+
2951
+
2952
+
2953
+
2954
+
2955
+
2956
+
2957
+
2958
+
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
+ * @example
3006
+ * // Display tree
3007
+ * const mm = new TreeMultiMap<number, string>();
3008
+ * mm.add(1, 'a');
3009
+ * expect(() => mm.print()).not.toThrow();
3010
+ */
3011
+ print(): void {
3012
+ this.#core.print();
3013
+ }
3014
+
3015
+ /**
3016
+ * Executes a callback for each entry.
3017
+ * @remarks Time O(n), Space O(1)
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
+
3086
+
3087
+
3088
+
3089
+
3090
+
3091
+
3092
+
3093
+
3094
+
3095
+
3096
+
3097
+
3098
+
3099
+
3100
+
3101
+
3102
+
3103
+
3104
+
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
+ * @example
3162
+ * // Iterate entries
3163
+ * const mm = new TreeMultiMap<number, string>();
3164
+ * mm.add(1, 'a');
3165
+ * mm.add(2, 'b');
3166
+ * const keys: number[] = [];
3167
+ * mm.forEach((v, k) => keys.push(k));
3168
+ * console.log(keys); // [1, 2];
3169
+ */
3170
+ forEach(callback: (value: V[], key: K, map: this) => void): void {
3171
+ for (const [k, v] of this) {
3172
+ callback(v, k, this);
3173
+ }
657
3174
  }
658
3175
 
659
- // ---- iteration (bucket view) ----
660
-
661
3176
  /**
662
- * Iterates over all entries as [key, bucket] pairs.
663
- * @remarks Time O(n), Space O(1)
3177
+ * Creates a new map with entries that pass the predicate.
3178
+ * @remarks Time O(n), Space O(n)
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
+
3264
+
3265
+
3266
+
3267
+
3268
+
3269
+
3270
+
3271
+
3272
+
3273
+
3274
+
3275
+
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
+ * @example
3323
+ * // Filter entries
3324
+ * const mm = new TreeMultiMap<number, string>();
3325
+ * mm.add(1, 'a');
3326
+ * mm.add(2, 'b');
3327
+ * mm.add(3, 'c');
3328
+ * const filtered = mm.filter((v, k) => k > 1);
3329
+ * console.log([...filtered.keys()]); // [2, 3];
664
3330
  */
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[])];
3331
+ filter(predicate: (value: V[], key: K, map: this) => boolean): TreeMultiMap<K, V, R> {
3332
+ const filtered: [K, V[]][] = [];
3333
+ for (const [k, v] of this) {
3334
+ if (predicate(v, k, this)) filtered.push([k, v]);
669
3335
  }
3336
+ return new TreeMultiMap<K, V, R>(filtered, { comparator: this.comparator });
670
3337
  }
671
3338
 
672
3339
  /**
673
- * Iterates over all keys.
674
- * @remarks Time O(n), Space O(1)
3340
+ * Creates a new map by transforming each entry.
3341
+ * @remarks Time O(n log n), Space O(n)
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
+
675
3403
 
676
3404
 
677
3405
 
@@ -710,20 +3438,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
710
3438
 
711
3439
 
712
3440
 
713
- * @example
714
- * // Iterate keys
715
- * const mm = new TreeMultiMap<number, string>();
716
- * mm.add(3, 'c');
717
- * mm.add(1, 'a');
718
- * console.log([...mm.keys()]); // [1, 3];
719
- */
720
- *keys(): IterableIterator<K> {
721
- yield* this.#core.keys();
722
- }
723
-
724
- /**
725
- * Iterates over all buckets.
726
- * @remarks Time O(n), Space O(1)
727
3441
 
728
3442
 
729
3443
 
@@ -762,80 +3476,105 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
762
3476
 
763
3477
 
764
3478
 
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
3479
 
782
3480
 
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
3481
 
800
3482
 
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
3483
 
818
3484
 
819
3485
  * @example
820
- * // All key-value pairs flattened
3486
+ * // Transform values
821
3487
  * const mm = new TreeMultiMap<number, string>();
822
3488
  * 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']];
3489
+ * const mapped = mm.map((v, k) => [k, v.map(s => s.toUpperCase())] as [number, string[]]);
3490
+ * console.log(mapped.get(1)); // ['A'];
826
3491
  */
827
- *flatEntries(): IterableIterator<[K, V]> {
828
- for (const [k, bucket] of this) {
829
- for (const v of bucket) yield [k, v];
3492
+ map<V2>(
3493
+ mapper: (value: V[], key: K, map: this) => [K, V2[]]
3494
+ ): TreeMultiMap<K, V2, R> {
3495
+ const mapped: [K, V2[]][] = [];
3496
+ for (const [k, v] of this) {
3497
+ mapped.push(mapper(v, k, this));
830
3498
  }
3499
+ return new TreeMultiMap<K, V2, R>(mapped, { comparator: this.comparator });
831
3500
  }
832
3501
 
833
- // ━━━ Navigable methods (return [K, V[]] | undefined) ━━━
834
-
835
3502
  /**
836
- * Returns the entry with the smallest key.
837
- * @remarks Time O(log n), Space O(1)
838
-
3503
+ * Reduces all entries to a single value.
3504
+ * @remarks Time O(n), Space O(1)
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
+
839
3578
 
840
3579
 
841
3580
 
@@ -849,24 +3588,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
849
3588
 
850
3589
 
851
3590
 
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
3591
 
871
3592
 
872
3593
 
@@ -880,67 +3601,10 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
880
3601
 
881
3602
 
882
3603
 
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
3604
 
902
3605
 
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
3606
 
924
3607
 
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
3608
 
945
3609
 
946
3610
 
@@ -982,26 +3646,24 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
982
3646
 
983
3647
 
984
3648
  * @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;
3649
+ * // Aggregate
3650
+ * const mm = new TreeMultiMap<number, number>();
3651
+ * mm.add(1, 10);
3652
+ * mm.add(2, 20);
3653
+ * const sum = mm.reduce((acc, v) => acc + v.reduce((a, b) => a + b, 0), 0);
3654
+ * console.log(sum); // 30;
991
3655
  */
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];
3656
+ reduce<U>(callback: (accumulator: U, value: V[], key: K, map: this) => U, initialValue: U): U {
3657
+ let acc = initialValue;
3658
+ for (const [k, v] of this) {
3659
+ acc = callback(acc, v, k, this);
3660
+ }
3661
+ return acc;
998
3662
  }
999
3663
 
1000
3664
  /**
1001
- * Returns the entry with the largest key <= given key.
1002
- * @remarks Time O(log n), Space O(1)
1003
-
1004
-
3665
+ * Sets multiple entries at once.
3666
+ * @remarks Time O(m log n), Space O(m) where m is input size
1005
3667
 
1006
3668
 
1007
3669
 
@@ -1041,26 +3703,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1041
3703
 
1042
3704
 
1043
3705
 
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
3706
 
1065
3707
 
1066
3708
 
@@ -1090,25 +3732,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1090
3732
 
1091
3733
 
1092
3734
 
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
-
1112
3735
 
1113
3736
 
1114
3737
 
@@ -1138,26 +3761,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1138
3761
 
1139
3762
 
1140
3763
 
1141
- * @example
1142
- * // Greatest key < target
1143
- * const mm = new TreeMultiMap<number, string>();
1144
- * mm.add(10, 'a');
1145
- * mm.add(20, 'b');
1146
- * console.log(mm.lower(20)?.[0]); // 10;
1147
- */
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];
1154
- }
1155
-
1156
- // ━━━ Tree utilities ━━━
1157
-
1158
- /**
1159
- * Prints the internal tree structure (for debugging).
1160
- * @remarks Time O(n), Space O(n)
1161
3764
 
1162
3765
 
1163
3766
 
@@ -1197,18 +3800,23 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1197
3800
 
1198
3801
 
1199
3802
  * @example
1200
- * // Display tree
3803
+ * // Set multiple entries
1201
3804
  * const mm = new TreeMultiMap<number, string>();
1202
- * mm.add(1, 'a');
1203
- * expect(() => mm.print()).not.toThrow();
3805
+ * mm.setMany([[1, ['a']], [2, ['b']]]);
3806
+ * console.log(mm.size); // 2;
1204
3807
  */
1205
- print(): void {
1206
- this.#core.print();
3808
+ setMany(keysNodesEntriesOrRaws: Iterable<K | [K | null | undefined, V[] | undefined]>): boolean[] {
3809
+ const results: boolean[] = [];
3810
+ for (const x of keysNodesEntriesOrRaws) {
3811
+ // Call implementation directly: entry can be K or [K, V[]] or [K, undefined]
3812
+ results.push(this.set(x));
3813
+ }
3814
+ return results;
1207
3815
  }
1208
3816
 
1209
3817
  /**
1210
- * Executes a callback for each entry.
1211
- * @remarks Time O(n), Space O(1)
3818
+ * Searches for entries within a key range.
3819
+ * @remarks Time O(log n + k), Space O(k) where k is result size
1212
3820
 
1213
3821
 
1214
3822
 
@@ -1247,24 +3855,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1247
3855
 
1248
3856
 
1249
3857
 
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
3858
 
1269
3859
 
1270
3860
 
@@ -1303,26 +3893,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1303
3893
 
1304
3894
 
1305
3895
 
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
3896
 
1327
3897
 
1328
3898
 
@@ -1362,25 +3932,31 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1362
3932
 
1363
3933
 
1364
3934
  * @example
1365
- * // Transform values
3935
+ * // Find keys in range
1366
3936
  * 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'];
3937
+ * mm.add(10, 'a');
3938
+ * mm.add(20, 'b');
3939
+ * mm.add(30, 'c');
3940
+ * const result = mm.rangeSearch([15, 25]);
3941
+ * console.log(result.length); // 1;
1370
3942
  */
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 });
3943
+ rangeSearch<C extends (node: RedBlackTreeNode<K, V[]>) => unknown>(
3944
+ range: Range<K> | [K, K],
3945
+ callback?: C
3946
+ ): ReturnType<C>[] {
3947
+ return this.#core.rangeSearch(range, callback as (node: RedBlackTreeNode<K, V[]>) => ReturnType<C>);
1379
3948
  }
1380
3949
 
1381
3950
  /**
1382
- * Reduces all entries to a single value.
1383
- * @remarks Time O(n), Space O(1)
3951
+ * Creates a shallow clone of this map.
3952
+ * @remarks Time O(n log n), Space O(n)
3953
+
3954
+
3955
+
3956
+
3957
+
3958
+
3959
+
1384
3960
 
1385
3961
 
1386
3962
 
@@ -1419,25 +3995,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1419
3995
 
1420
3996
 
1421
3997
 
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
3998
 
1442
3999
 
1443
4000
 
@@ -1468,24 +4025,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1468
4025
 
1469
4026
 
1470
4027
 
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
4028
 
1490
4029
 
1491
4030
 
@@ -1516,25 +4055,6 @@ export class TreeMultiMap<K = any, V = any, R = any> implements Iterable<[K, V[]
1516
4055
 
1517
4056
 
1518
4057
 
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
4058
 
1539
4059
 
1540
4060