max-priority-queue-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.
- package/dist/cjs/index.cjs +398 -55
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +397 -54
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +398 -56
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +397 -55
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/common/error.d.ts +9 -0
- package/dist/types/common/index.d.ts +1 -1
- package/dist/types/data-structures/base/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-entry-base.d.ts +8 -8
- package/dist/types/data-structures/base/linear-base.d.ts +3 -3
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +288 -0
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +336 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +618 -18
- package/dist/types/data-structures/binary-tree/bst.d.ts +676 -1
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +456 -0
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +144 -1
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +3307 -399
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +3285 -360
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +2674 -325
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +3072 -287
- package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -4
- package/dist/types/data-structures/graph/directed-graph.d.ts +240 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +216 -0
- package/dist/types/data-structures/hash/hash-map.d.ts +274 -10
- package/dist/types/data-structures/heap/heap.d.ts +336 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +411 -3
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +363 -3
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +434 -2
- package/dist/types/data-structures/matrix/matrix.d.ts +192 -0
- package/dist/types/data-structures/queue/deque.d.ts +364 -4
- package/dist/types/data-structures/queue/queue.d.ts +288 -0
- package/dist/types/data-structures/stack/stack.d.ts +240 -0
- package/dist/types/data-structures/trie/trie.d.ts +292 -4
- package/dist/types/interfaces/graph.d.ts +1 -1
- package/dist/types/types/common.d.ts +2 -2
- package/dist/types/types/data-structures/binary-tree/bst.d.ts +1 -0
- package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +5 -0
- package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +4 -0
- package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +4 -0
- package/dist/types/types/data-structures/heap/heap.d.ts +1 -0
- package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +1 -0
- package/dist/types/types/utils/validate-type.d.ts +4 -4
- package/dist/umd/max-priority-queue-typed.js +395 -53
- package/dist/umd/max-priority-queue-typed.js.map +1 -1
- package/dist/umd/max-priority-queue-typed.min.js +1 -1
- package/dist/umd/max-priority-queue-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/common/error.ts +19 -1
- package/src/common/index.ts +1 -1
- package/src/data-structures/base/index.ts +1 -0
- package/src/data-structures/base/iterable-element-base.ts +3 -2
- package/src/data-structures/base/iterable-entry-base.ts +8 -8
- package/src/data-structures/base/linear-base.ts +3 -3
- package/src/data-structures/binary-tree/avl-tree.ts +299 -0
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +341 -5
- package/src/data-structures/binary-tree/binary-tree.ts +606 -6
- package/src/data-structures/binary-tree/bst.ts +946 -7
- package/src/data-structures/binary-tree/red-black-tree.ts +472 -0
- package/src/data-structures/binary-tree/segment-tree.ts +145 -2
- package/src/data-structures/binary-tree/tree-map.ts +3423 -499
- package/src/data-structures/binary-tree/tree-multi-map.ts +3537 -596
- package/src/data-structures/binary-tree/tree-multi-set.ts +2855 -495
- package/src/data-structures/binary-tree/tree-set.ts +3209 -413
- package/src/data-structures/graph/abstract-graph.ts +6 -6
- package/src/data-structures/graph/directed-graph.ts +240 -0
- package/src/data-structures/graph/undirected-graph.ts +216 -0
- package/src/data-structures/hash/hash-map.ts +281 -19
- package/src/data-structures/heap/heap.ts +340 -4
- package/src/data-structures/heap/max-heap.ts +2 -2
- package/src/data-structures/linked-list/doubly-linked-list.ts +411 -3
- package/src/data-structures/linked-list/singly-linked-list.ts +363 -3
- package/src/data-structures/linked-list/skip-linked-list.ts +439 -7
- package/src/data-structures/matrix/matrix.ts +202 -10
- package/src/data-structures/priority-queue/max-priority-queue.ts +2 -2
- package/src/data-structures/queue/deque.ts +365 -5
- package/src/data-structures/queue/queue.ts +288 -0
- package/src/data-structures/stack/stack.ts +240 -0
- package/src/data-structures/trie/trie.ts +295 -7
- package/src/interfaces/graph.ts +1 -1
- package/src/types/common.ts +2 -2
- package/src/types/data-structures/binary-tree/bst.ts +1 -0
- package/src/types/data-structures/binary-tree/tree-map.ts +6 -0
- package/src/types/data-structures/binary-tree/tree-multi-set.ts +5 -0
- package/src/types/data-structures/binary-tree/tree-set.ts +5 -0
- package/src/types/data-structures/heap/heap.ts +1 -0
- package/src/types/data-structures/priority-queue/priority-queue.ts +1 -0
- 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))
|
|
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()))
|
|
99
|
+
if (Number.isNaN(key.getTime())) raise(TypeError, ERR.invalidDate('TreeMultiMap'));
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
|
-
|
|
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
|
-
* //
|
|
444
|
+
* // Remove all entries
|
|
638
445
|
* const mm = new TreeMultiMap<number, string>();
|
|
639
446
|
* mm.add(1, 'a');
|
|
640
|
-
* mm.
|
|
641
|
-
* mm.
|
|
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
|
-
|
|
666
|
-
|
|
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
|
-
*
|
|
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
|
-
* //
|
|
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
|
-
*
|
|
528
|
+
* mm.add(1, 'b');
|
|
529
|
+
* mm.add(2, 'c');
|
|
530
|
+
* console.log(mm.totalSize); // 3;
|
|
719
531
|
*/
|
|
720
|
-
|
|
721
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
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
|
-
* //
|
|
4136
|
+
* // Set multiple entries
|
|
1143
4137
|
* const mm = new TreeMultiMap<number, string>();
|
|
1144
|
-
* mm.
|
|
1145
|
-
* mm.
|
|
1146
|
-
* console.log(mm.lower(20)?.[0]); // 10;
|
|
4138
|
+
* mm.setMany([[1, ['a']], [2, ['b']]]);
|
|
4139
|
+
* console.log(mm.size); // 2;
|
|
1147
4140
|
*/
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
const
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
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
|
-
*
|
|
1160
|
-
* @remarks Time O(n), Space O(
|
|
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
|
|