data-structure-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/CHANGELOG.md +1 -1
- package/README.md +15 -5
- package/dist/cjs/index.cjs +10240 -2079
- package/dist/cjs-legacy/index.cjs +10305 -2135
- package/dist/esm/index.mjs +10241 -2078
- package/dist/esm-legacy/index.mjs +10306 -2134
- 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/data-structure-typed.js +10308 -2133
- package/dist/umd/data-structure-typed.min.js +4 -4
- package/package.json +5 -4
- package/src/data-structures/base/iterable-element-base.ts +4 -5
- package/src/data-structures/binary-tree/avl-tree.ts +146 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +316 -247
- package/src/data-structures/binary-tree/binary-tree.ts +454 -79
- package/src/data-structures/binary-tree/bst.ts +359 -34
- package/src/data-structures/binary-tree/red-black-tree.ts +309 -97
- package/src/data-structures/binary-tree/segment-tree.ts +378 -248
- package/src/data-structures/binary-tree/tree-map.ts +1403 -6
- package/src/data-structures/binary-tree/tree-multi-map.ts +1214 -211
- package/src/data-structures/binary-tree/tree-multi-set.ts +954 -65
- package/src/data-structures/binary-tree/tree-set.ts +1250 -9
- package/src/data-structures/graph/directed-graph.ts +229 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +213 -59
- package/src/data-structures/hash/hash-map.ts +241 -77
- package/src/data-structures/heap/heap.ts +301 -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 +303 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +293 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +707 -90
- package/src/data-structures/matrix/matrix.ts +424 -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 +287 -65
- package/src/data-structures/queue/queue.ts +223 -42
- package/src/data-structures/stack/stack.ts +184 -32
- package/src/data-structures/trie/trie.ts +225 -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,52 @@ 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
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
* @example
|
|
184
|
+
* // Check empty
|
|
185
|
+
* console.log(new TreeMap().isEmpty()); // true;
|
|
133
186
|
*/
|
|
134
187
|
isEmpty(): boolean {
|
|
135
188
|
return this.size === 0;
|
|
@@ -138,6 +191,78 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
138
191
|
/**
|
|
139
192
|
* Set or overwrite a value for a key.
|
|
140
193
|
* @remarks Expected time O(log n)
|
|
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
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
* @example
|
|
247
|
+
* // Sorted dictionary for a contact book
|
|
248
|
+
* const contacts = new TreeMap<string, string>([
|
|
249
|
+
* ['Bob', '555-0102'],
|
|
250
|
+
* ['Alice', '555-0101'],
|
|
251
|
+
* ['Charlie', '555-0103']
|
|
252
|
+
* ]);
|
|
253
|
+
*
|
|
254
|
+
* // Contacts are automatically sorted by name
|
|
255
|
+
* console.log([...contacts.keys()]); // ['Alice', 'Bob', 'Charlie'];
|
|
256
|
+
* console.log(contacts.get('Bob')); // '555-0102';
|
|
257
|
+
*
|
|
258
|
+
* // Find the first contact alphabetically after 'B'
|
|
259
|
+
* console.log(contacts.ceiling('B')); // ['Bob', '555-0102'];
|
|
260
|
+
*
|
|
261
|
+
* // Find contacts in range
|
|
262
|
+
* console.log(contacts.rangeSearch(['Alice', 'Bob'])); // [
|
|
263
|
+
* // ['Alice', '555-0101'],
|
|
264
|
+
* // ['Bob', '555-0102']
|
|
265
|
+
* // ];
|
|
141
266
|
*/
|
|
142
267
|
set(key: K, value: V | undefined): this {
|
|
143
268
|
this._validateKey(key);
|
|
@@ -148,6 +273,71 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
148
273
|
/**
|
|
149
274
|
* Get the value under a key.
|
|
150
275
|
* @remarks Expected time O(log n)
|
|
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
|
+
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
* @example
|
|
331
|
+
* // Configuration registry with typed lookups
|
|
332
|
+
* const config = new TreeMap<string, number>([
|
|
333
|
+
* ['maxRetries', 3],
|
|
334
|
+
* ['timeout', 5000],
|
|
335
|
+
* ['poolSize', 10]
|
|
336
|
+
* ]);
|
|
337
|
+
*
|
|
338
|
+
* console.log(config.get('timeout')); // 5000;
|
|
339
|
+
* console.log(config.get('missing')); // undefined;
|
|
340
|
+
* console.log(config.size); // 3;
|
|
151
341
|
*/
|
|
152
342
|
get(key: K): V | undefined {
|
|
153
343
|
this._validateKey(key);
|
|
@@ -157,6 +347,70 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
157
347
|
/**
|
|
158
348
|
* Test whether a key exists.
|
|
159
349
|
* @remarks Expected time O(log n)
|
|
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
|
+
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
* @example
|
|
405
|
+
* // Feature flag checking
|
|
406
|
+
* const flags = new TreeMap<string, boolean>([
|
|
407
|
+
* ['darkMode', true],
|
|
408
|
+
* ['betaFeature', false],
|
|
409
|
+
* ['notifications', true]
|
|
410
|
+
* ]);
|
|
411
|
+
*
|
|
412
|
+
* console.log(flags.has('darkMode')); // true;
|
|
413
|
+
* console.log(flags.has('unknownFlag')); // false;
|
|
160
414
|
*/
|
|
161
415
|
has(key: K): boolean {
|
|
162
416
|
this._validateKey(key);
|
|
@@ -167,6 +421,72 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
167
421
|
* Delete a key.
|
|
168
422
|
* @returns `true` if the key existed; otherwise `false`.
|
|
169
423
|
* @remarks Expected time O(log n)
|
|
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
|
+
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
* @example
|
|
479
|
+
* // Session management with expiry
|
|
480
|
+
* const sessions = new TreeMap<string, number>([
|
|
481
|
+
* ['sess_abc', Date.now()],
|
|
482
|
+
* ['sess_def', Date.now()],
|
|
483
|
+
* ['sess_ghi', Date.now()]
|
|
484
|
+
* ]);
|
|
485
|
+
*
|
|
486
|
+
* console.log(sessions.size); // 3;
|
|
487
|
+
* sessions.delete('sess_def');
|
|
488
|
+
* console.log(sessions.has('sess_def')); // false;
|
|
489
|
+
* console.log(sessions.size); // 2;
|
|
170
490
|
*/
|
|
171
491
|
delete(key: K): boolean {
|
|
172
492
|
this._validateKey(key);
|
|
@@ -176,6 +496,54 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
176
496
|
|
|
177
497
|
/**
|
|
178
498
|
* Remove all entries.
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
* @example
|
|
543
|
+
* // Remove all
|
|
544
|
+
* const tm = new TreeMap<number, string>([[1, 'a']]);
|
|
545
|
+
* tm.clear();
|
|
546
|
+
* console.log(tm.isEmpty()); // true;
|
|
179
547
|
*/
|
|
180
548
|
clear(): void {
|
|
181
549
|
this.#core.clear();
|
|
@@ -183,6 +551,53 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
183
551
|
|
|
184
552
|
/**
|
|
185
553
|
* Iterate over keys in ascending order.
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
* @example
|
|
598
|
+
* // Get sorted keys
|
|
599
|
+
* const tm = new TreeMap<number, string>([[3, 'c'], [1, 'a']]);
|
|
600
|
+
* console.log([...tm.keys()]); // [1, 3];
|
|
186
601
|
*/
|
|
187
602
|
keys(): IterableIterator<K> {
|
|
188
603
|
return this.#core.keys();
|
|
@@ -198,6 +613,53 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
198
613
|
* Iterate over values in ascending key order.
|
|
199
614
|
*
|
|
200
615
|
* Note: values may be `undefined` (TreeMap allows storing `undefined`, like native `Map`).
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
* @example
|
|
660
|
+
* // Get values in key order
|
|
661
|
+
* const tm = new TreeMap<number, string>([[2, 'b'], [1, 'a']]);
|
|
662
|
+
* console.log([...tm.values()]); // ['a', 'b'];
|
|
201
663
|
*/
|
|
202
664
|
*values(): IterableIterator<V | undefined> {
|
|
203
665
|
for (const k of this.keys()) yield this._entryFromKey(k)[1];
|
|
@@ -207,6 +669,53 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
207
669
|
* Iterate over `[key, value]` entries in ascending key order.
|
|
208
670
|
*
|
|
209
671
|
* Note: values may be `undefined`.
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
|
|
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
|
+
* @example
|
|
716
|
+
* // Iterate key-value pairs
|
|
717
|
+
* const tm = new TreeMap<number, string>([[3, 'c'], [1, 'a'], [2, 'b']]);
|
|
718
|
+
* console.log([...tm.entries()]); // [[1, 'a'], [2, 'b'], [3, 'c']];
|
|
210
719
|
*/
|
|
211
720
|
*entries(): IterableIterator<[K, V | undefined]> {
|
|
212
721
|
for (const k of this.keys()) yield this._entryFromKey(k);
|
|
@@ -220,6 +729,55 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
220
729
|
* Visit each entry in ascending key order.
|
|
221
730
|
*
|
|
222
731
|
* Note: callback value may be `undefined`.
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
* @example
|
|
776
|
+
* // Execute for each entry
|
|
777
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
778
|
+
* const pairs: string[] = [];
|
|
779
|
+
* tm.forEach((v, k) => pairs.push(`${k}:${v}`));
|
|
780
|
+
* console.log(pairs); // ['1:a', '2:b'];
|
|
223
781
|
*/
|
|
224
782
|
forEach(cb: (value: V | undefined, key: K, map: TreeMap<K, V>) => void, thisArg?: any): void {
|
|
225
783
|
for (const [k, v] of this) cb.call(thisArg, v, k, this);
|
|
@@ -230,6 +788,54 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
230
788
|
*
|
|
231
789
|
* This mirrors `RedBlackTree.map`: mapping produces a new ordered container.
|
|
232
790
|
* @remarks Time O(n log n) expected, Space O(n)
|
|
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
|
+
* @example
|
|
835
|
+
* // Transform entries
|
|
836
|
+
* const tm = new TreeMap<number, number>([[1, 10], [2, 20]]);
|
|
837
|
+
* const doubled = tm.map((v, k) => [k, (v ?? 0) * 2] as [number, number]);
|
|
838
|
+
* console.log([...doubled.values()]); // [20, 40];
|
|
233
839
|
*/
|
|
234
840
|
map<MK, MV>(
|
|
235
841
|
callbackfn: TreeMapEntryCallback<K, V, [MK, MV], TreeMap<K, V>>,
|
|
@@ -250,6 +856,54 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
250
856
|
/**
|
|
251
857
|
* Create a new TreeMap containing only entries that satisfy the predicate.
|
|
252
858
|
* @remarks Time O(n log n) expected, Space O(n)
|
|
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
|
+
* @example
|
|
903
|
+
* // Filter entries
|
|
904
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
905
|
+
* const filtered = tm.filter((v, k) => k > 1);
|
|
906
|
+
* console.log([...filtered.keys()]); // [2, 3];
|
|
253
907
|
*/
|
|
254
908
|
filter(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): TreeMap<K, V> {
|
|
255
909
|
const out = new TreeMap<K, V>([], { comparator: this.#userComparator });
|
|
@@ -266,6 +920,53 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
266
920
|
/**
|
|
267
921
|
* Reduce entries into a single accumulator.
|
|
268
922
|
* @remarks Time O(n), Space O(1)
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
* @example
|
|
967
|
+
* // Aggregate values
|
|
968
|
+
* const tm = new TreeMap<number, number>([[1, 10], [2, 20]]);
|
|
969
|
+
* console.log(tm.reduce((acc, v) => acc + (v ?? 0), 0)); // 30;
|
|
269
970
|
*/
|
|
270
971
|
reduce<A>(callbackfn: TreeMapReduceCallback<K, V, A, TreeMap<K, V>>, initialValue: A): A {
|
|
271
972
|
let acc = initialValue;
|
|
@@ -277,6 +978,51 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
277
978
|
/**
|
|
278
979
|
* Test whether all entries satisfy a predicate.
|
|
279
980
|
* @remarks Time O(n), Space O(1)
|
|
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
|
+
* @example
|
|
1023
|
+
* // Test all entries
|
|
1024
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
1025
|
+
* console.log(tm.every((v, k) => k > 0)); // true;
|
|
280
1026
|
*/
|
|
281
1027
|
every(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): boolean {
|
|
282
1028
|
let index = 0;
|
|
@@ -292,6 +1038,51 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
292
1038
|
/**
|
|
293
1039
|
* Test whether any entry satisfies a predicate.
|
|
294
1040
|
* @remarks Time O(n), Space O(1)
|
|
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
|
+
* @example
|
|
1083
|
+
* // Test any entry
|
|
1084
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
1085
|
+
* console.log(tm.some((v, k) => k === 2)); // true;
|
|
295
1086
|
*/
|
|
296
1087
|
some(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): boolean {
|
|
297
1088
|
let index = 0;
|
|
@@ -308,6 +1099,51 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
308
1099
|
* Find the first entry that satisfies a predicate.
|
|
309
1100
|
* @returns The first matching `[key, value]` tuple, or `undefined`.
|
|
310
1101
|
* @remarks Time O(n), Space O(1)
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
* @example
|
|
1144
|
+
* // Find matching entry
|
|
1145
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
1146
|
+
* console.log(tm.find(v => v === 'b')?.[0]); // 2;
|
|
311
1147
|
*/
|
|
312
1148
|
find(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): [K, V | undefined] | undefined {
|
|
313
1149
|
let index = 0;
|
|
@@ -323,6 +1159,53 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
323
1159
|
/**
|
|
324
1160
|
* Materialize the map into an array of `[key, value]` tuples.
|
|
325
1161
|
* @remarks Time O(n), Space O(n)
|
|
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
|
+
* @example
|
|
1206
|
+
* // Convert to array
|
|
1207
|
+
* const tm = new TreeMap<number, string>([[2, 'b'], [1, 'a']]);
|
|
1208
|
+
* console.log(tm.toArray()); // [[1, 'a'], [2, 'b']];
|
|
326
1209
|
*/
|
|
327
1210
|
toArray(): Array<[K, V | undefined]> {
|
|
328
1211
|
return [...this];
|
|
@@ -331,6 +1214,53 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
331
1214
|
/**
|
|
332
1215
|
* Print a human-friendly representation.
|
|
333
1216
|
* @remarks Time O(n), Space O(n)
|
|
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
|
+
* @example
|
|
1261
|
+
* // Display tree
|
|
1262
|
+
* const tm = new TreeMap<number, string>([[1, 'a']]);
|
|
1263
|
+
* expect(() => tm.print()).not.toThrow();
|
|
334
1264
|
*/
|
|
335
1265
|
print(): void {
|
|
336
1266
|
// Delegate to the underlying tree's visualization.
|
|
@@ -342,6 +1272,44 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
342
1272
|
|
|
343
1273
|
/**
|
|
344
1274
|
* Smallest entry by key.
|
|
1275
|
+
|
|
1276
|
+
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
|
|
1287
|
+
* @example
|
|
1288
|
+
* // Leaderboard with ranked scores
|
|
1289
|
+
* // Use score as key (descending), player name as value
|
|
1290
|
+
* const leaderboard = new TreeMap<number, string>([], {
|
|
1291
|
+
* comparator: (a, b) => b - a // descending
|
|
1292
|
+
* });
|
|
1293
|
+
*
|
|
1294
|
+
* leaderboard.set(1500, 'Alice');
|
|
1295
|
+
* leaderboard.set(2200, 'Bob');
|
|
1296
|
+
* leaderboard.set(1800, 'Charlie');
|
|
1297
|
+
* leaderboard.set(2500, 'Diana');
|
|
1298
|
+
*
|
|
1299
|
+
* // Top 3 players (first 3 in descending order)
|
|
1300
|
+
* const top3 = [...leaderboard.entries()].slice(0, 3);
|
|
1301
|
+
* console.log(top3); // [
|
|
1302
|
+
* // [2500, 'Diana'],
|
|
1303
|
+
* // [2200, 'Bob'],
|
|
1304
|
+
* // [1800, 'Charlie']
|
|
1305
|
+
* // ];
|
|
1306
|
+
*
|
|
1307
|
+
* // Highest scorer
|
|
1308
|
+
* console.log(leaderboard.first()); // [2500, 'Diana'];
|
|
1309
|
+
*
|
|
1310
|
+
* // Remove lowest scorer
|
|
1311
|
+
* console.log(leaderboard.pollLast()); // [1500, 'Alice'];
|
|
1312
|
+
* console.log(leaderboard.size); // 3;
|
|
345
1313
|
*/
|
|
346
1314
|
first(): [K, V | undefined] | undefined {
|
|
347
1315
|
const k = this.#core.getLeftMost();
|
|
@@ -350,6 +1318,28 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
350
1318
|
|
|
351
1319
|
/**
|
|
352
1320
|
* Largest entry by key.
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
* @example
|
|
1334
|
+
* // Access the maximum entry
|
|
1335
|
+
* const scores = new TreeMap<number, string>([
|
|
1336
|
+
* [85, 'Bob'],
|
|
1337
|
+
* [92, 'Alice'],
|
|
1338
|
+
* [78, 'Charlie']
|
|
1339
|
+
* ]);
|
|
1340
|
+
*
|
|
1341
|
+
* console.log(scores.last()); // [92, 'Alice'];
|
|
1342
|
+
* console.log(scores.first()); // [78, 'Charlie'];
|
|
353
1343
|
*/
|
|
354
1344
|
last(): [K, V | undefined] | undefined {
|
|
355
1345
|
const k = this.#core.getRightMost();
|
|
@@ -358,6 +1348,30 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
358
1348
|
|
|
359
1349
|
/**
|
|
360
1350
|
* Remove and return the smallest entry.
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
|
|
1356
|
+
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
|
|
1363
|
+
* @example
|
|
1364
|
+
* // Process items from lowest priority
|
|
1365
|
+
* const tasks = new TreeMap<number, string>([
|
|
1366
|
+
* [3, 'Low'],
|
|
1367
|
+
* [1, 'Critical'],
|
|
1368
|
+
* [2, 'Medium']
|
|
1369
|
+
* ]);
|
|
1370
|
+
*
|
|
1371
|
+
* // Process lowest priority first
|
|
1372
|
+
* console.log(tasks.pollFirst()); // [1, 'Critical'];
|
|
1373
|
+
* console.log(tasks.pollFirst()); // [2, 'Medium'];
|
|
1374
|
+
* console.log(tasks.size); // 1;
|
|
361
1375
|
*/
|
|
362
1376
|
pollFirst(): [K, V | undefined] | undefined {
|
|
363
1377
|
const entry = this.first();
|
|
@@ -368,6 +1382,30 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
368
1382
|
|
|
369
1383
|
/**
|
|
370
1384
|
* Remove and return the largest entry.
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
|
|
1397
|
+
* @example
|
|
1398
|
+
* // Remove the maximum entry
|
|
1399
|
+
* const bids = new TreeMap<number, string>([
|
|
1400
|
+
* [100, 'Alice'],
|
|
1401
|
+
* [150, 'Bob'],
|
|
1402
|
+
* [120, 'Charlie']
|
|
1403
|
+
* ]);
|
|
1404
|
+
*
|
|
1405
|
+
* // Remove highest bid
|
|
1406
|
+
* console.log(bids.pollLast()); // [150, 'Bob'];
|
|
1407
|
+
* console.log(bids.size); // 2;
|
|
1408
|
+
* console.log(bids.last()); // [120, 'Charlie'];
|
|
371
1409
|
*/
|
|
372
1410
|
pollLast(): [K, V | undefined] | undefined {
|
|
373
1411
|
const entry = this.last();
|
|
@@ -378,6 +1416,79 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
378
1416
|
|
|
379
1417
|
/**
|
|
380
1418
|
* Smallest entry whose key is >= the given key.
|
|
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
|
+
* @example
|
|
1462
|
+
* // Event scheduler with time-based lookup
|
|
1463
|
+
* const events = new TreeMap<Date, string>();
|
|
1464
|
+
*
|
|
1465
|
+
* const meeting = new Date('2024-01-15T10:00:00Z');
|
|
1466
|
+
* const lunch = new Date('2024-01-15T12:00:00Z');
|
|
1467
|
+
* const review = new Date('2024-01-15T15:00:00Z');
|
|
1468
|
+
* const standup = new Date('2024-01-15T09:00:00Z');
|
|
1469
|
+
*
|
|
1470
|
+
* events.set(meeting, 'Team Meeting');
|
|
1471
|
+
* events.set(lunch, 'Lunch Break');
|
|
1472
|
+
* events.set(review, 'Code Review');
|
|
1473
|
+
* events.set(standup, 'Daily Standup');
|
|
1474
|
+
*
|
|
1475
|
+
* // Events are sorted chronologically
|
|
1476
|
+
* console.log([...events.values()]); // [
|
|
1477
|
+
* // 'Daily Standup',
|
|
1478
|
+
* // 'Team Meeting',
|
|
1479
|
+
* // 'Lunch Break',
|
|
1480
|
+
* // 'Code Review'
|
|
1481
|
+
* // ];
|
|
1482
|
+
*
|
|
1483
|
+
* // Next event after 11:00
|
|
1484
|
+
* const after11 = new Date('2024-01-15T11:00:00Z');
|
|
1485
|
+
* console.log(events.ceiling(after11)?.[1]); // 'Lunch Break';
|
|
1486
|
+
*
|
|
1487
|
+
* // Events between 9:30 and 13:00
|
|
1488
|
+
* const from = new Date('2024-01-15T09:30:00Z');
|
|
1489
|
+
* const to = new Date('2024-01-15T13:00:00Z');
|
|
1490
|
+
* const window = events.rangeSearch([from, to]);
|
|
1491
|
+
* console.log(window.map(([, v]) => v)); // ['Team Meeting', 'Lunch Break'];
|
|
381
1492
|
*/
|
|
382
1493
|
ceiling(key: K): [K, V | undefined] | undefined {
|
|
383
1494
|
this._validateKey(key);
|
|
@@ -387,6 +1498,63 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
387
1498
|
|
|
388
1499
|
/**
|
|
389
1500
|
* Largest entry whose key is <= the given key.
|
|
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
|
+
* @example
|
|
1544
|
+
* // Find the largest key ≤ target
|
|
1545
|
+
* const versions = new TreeMap<number, string>([
|
|
1546
|
+
* [1, 'v1.0'],
|
|
1547
|
+
* [3, 'v3.0'],
|
|
1548
|
+
* [5, 'v5.0'],
|
|
1549
|
+
* [7, 'v7.0']
|
|
1550
|
+
* ]);
|
|
1551
|
+
*
|
|
1552
|
+
* // Largest version ≤ 4
|
|
1553
|
+
* console.log(versions.floor(4)); // [3, 'v3.0'];
|
|
1554
|
+
* // Largest version ≤ 5 (exact match)
|
|
1555
|
+
* console.log(versions.floor(5)); // [5, 'v5.0'];
|
|
1556
|
+
* // No version ≤ 0
|
|
1557
|
+
* console.log(versions.floor(0)); // undefined;
|
|
390
1558
|
*/
|
|
391
1559
|
floor(key: K): [K, V | undefined] | undefined {
|
|
392
1560
|
this._validateKey(key);
|
|
@@ -396,6 +1564,63 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
396
1564
|
|
|
397
1565
|
/**
|
|
398
1566
|
* Smallest entry whose key is > the given key.
|
|
1567
|
+
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
|
|
1571
|
+
|
|
1572
|
+
|
|
1573
|
+
|
|
1574
|
+
|
|
1575
|
+
|
|
1576
|
+
|
|
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
|
+
|
|
1604
|
+
|
|
1605
|
+
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
|
|
1609
|
+
* @example
|
|
1610
|
+
* // Find the smallest key strictly > target
|
|
1611
|
+
* const prices = new TreeMap<number, string>([
|
|
1612
|
+
* [10, 'Basic'],
|
|
1613
|
+
* [25, 'Standard'],
|
|
1614
|
+
* [50, 'Premium'],
|
|
1615
|
+
* [100, 'Enterprise']
|
|
1616
|
+
* ]);
|
|
1617
|
+
*
|
|
1618
|
+
* // Next tier above $25
|
|
1619
|
+
* console.log(prices.higher(25)); // [50, 'Premium'];
|
|
1620
|
+
* // Next tier above $99
|
|
1621
|
+
* console.log(prices.higher(99)); // [100, 'Enterprise'];
|
|
1622
|
+
* // Nothing above $100
|
|
1623
|
+
* console.log(prices.higher(100)); // undefined;
|
|
399
1624
|
*/
|
|
400
1625
|
higher(key: K): [K, V | undefined] | undefined {
|
|
401
1626
|
this._validateKey(key);
|
|
@@ -405,6 +1630,61 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
405
1630
|
|
|
406
1631
|
/**
|
|
407
1632
|
* Largest entry whose key is < the given key.
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
|
|
1637
|
+
|
|
1638
|
+
|
|
1639
|
+
|
|
1640
|
+
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
|
|
1644
|
+
|
|
1645
|
+
|
|
1646
|
+
|
|
1647
|
+
|
|
1648
|
+
|
|
1649
|
+
|
|
1650
|
+
|
|
1651
|
+
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
|
|
1655
|
+
|
|
1656
|
+
|
|
1657
|
+
|
|
1658
|
+
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
|
|
1668
|
+
|
|
1669
|
+
|
|
1670
|
+
|
|
1671
|
+
|
|
1672
|
+
|
|
1673
|
+
|
|
1674
|
+
|
|
1675
|
+
* @example
|
|
1676
|
+
* // Find the largest key strictly < target
|
|
1677
|
+
* const temps = new TreeMap<number, string>([
|
|
1678
|
+
* [0, 'Freezing'],
|
|
1679
|
+
* [20, 'Cool'],
|
|
1680
|
+
* [30, 'Warm'],
|
|
1681
|
+
* [40, 'Hot']
|
|
1682
|
+
* ]);
|
|
1683
|
+
*
|
|
1684
|
+
* // Largest reading below 30
|
|
1685
|
+
* console.log(temps.lower(30)); // [20, 'Cool'];
|
|
1686
|
+
* // Nothing below 0
|
|
1687
|
+
* console.log(temps.lower(0)); // undefined;
|
|
408
1688
|
*/
|
|
409
1689
|
lower(key: K): [K, V | undefined] | undefined {
|
|
410
1690
|
this._validateKey(key);
|
|
@@ -417,6 +1697,78 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
417
1697
|
*
|
|
418
1698
|
* @param range `[low, high]`
|
|
419
1699
|
* @param options Inclusive/exclusive bounds (defaults to inclusive).
|
|
1700
|
+
|
|
1701
|
+
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
|
|
1705
|
+
|
|
1706
|
+
|
|
1707
|
+
|
|
1708
|
+
|
|
1709
|
+
|
|
1710
|
+
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
|
|
1714
|
+
|
|
1715
|
+
|
|
1716
|
+
|
|
1717
|
+
|
|
1718
|
+
|
|
1719
|
+
|
|
1720
|
+
|
|
1721
|
+
|
|
1722
|
+
|
|
1723
|
+
|
|
1724
|
+
|
|
1725
|
+
|
|
1726
|
+
|
|
1727
|
+
|
|
1728
|
+
|
|
1729
|
+
|
|
1730
|
+
|
|
1731
|
+
|
|
1732
|
+
|
|
1733
|
+
|
|
1734
|
+
|
|
1735
|
+
|
|
1736
|
+
|
|
1737
|
+
|
|
1738
|
+
|
|
1739
|
+
|
|
1740
|
+
|
|
1741
|
+
|
|
1742
|
+
* @example
|
|
1743
|
+
* // Inventory system with price-sorted products
|
|
1744
|
+
* interface Product {
|
|
1745
|
+
* name: string;
|
|
1746
|
+
* price: number;
|
|
1747
|
+
* stock: number;
|
|
1748
|
+
* }
|
|
1749
|
+
*
|
|
1750
|
+
* const inventory = new TreeMap<string, Product, Product>(
|
|
1751
|
+
* [
|
|
1752
|
+
* { name: 'Widget', price: 9.99, stock: 100 },
|
|
1753
|
+
* { name: 'Gadget', price: 24.99, stock: 50 },
|
|
1754
|
+
* { name: 'Doohickey', price: 4.99, stock: 200 }
|
|
1755
|
+
* ],
|
|
1756
|
+
* { toEntryFn: p => [p.name, p] }
|
|
1757
|
+
* );
|
|
1758
|
+
*
|
|
1759
|
+
* // Sorted alphabetically by product name
|
|
1760
|
+
* console.log([...inventory.keys()]); // ['Doohickey', 'Gadget', 'Widget'];
|
|
1761
|
+
*
|
|
1762
|
+
* // Filter high-stock items
|
|
1763
|
+
* const highStock = inventory.filter(p => (p?.stock ?? 0) > 75);
|
|
1764
|
+
* console.log([...highStock.keys()]); // ['Doohickey', 'Widget'];
|
|
1765
|
+
*
|
|
1766
|
+
* // Calculate total inventory value
|
|
1767
|
+
* const totalValue = inventory.reduce(
|
|
1768
|
+
* (sum, p) => sum + (p ? p.price * p.stock : 0),
|
|
1769
|
+
* 0
|
|
1770
|
+
* );
|
|
1771
|
+
* console.log(totalValue); // toBeCloseTo;
|
|
420
1772
|
*/
|
|
421
1773
|
rangeSearch(range: [K, K], options: TreeMapRangeOptions = {}): Array<[K, V | undefined]> {
|
|
422
1774
|
const { lowInclusive = true, highInclusive = true } = options;
|
|
@@ -429,7 +1781,7 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
429
1781
|
const cmp = this.#core.comparator;
|
|
430
1782
|
|
|
431
1783
|
for (const k of keys) {
|
|
432
|
-
if (k === undefined) continue;
|
|
1784
|
+
/* istanbul ignore next -- defensive: tree keys are never undefined */ if (k === undefined) continue;
|
|
433
1785
|
if (!lowInclusive && cmp(k, low) === 0) continue;
|
|
434
1786
|
if (!highInclusive && cmp(k, high) === 0) continue;
|
|
435
1787
|
out.push(this._entryFromKey(k));
|
|
@@ -441,11 +1793,56 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
441
1793
|
/**
|
|
442
1794
|
* Creates a shallow clone of this map.
|
|
443
1795
|
* @remarks Time O(n log n), Space O(n)
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
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
|
+
* @example
|
|
1841
|
+
* // Deep clone
|
|
1842
|
+
* const tm = new TreeMap<number, string>([[1, 'a'], [2, 'b']]);
|
|
1843
|
+
* const copy = tm.clone();
|
|
1844
|
+
* copy.delete(1);
|
|
1845
|
+
* console.log(tm.has(1)); // true;
|
|
449
1846
|
*/
|
|
450
1847
|
clone(): TreeMap<K, V> {
|
|
451
1848
|
return new TreeMap<K, V>(this, {
|