binary-tree-typed 2.4.5 → 2.5.0
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/README.md +0 -84
- package/dist/cjs/index.cjs +867 -404
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +864 -401
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +867 -404
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +864 -401
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +429 -78
- package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +212 -32
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
- package/dist/types/data-structures/graph/directed-graph.d.ts +219 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +204 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
- package/dist/types/data-structures/heap/heap.d.ts +287 -99
- package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
- package/dist/types/data-structures/queue/deque.d.ts +272 -65
- package/dist/types/data-structures/queue/queue.d.ts +211 -42
- package/dist/types/data-structures/stack/stack.d.ts +174 -32
- package/dist/types/data-structures/trie/trie.d.ts +213 -43
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/umd/binary-tree-typed.js +860 -397
- package/dist/umd/binary-tree-typed.js.map +1 -1
- package/dist/umd/binary-tree-typed.min.js +2 -2
- package/dist/umd/binary-tree-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +4 -5
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +302 -247
- package/src/data-structures/binary-tree/binary-tree.ts +429 -79
- package/src/data-structures/binary-tree/bst.ts +335 -34
- package/src/data-structures/binary-tree/red-black-tree.ts +290 -97
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1284 -6
- package/src/data-structures/binary-tree/tree-multi-map.ts +1094 -211
- package/src/data-structures/binary-tree/tree-multi-set.ts +858 -65
- package/src/data-structures/binary-tree/tree-set.ts +1136 -9
- package/src/data-structures/graph/directed-graph.ts +219 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +204 -59
- package/src/data-structures/hash/hash-map.ts +230 -77
- package/src/data-structures/heap/heap.ts +287 -99
- package/src/data-structures/heap/max-heap.ts +46 -0
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
- package/src/data-structures/matrix/matrix.ts +416 -12
- package/src/data-structures/priority-queue/max-priority-queue.ts +57 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +272 -65
- package/src/data-structures/queue/queue.ts +211 -42
- package/src/data-structures/stack/stack.ts +174 -32
- package/src/data-structures/trie/trie.ts +213 -43
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
|
@@ -17,6 +17,11 @@ import { ERR } from '../../common';
|
|
|
17
17
|
*
|
|
18
18
|
* - Iteration order is ascending by key.
|
|
19
19
|
* - No node exposure: all APIs use keys/values only.
|
|
20
|
+
* @example
|
|
21
|
+
* // Set multiple key-value pairs
|
|
22
|
+
* const tm = new TreeMap<number, string>();
|
|
23
|
+
* tm.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
24
|
+
* console.log(tm.size); // 3;
|
|
20
25
|
*/
|
|
21
26
|
export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | undefined]> {
|
|
22
27
|
readonly #core: RedBlackTree<K, V>;
|
|
@@ -82,6 +87,7 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
82
87
|
static createDefaultComparator<K>(): Comparator<K> {
|
|
83
88
|
return (a: K, b: K): number => {
|
|
84
89
|
if (typeof a === 'number' && typeof b === 'number') {
|
|
90
|
+
/* istanbul ignore next -- _validateKey prevents NaN from entering the tree */
|
|
85
91
|
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN('TreeMap'));
|
|
86
92
|
const aa = Object.is(a, -0) ? 0 : a;
|
|
87
93
|
const bb = Object.is(b, -0) ? 0 : b;
|
|
@@ -95,6 +101,7 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
95
101
|
if (a instanceof Date && b instanceof Date) {
|
|
96
102
|
const ta = a.getTime();
|
|
97
103
|
const tb = b.getTime();
|
|
104
|
+
/* istanbul ignore next -- _validateKey prevents invalid Date from entering the tree */
|
|
98
105
|
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate('TreeMap'));
|
|
99
106
|
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
100
107
|
}
|
|
@@ -130,6 +137,47 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
130
137
|
|
|
131
138
|
/**
|
|
132
139
|
* Whether the map is empty.
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
* @example
|
|
179
|
+
* // Check empty
|
|
180
|
+
* console.log(new TreeMap().isEmpty()); // true;
|
|
133
181
|
*/
|
|
134
182
|
isEmpty(): boolean {
|
|
135
183
|
return this.size === 0;
|
|
@@ -138,6 +186,73 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
138
186
|
/**
|
|
139
187
|
* Set or overwrite a value for a key.
|
|
140
188
|
* @remarks Expected time O(log n)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
* @example
|
|
237
|
+
* // Sorted dictionary for a contact book
|
|
238
|
+
* const contacts = new TreeMap<string, string>([
|
|
239
|
+
* ['Bob', '555-0102'],
|
|
240
|
+
* ['Alice', '555-0101'],
|
|
241
|
+
* ['Charlie', '555-0103']
|
|
242
|
+
* ]);
|
|
243
|
+
*
|
|
244
|
+
* // Contacts are automatically sorted by name
|
|
245
|
+
* console.log([...contacts.keys()]); // ['Alice', 'Bob', 'Charlie'];
|
|
246
|
+
* console.log(contacts.get('Bob')); // '555-0102';
|
|
247
|
+
*
|
|
248
|
+
* // Find the first contact alphabetically after 'B'
|
|
249
|
+
* console.log(contacts.ceiling('B')); // ['Bob', '555-0102'];
|
|
250
|
+
*
|
|
251
|
+
* // Find contacts in range
|
|
252
|
+
* console.log(contacts.rangeSearch(['Alice', 'Bob'])); // [
|
|
253
|
+
* // ['Alice', '555-0101'],
|
|
254
|
+
* // ['Bob', '555-0102']
|
|
255
|
+
* // ];
|
|
141
256
|
*/
|
|
142
257
|
set(key: K, value: V | undefined): this {
|
|
143
258
|
this._validateKey(key);
|
|
@@ -148,6 +263,66 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
148
263
|
/**
|
|
149
264
|
* Get the value under a key.
|
|
150
265
|
* @remarks Expected time O(log n)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
* @example
|
|
316
|
+
* // Configuration registry with typed lookups
|
|
317
|
+
* const config = new TreeMap<string, number>([
|
|
318
|
+
* ['maxRetries', 3],
|
|
319
|
+
* ['timeout', 5000],
|
|
320
|
+
* ['poolSize', 10]
|
|
321
|
+
* ]);
|
|
322
|
+
*
|
|
323
|
+
* console.log(config.get('timeout')); // 5000;
|
|
324
|
+
* console.log(config.get('missing')); // undefined;
|
|
325
|
+
* console.log(config.size); // 3;
|
|
151
326
|
*/
|
|
152
327
|
get(key: K): V | undefined {
|
|
153
328
|
this._validateKey(key);
|
|
@@ -157,6 +332,65 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
157
332
|
/**
|
|
158
333
|
* Test whether a key exists.
|
|
159
334
|
* @remarks Expected time O(log n)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
* @example
|
|
385
|
+
* // Feature flag checking
|
|
386
|
+
* const flags = new TreeMap<string, boolean>([
|
|
387
|
+
* ['darkMode', true],
|
|
388
|
+
* ['betaFeature', false],
|
|
389
|
+
* ['notifications', true]
|
|
390
|
+
* ]);
|
|
391
|
+
*
|
|
392
|
+
* console.log(flags.has('darkMode')); // true;
|
|
393
|
+
* console.log(flags.has('unknownFlag')); // false;
|
|
160
394
|
*/
|
|
161
395
|
has(key: K): boolean {
|
|
162
396
|
this._validateKey(key);
|
|
@@ -167,6 +401,67 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
167
401
|
* Delete a key.
|
|
168
402
|
* @returns `true` if the key existed; otherwise `false`.
|
|
169
403
|
* @remarks Expected time O(log n)
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
* @example
|
|
454
|
+
* // Session management with expiry
|
|
455
|
+
* const sessions = new TreeMap<string, number>([
|
|
456
|
+
* ['sess_abc', Date.now()],
|
|
457
|
+
* ['sess_def', Date.now()],
|
|
458
|
+
* ['sess_ghi', Date.now()]
|
|
459
|
+
* ]);
|
|
460
|
+
*
|
|
461
|
+
* console.log(sessions.size); // 3;
|
|
462
|
+
* sessions.delete('sess_def');
|
|
463
|
+
* console.log(sessions.has('sess_def')); // false;
|
|
464
|
+
* console.log(sessions.size); // 2;
|
|
170
465
|
*/
|
|
171
466
|
delete(key: K): boolean {
|
|
172
467
|
this._validateKey(key);
|
|
@@ -176,6 +471,49 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
176
471
|
|
|
177
472
|
/**
|
|
178
473
|
* Remove all entries.
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
* @example
|
|
513
|
+
* // Remove all
|
|
514
|
+
* const tm = new TreeMap<number, string>([[1, 'a']]);
|
|
515
|
+
* tm.clear();
|
|
516
|
+
* console.log(tm.isEmpty()); // true;
|
|
179
517
|
*/
|
|
180
518
|
clear(): void {
|
|
181
519
|
this.#core.clear();
|
|
@@ -183,6 +521,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
183
521
|
|
|
184
522
|
/**
|
|
185
523
|
* Iterate over keys in ascending order.
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
* @example
|
|
563
|
+
* // Get sorted keys
|
|
564
|
+
* const tm = new TreeMap<number, string>([[3, 'c'], [1, 'a']]);
|
|
565
|
+
* console.log([...tm.keys()]); // [1, 3];
|
|
186
566
|
*/
|
|
187
567
|
keys(): IterableIterator<K> {
|
|
188
568
|
return this.#core.keys();
|
|
@@ -198,6 +578,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
198
578
|
* Iterate over values in ascending key order.
|
|
199
579
|
*
|
|
200
580
|
* Note: values may be `undefined` (TreeMap allows storing `undefined`, like native `Map`).
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
* @example
|
|
620
|
+
* // Get values in key order
|
|
621
|
+
* const tm = new TreeMap<number, string>([[2, 'b'], [1, 'a']]);
|
|
622
|
+
* console.log([...tm.values()]); // ['a', 'b'];
|
|
201
623
|
*/
|
|
202
624
|
*values(): IterableIterator<V | undefined> {
|
|
203
625
|
for (const k of this.keys()) yield this._entryFromKey(k)[1];
|
|
@@ -207,6 +629,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
207
629
|
* Iterate over `[key, value]` entries in ascending key order.
|
|
208
630
|
*
|
|
209
631
|
* Note: values may be `undefined`.
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
* @example
|
|
671
|
+
* // Iterate key-value pairs
|
|
672
|
+
* const tm = new TreeMap<number, string>([[3, 'c'], [1, 'a'], [2, 'b']]);
|
|
673
|
+
* console.log([...tm.entries()]); // [[1, 'a'], [2, 'b'], [3, 'c']];
|
|
210
674
|
*/
|
|
211
675
|
*entries(): IterableIterator<[K, V | undefined]> {
|
|
212
676
|
for (const k of this.keys()) yield this._entryFromKey(k);
|
|
@@ -220,6 +684,50 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
220
684
|
* Visit each entry in ascending key order.
|
|
221
685
|
*
|
|
222
686
|
* Note: callback value may be `undefined`.
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
* @example
|
|
726
|
+
* // Execute for each entry
|
|
727
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
728
|
+
* const pairs: string[] = [];
|
|
729
|
+
* tm.forEach((v, k) => pairs.push(`${k}:${v}`));
|
|
730
|
+
* console.log(pairs); // ['1:a', '2:b'];
|
|
223
731
|
*/
|
|
224
732
|
forEach(cb: (value: V | undefined, key: K, map: TreeMap<K, V>) => void, thisArg?: any): void {
|
|
225
733
|
for (const [k, v] of this) cb.call(thisArg, v, k, this);
|
|
@@ -230,6 +738,49 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
230
738
|
*
|
|
231
739
|
* This mirrors `RedBlackTree.map`: mapping produces a new ordered container.
|
|
232
740
|
* @remarks Time O(n log n) expected, Space O(n)
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
* @example
|
|
780
|
+
* // Transform entries
|
|
781
|
+
* const tm = new TreeMap<number, number>([[1, 10], [2, 20]]);
|
|
782
|
+
* const doubled = tm.map((v, k) => [k, (v ?? 0) * 2] as [number, number]);
|
|
783
|
+
* console.log([...doubled.values()]); // [20, 40];
|
|
233
784
|
*/
|
|
234
785
|
map<MK, MV>(
|
|
235
786
|
callbackfn: TreeMapEntryCallback<K, V, [MK, MV], TreeMap<K, V>>,
|
|
@@ -250,6 +801,49 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
250
801
|
/**
|
|
251
802
|
* Create a new TreeMap containing only entries that satisfy the predicate.
|
|
252
803
|
* @remarks Time O(n log n) expected, Space O(n)
|
|
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
|
+
* @example
|
|
843
|
+
* // Filter entries
|
|
844
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
845
|
+
* const filtered = tm.filter((v, k) => k > 1);
|
|
846
|
+
* console.log([...filtered.keys()]); // [2, 3];
|
|
253
847
|
*/
|
|
254
848
|
filter(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): TreeMap<K, V> {
|
|
255
849
|
const out = new TreeMap<K, V>([], { comparator: this.#userComparator });
|
|
@@ -266,6 +860,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
266
860
|
/**
|
|
267
861
|
* Reduce entries into a single accumulator.
|
|
268
862
|
* @remarks Time O(n), Space O(1)
|
|
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
|
+
* @example
|
|
902
|
+
* // Aggregate values
|
|
903
|
+
* const tm = new TreeMap<number, number>([[1, 10], [2, 20]]);
|
|
904
|
+
* console.log(tm.reduce((acc, v) => acc + (v ?? 0), 0)); // 30;
|
|
269
905
|
*/
|
|
270
906
|
reduce<A>(callbackfn: TreeMapReduceCallback<K, V, A, TreeMap<K, V>>, initialValue: A): A {
|
|
271
907
|
let acc = initialValue;
|
|
@@ -277,6 +913,46 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
277
913
|
/**
|
|
278
914
|
* Test whether all entries satisfy a predicate.
|
|
279
915
|
* @remarks Time O(n), Space O(1)
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
* @example
|
|
953
|
+
* // Test all entries
|
|
954
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
955
|
+
* console.log(tm.every((v, k) => k > 0)); // true;
|
|
280
956
|
*/
|
|
281
957
|
every(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): boolean {
|
|
282
958
|
let index = 0;
|
|
@@ -292,6 +968,46 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
292
968
|
/**
|
|
293
969
|
* Test whether any entry satisfies a predicate.
|
|
294
970
|
* @remarks Time O(n), Space O(1)
|
|
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
|
+
* @example
|
|
1008
|
+
* // Test any entry
|
|
1009
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
1010
|
+
* console.log(tm.some((v, k) => k === 2)); // true;
|
|
295
1011
|
*/
|
|
296
1012
|
some(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): boolean {
|
|
297
1013
|
let index = 0;
|
|
@@ -308,6 +1024,46 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
308
1024
|
* Find the first entry that satisfies a predicate.
|
|
309
1025
|
* @returns The first matching `[key, value]` tuple, or `undefined`.
|
|
310
1026
|
* @remarks Time O(n), Space O(1)
|
|
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
|
+
* @example
|
|
1064
|
+
* // Find matching entry
|
|
1065
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
1066
|
+
* console.log(tm.find(v => v === 'b')?.[0]); // 2;
|
|
311
1067
|
*/
|
|
312
1068
|
find(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): [K, V | undefined] | undefined {
|
|
313
1069
|
let index = 0;
|
|
@@ -323,6 +1079,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
323
1079
|
/**
|
|
324
1080
|
* Materialize the map into an array of `[key, value]` tuples.
|
|
325
1081
|
* @remarks Time O(n), Space O(n)
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
* @example
|
|
1121
|
+
* // Convert to array
|
|
1122
|
+
* const tm = new TreeMap<number, string>([[2, 'b'], [1, 'a']]);
|
|
1123
|
+
* console.log(tm.toArray()); // [[1, 'a'], [2, 'b']];
|
|
326
1124
|
*/
|
|
327
1125
|
toArray(): Array<[K, V | undefined]> {
|
|
328
1126
|
return [...this];
|
|
@@ -331,6 +1129,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
331
1129
|
/**
|
|
332
1130
|
* Print a human-friendly representation.
|
|
333
1131
|
* @remarks Time O(n), Space O(n)
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
* @example
|
|
1171
|
+
* // Display tree
|
|
1172
|
+
* const tm = new TreeMap<number, string>([[1, 'a']]);
|
|
1173
|
+
* expect(() => tm.print()).not.toThrow();
|
|
334
1174
|
*/
|
|
335
1175
|
print(): void {
|
|
336
1176
|
// Delegate to the underlying tree's visualization.
|
|
@@ -342,6 +1182,43 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
342
1182
|
|
|
343
1183
|
/**
|
|
344
1184
|
* Smallest entry by key.
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
* @example
|
|
1197
|
+
* // Leaderboard with ranked scores
|
|
1198
|
+
* // Use score as key (descending), player name as value
|
|
1199
|
+
* const leaderboard = new TreeMap<number, string>([], {
|
|
1200
|
+
* comparator: (a, b) => b - a // descending
|
|
1201
|
+
* });
|
|
1202
|
+
*
|
|
1203
|
+
* leaderboard.set(1500, 'Alice');
|
|
1204
|
+
* leaderboard.set(2200, 'Bob');
|
|
1205
|
+
* leaderboard.set(1800, 'Charlie');
|
|
1206
|
+
* leaderboard.set(2500, 'Diana');
|
|
1207
|
+
*
|
|
1208
|
+
* // Top 3 players (first 3 in descending order)
|
|
1209
|
+
* const top3 = [...leaderboard.entries()].slice(0, 3);
|
|
1210
|
+
* console.log(top3); // [
|
|
1211
|
+
* // [2500, 'Diana'],
|
|
1212
|
+
* // [2200, 'Bob'],
|
|
1213
|
+
* // [1800, 'Charlie']
|
|
1214
|
+
* // ];
|
|
1215
|
+
*
|
|
1216
|
+
* // Highest scorer
|
|
1217
|
+
* console.log(leaderboard.first()); // [2500, 'Diana'];
|
|
1218
|
+
*
|
|
1219
|
+
* // Remove lowest scorer
|
|
1220
|
+
* console.log(leaderboard.pollLast()); // [1500, 'Alice'];
|
|
1221
|
+
* console.log(leaderboard.size); // 3;
|
|
345
1222
|
*/
|
|
346
1223
|
first(): [K, V | undefined] | undefined {
|
|
347
1224
|
const k = this.#core.getLeftMost();
|
|
@@ -350,6 +1227,27 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
350
1227
|
|
|
351
1228
|
/**
|
|
352
1229
|
* Largest entry by key.
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
|
|
1238
|
+
|
|
1239
|
+
|
|
1240
|
+
|
|
1241
|
+
* @example
|
|
1242
|
+
* // Access the maximum entry
|
|
1243
|
+
* const scores = new TreeMap<number, string>([
|
|
1244
|
+
* [85, 'Bob'],
|
|
1245
|
+
* [92, 'Alice'],
|
|
1246
|
+
* [78, 'Charlie']
|
|
1247
|
+
* ]);
|
|
1248
|
+
*
|
|
1249
|
+
* console.log(scores.last()); // [92, 'Alice'];
|
|
1250
|
+
* console.log(scores.first()); // [78, 'Charlie'];
|
|
353
1251
|
*/
|
|
354
1252
|
last(): [K, V | undefined] | undefined {
|
|
355
1253
|
const k = this.#core.getRightMost();
|
|
@@ -358,6 +1256,29 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
358
1256
|
|
|
359
1257
|
/**
|
|
360
1258
|
* Remove and return the smallest entry.
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
|
|
1263
|
+
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
|
|
1270
|
+
* @example
|
|
1271
|
+
* // Process items from lowest priority
|
|
1272
|
+
* const tasks = new TreeMap<number, string>([
|
|
1273
|
+
* [3, 'Low'],
|
|
1274
|
+
* [1, 'Critical'],
|
|
1275
|
+
* [2, 'Medium']
|
|
1276
|
+
* ]);
|
|
1277
|
+
*
|
|
1278
|
+
* // Process lowest priority first
|
|
1279
|
+
* console.log(tasks.pollFirst()); // [1, 'Critical'];
|
|
1280
|
+
* console.log(tasks.pollFirst()); // [2, 'Medium'];
|
|
1281
|
+
* console.log(tasks.size); // 1;
|
|
361
1282
|
*/
|
|
362
1283
|
pollFirst(): [K, V | undefined] | undefined {
|
|
363
1284
|
const entry = this.first();
|
|
@@ -368,6 +1289,29 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
368
1289
|
|
|
369
1290
|
/**
|
|
370
1291
|
* Remove and return the largest entry.
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
|
|
1303
|
+
* @example
|
|
1304
|
+
* // Remove the maximum entry
|
|
1305
|
+
* const bids = new TreeMap<number, string>([
|
|
1306
|
+
* [100, 'Alice'],
|
|
1307
|
+
* [150, 'Bob'],
|
|
1308
|
+
* [120, 'Charlie']
|
|
1309
|
+
* ]);
|
|
1310
|
+
*
|
|
1311
|
+
* // Remove highest bid
|
|
1312
|
+
* console.log(bids.pollLast()); // [150, 'Bob'];
|
|
1313
|
+
* console.log(bids.size); // 2;
|
|
1314
|
+
* console.log(bids.last()); // [120, 'Charlie'];
|
|
371
1315
|
*/
|
|
372
1316
|
pollLast(): [K, V | undefined] | undefined {
|
|
373
1317
|
const entry = this.last();
|
|
@@ -378,6 +1322,75 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
378
1322
|
|
|
379
1323
|
/**
|
|
380
1324
|
* Smallest entry whose key is >= the given key.
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
|
|
1345
|
+
|
|
1346
|
+
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
|
|
1356
|
+
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
|
|
1363
|
+
* @example
|
|
1364
|
+
* // Event scheduler with time-based lookup
|
|
1365
|
+
* const events = new TreeMap<Date, string>();
|
|
1366
|
+
*
|
|
1367
|
+
* const meeting = new Date('2024-01-15T10:00:00Z');
|
|
1368
|
+
* const lunch = new Date('2024-01-15T12:00:00Z');
|
|
1369
|
+
* const review = new Date('2024-01-15T15:00:00Z');
|
|
1370
|
+
* const standup = new Date('2024-01-15T09:00:00Z');
|
|
1371
|
+
*
|
|
1372
|
+
* events.set(meeting, 'Team Meeting');
|
|
1373
|
+
* events.set(lunch, 'Lunch Break');
|
|
1374
|
+
* events.set(review, 'Code Review');
|
|
1375
|
+
* events.set(standup, 'Daily Standup');
|
|
1376
|
+
*
|
|
1377
|
+
* // Events are sorted chronologically
|
|
1378
|
+
* console.log([...events.values()]); // [
|
|
1379
|
+
* // 'Daily Standup',
|
|
1380
|
+
* // 'Team Meeting',
|
|
1381
|
+
* // 'Lunch Break',
|
|
1382
|
+
* // 'Code Review'
|
|
1383
|
+
* // ];
|
|
1384
|
+
*
|
|
1385
|
+
* // Next event after 11:00
|
|
1386
|
+
* const after11 = new Date('2024-01-15T11:00:00Z');
|
|
1387
|
+
* console.log(events.ceiling(after11)?.[1]); // 'Lunch Break';
|
|
1388
|
+
*
|
|
1389
|
+
* // Events between 9:30 and 13:00
|
|
1390
|
+
* const from = new Date('2024-01-15T09:30:00Z');
|
|
1391
|
+
* const to = new Date('2024-01-15T13:00:00Z');
|
|
1392
|
+
* const window = events.rangeSearch([from, to]);
|
|
1393
|
+
* console.log(window.map(([, v]) => v)); // ['Team Meeting', 'Lunch Break'];
|
|
381
1394
|
*/
|
|
382
1395
|
ceiling(key: K): [K, V | undefined] | undefined {
|
|
383
1396
|
this._validateKey(key);
|
|
@@ -387,6 +1400,59 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
387
1400
|
|
|
388
1401
|
/**
|
|
389
1402
|
* Largest entry whose key is <= the given key.
|
|
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
|
+
* @example
|
|
1442
|
+
* // Find the largest key ≤ target
|
|
1443
|
+
* const versions = new TreeMap<number, string>([
|
|
1444
|
+
* [1, 'v1.0'],
|
|
1445
|
+
* [3, 'v3.0'],
|
|
1446
|
+
* [5, 'v5.0'],
|
|
1447
|
+
* [7, 'v7.0']
|
|
1448
|
+
* ]);
|
|
1449
|
+
*
|
|
1450
|
+
* // Largest version ≤ 4
|
|
1451
|
+
* console.log(versions.floor(4)); // [3, 'v3.0'];
|
|
1452
|
+
* // Largest version ≤ 5 (exact match)
|
|
1453
|
+
* console.log(versions.floor(5)); // [5, 'v5.0'];
|
|
1454
|
+
* // No version ≤ 0
|
|
1455
|
+
* console.log(versions.floor(0)); // undefined;
|
|
390
1456
|
*/
|
|
391
1457
|
floor(key: K): [K, V | undefined] | undefined {
|
|
392
1458
|
this._validateKey(key);
|
|
@@ -396,6 +1462,59 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
396
1462
|
|
|
397
1463
|
/**
|
|
398
1464
|
* Smallest entry whose key is > the given key.
|
|
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
|
+
* @example
|
|
1504
|
+
* // Find the smallest key strictly > target
|
|
1505
|
+
* const prices = new TreeMap<number, string>([
|
|
1506
|
+
* [10, 'Basic'],
|
|
1507
|
+
* [25, 'Standard'],
|
|
1508
|
+
* [50, 'Premium'],
|
|
1509
|
+
* [100, 'Enterprise']
|
|
1510
|
+
* ]);
|
|
1511
|
+
*
|
|
1512
|
+
* // Next tier above $25
|
|
1513
|
+
* console.log(prices.higher(25)); // [50, 'Premium'];
|
|
1514
|
+
* // Next tier above $99
|
|
1515
|
+
* console.log(prices.higher(99)); // [100, 'Enterprise'];
|
|
1516
|
+
* // Nothing above $100
|
|
1517
|
+
* console.log(prices.higher(100)); // undefined;
|
|
399
1518
|
*/
|
|
400
1519
|
higher(key: K): [K, V | undefined] | undefined {
|
|
401
1520
|
this._validateKey(key);
|
|
@@ -405,6 +1524,57 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
405
1524
|
|
|
406
1525
|
/**
|
|
407
1526
|
* Largest entry whose key is < the given key.
|
|
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
|
+
|
|
1562
|
+
|
|
1563
|
+
|
|
1564
|
+
|
|
1565
|
+
* @example
|
|
1566
|
+
* // Find the largest key strictly < target
|
|
1567
|
+
* const temps = new TreeMap<number, string>([
|
|
1568
|
+
* [0, 'Freezing'],
|
|
1569
|
+
* [20, 'Cool'],
|
|
1570
|
+
* [30, 'Warm'],
|
|
1571
|
+
* [40, 'Hot']
|
|
1572
|
+
* ]);
|
|
1573
|
+
*
|
|
1574
|
+
* // Largest reading below 30
|
|
1575
|
+
* console.log(temps.lower(30)); // [20, 'Cool'];
|
|
1576
|
+
* // Nothing below 0
|
|
1577
|
+
* console.log(temps.lower(0)); // undefined;
|
|
408
1578
|
*/
|
|
409
1579
|
lower(key: K): [K, V | undefined] | undefined {
|
|
410
1580
|
this._validateKey(key);
|
|
@@ -417,6 +1587,74 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
417
1587
|
*
|
|
418
1588
|
* @param range `[low, high]`
|
|
419
1589
|
* @param options Inclusive/exclusive bounds (defaults to inclusive).
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
|
|
1598
|
+
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
|
|
1605
|
+
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
|
|
1611
|
+
|
|
1612
|
+
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
|
|
1617
|
+
|
|
1618
|
+
|
|
1619
|
+
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
* @example
|
|
1629
|
+
* // Inventory system with price-sorted products
|
|
1630
|
+
* interface Product {
|
|
1631
|
+
* name: string;
|
|
1632
|
+
* price: number;
|
|
1633
|
+
* stock: number;
|
|
1634
|
+
* }
|
|
1635
|
+
*
|
|
1636
|
+
* const inventory = new TreeMap<string, Product, Product>(
|
|
1637
|
+
* [
|
|
1638
|
+
* { name: 'Widget', price: 9.99, stock: 100 },
|
|
1639
|
+
* { name: 'Gadget', price: 24.99, stock: 50 },
|
|
1640
|
+
* { name: 'Doohickey', price: 4.99, stock: 200 }
|
|
1641
|
+
* ],
|
|
1642
|
+
* { toEntryFn: p => [p.name, p] }
|
|
1643
|
+
* );
|
|
1644
|
+
*
|
|
1645
|
+
* // Sorted alphabetically by product name
|
|
1646
|
+
* console.log([...inventory.keys()]); // ['Doohickey', 'Gadget', 'Widget'];
|
|
1647
|
+
*
|
|
1648
|
+
* // Filter high-stock items
|
|
1649
|
+
* const highStock = inventory.filter(p => (p?.stock ?? 0) > 75);
|
|
1650
|
+
* console.log([...highStock.keys()]); // ['Doohickey', 'Widget'];
|
|
1651
|
+
*
|
|
1652
|
+
* // Calculate total inventory value
|
|
1653
|
+
* const totalValue = inventory.reduce(
|
|
1654
|
+
* (sum, p) => sum + (p ? p.price * p.stock : 0),
|
|
1655
|
+
* 0
|
|
1656
|
+
* );
|
|
1657
|
+
* console.log(totalValue); // toBeCloseTo;
|
|
420
1658
|
*/
|
|
421
1659
|
rangeSearch(range: [K, K], options: TreeMapRangeOptions = {}): Array<[K, V | undefined]> {
|
|
422
1660
|
const { lowInclusive = true, highInclusive = true } = options;
|
|
@@ -429,7 +1667,7 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
429
1667
|
const cmp = this.#core.comparator;
|
|
430
1668
|
|
|
431
1669
|
for (const k of keys) {
|
|
432
|
-
if (k === undefined) continue;
|
|
1670
|
+
/* istanbul ignore next -- defensive: tree keys are never undefined */ if (k === undefined) continue;
|
|
433
1671
|
if (!lowInclusive && cmp(k, low) === 0) continue;
|
|
434
1672
|
if (!highInclusive && cmp(k, high) === 0) continue;
|
|
435
1673
|
out.push(this._entryFromKey(k));
|
|
@@ -441,11 +1679,51 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
441
1679
|
/**
|
|
442
1680
|
* Creates a shallow clone of this map.
|
|
443
1681
|
* @remarks Time O(n log n), Space O(n)
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
1682
|
+
|
|
1683
|
+
|
|
1684
|
+
|
|
1685
|
+
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
|
|
1699
|
+
|
|
1700
|
+
|
|
1701
|
+
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
|
|
1705
|
+
|
|
1706
|
+
|
|
1707
|
+
|
|
1708
|
+
|
|
1709
|
+
|
|
1710
|
+
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
|
|
1714
|
+
|
|
1715
|
+
|
|
1716
|
+
|
|
1717
|
+
|
|
1718
|
+
|
|
1719
|
+
|
|
1720
|
+
|
|
1721
|
+
* @example
|
|
1722
|
+
* // Deep clone
|
|
1723
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
1724
|
+
* const copy = tm.clone();
|
|
1725
|
+
* copy.delete(1);
|
|
1726
|
+
* console.log(tm.has(1)); // true;
|
|
449
1727
|
*/
|
|
450
1728
|
clone(): TreeMap<K, V> {
|
|
451
1729
|
return new TreeMap<K, V>(this, {
|