binary-tree-typed 2.4.4 → 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 +965 -420
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +962 -417
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +965 -421
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +962 -418
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- 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 +439 -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 +217 -31
- 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/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -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 +313 -66
- 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/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/umd/binary-tree-typed.js +959 -414
- package/dist/umd/binary-tree-typed.js.map +1 -1
- package/dist/umd/binary-tree-typed.min.js +3 -3
- package/dist/umd/binary-tree-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
- package/src/data-structures/binary-tree/binary-tree.ts +542 -121
- package/src/data-structures/binary-tree/bst.ts +346 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1292 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
- package/src/data-structures/binary-tree/tree-set.ts +1143 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +223 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +299 -59
- package/src/data-structures/hash/hash-map.ts +243 -79
- package/src/data-structures/heap/heap.ts +291 -102
- package/src/data-structures/heap/max-heap.ts +48 -3
- 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 +425 -22
- package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
- 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 +343 -68
- 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 +215 -44
- 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
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
|
@@ -10,12 +10,18 @@
|
|
|
10
10
|
import type { Comparator } from '../../types';
|
|
11
11
|
import type { TreeMapEntryCallback, TreeMapOptions, TreeMapRangeOptions, TreeMapReduceCallback } from '../../types';
|
|
12
12
|
import { RedBlackTree } from './red-black-tree';
|
|
13
|
+
import { ERR } from '../../common';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* An ordered Map backed by a red-black tree.
|
|
16
17
|
*
|
|
17
18
|
* - Iteration order is ascending by key.
|
|
18
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;
|
|
19
25
|
*/
|
|
20
26
|
export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | undefined]> {
|
|
21
27
|
readonly #core: RedBlackTree<K, V>;
|
|
@@ -58,7 +64,7 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
58
64
|
} else {
|
|
59
65
|
// Validate entries like native Map: each item must be a 2-tuple-like value.
|
|
60
66
|
if (!Array.isArray(item) || item.length < 2) {
|
|
61
|
-
throw new TypeError('TreeMap
|
|
67
|
+
throw new TypeError(ERR.invalidEntry('TreeMap'));
|
|
62
68
|
}
|
|
63
69
|
k = item[0] as K;
|
|
64
70
|
v = item[1] as V | undefined;
|
|
@@ -81,7 +87,8 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
81
87
|
static createDefaultComparator<K>(): Comparator<K> {
|
|
82
88
|
return (a: K, b: K): number => {
|
|
83
89
|
if (typeof a === 'number' && typeof b === 'number') {
|
|
84
|
-
|
|
90
|
+
/* istanbul ignore next -- _validateKey prevents NaN from entering the tree */
|
|
91
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN('TreeMap'));
|
|
85
92
|
const aa = Object.is(a, -0) ? 0 : a;
|
|
86
93
|
const bb = Object.is(b, -0) ? 0 : b;
|
|
87
94
|
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
@@ -94,11 +101,12 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
94
101
|
if (a instanceof Date && b instanceof Date) {
|
|
95
102
|
const ta = a.getTime();
|
|
96
103
|
const tb = b.getTime();
|
|
97
|
-
|
|
104
|
+
/* istanbul ignore next -- _validateKey prevents invalid Date from entering the tree */
|
|
105
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate('TreeMap'));
|
|
98
106
|
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
throw new TypeError('TreeMap
|
|
109
|
+
throw new TypeError(ERR.comparatorRequired('TreeMap'));
|
|
102
110
|
};
|
|
103
111
|
}
|
|
104
112
|
|
|
@@ -106,18 +114,18 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
106
114
|
if (!this.#isDefaultComparator) return;
|
|
107
115
|
|
|
108
116
|
if (typeof key === 'number') {
|
|
109
|
-
if (Number.isNaN(key)) throw new TypeError('TreeMap
|
|
117
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN('TreeMap'));
|
|
110
118
|
return;
|
|
111
119
|
}
|
|
112
120
|
|
|
113
121
|
if (typeof key === 'string') return;
|
|
114
122
|
|
|
115
123
|
if (key instanceof Date) {
|
|
116
|
-
if (Number.isNaN(key.getTime())) throw new TypeError('TreeMap
|
|
124
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate('TreeMap'));
|
|
117
125
|
return;
|
|
118
126
|
}
|
|
119
127
|
|
|
120
|
-
throw new TypeError('TreeMap
|
|
128
|
+
throw new TypeError(ERR.comparatorRequired('TreeMap'));
|
|
121
129
|
}
|
|
122
130
|
|
|
123
131
|
/**
|
|
@@ -129,6 +137,47 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
129
137
|
|
|
130
138
|
/**
|
|
131
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;
|
|
132
181
|
*/
|
|
133
182
|
isEmpty(): boolean {
|
|
134
183
|
return this.size === 0;
|
|
@@ -137,6 +186,73 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
137
186
|
/**
|
|
138
187
|
* Set or overwrite a value for a key.
|
|
139
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
|
+
* // ];
|
|
140
256
|
*/
|
|
141
257
|
set(key: K, value: V | undefined): this {
|
|
142
258
|
this._validateKey(key);
|
|
@@ -147,6 +263,66 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
147
263
|
/**
|
|
148
264
|
* Get the value under a key.
|
|
149
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;
|
|
150
326
|
*/
|
|
151
327
|
get(key: K): V | undefined {
|
|
152
328
|
this._validateKey(key);
|
|
@@ -156,6 +332,65 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
156
332
|
/**
|
|
157
333
|
* Test whether a key exists.
|
|
158
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;
|
|
159
394
|
*/
|
|
160
395
|
has(key: K): boolean {
|
|
161
396
|
this._validateKey(key);
|
|
@@ -166,6 +401,67 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
166
401
|
* Delete a key.
|
|
167
402
|
* @returns `true` if the key existed; otherwise `false`.
|
|
168
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;
|
|
169
465
|
*/
|
|
170
466
|
delete(key: K): boolean {
|
|
171
467
|
this._validateKey(key);
|
|
@@ -175,6 +471,49 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
175
471
|
|
|
176
472
|
/**
|
|
177
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;
|
|
178
517
|
*/
|
|
179
518
|
clear(): void {
|
|
180
519
|
this.#core.clear();
|
|
@@ -182,6 +521,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
182
521
|
|
|
183
522
|
/**
|
|
184
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];
|
|
185
566
|
*/
|
|
186
567
|
keys(): IterableIterator<K> {
|
|
187
568
|
return this.#core.keys();
|
|
@@ -197,6 +578,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
197
578
|
* Iterate over values in ascending key order.
|
|
198
579
|
*
|
|
199
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'];
|
|
200
623
|
*/
|
|
201
624
|
*values(): IterableIterator<V | undefined> {
|
|
202
625
|
for (const k of this.keys()) yield this._entryFromKey(k)[1];
|
|
@@ -206,6 +629,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
206
629
|
* Iterate over `[key, value]` entries in ascending key order.
|
|
207
630
|
*
|
|
208
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']];
|
|
209
674
|
*/
|
|
210
675
|
*entries(): IterableIterator<[K, V | undefined]> {
|
|
211
676
|
for (const k of this.keys()) yield this._entryFromKey(k);
|
|
@@ -219,6 +684,50 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
219
684
|
* Visit each entry in ascending key order.
|
|
220
685
|
*
|
|
221
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'];
|
|
222
731
|
*/
|
|
223
732
|
forEach(cb: (value: V | undefined, key: K, map: TreeMap<K, V>) => void, thisArg?: any): void {
|
|
224
733
|
for (const [k, v] of this) cb.call(thisArg, v, k, this);
|
|
@@ -229,6 +738,49 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
229
738
|
*
|
|
230
739
|
* This mirrors `RedBlackTree.map`: mapping produces a new ordered container.
|
|
231
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];
|
|
232
784
|
*/
|
|
233
785
|
map<MK, MV>(
|
|
234
786
|
callbackfn: TreeMapEntryCallback<K, V, [MK, MV], TreeMap<K, V>>,
|
|
@@ -249,6 +801,49 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
249
801
|
/**
|
|
250
802
|
* Create a new TreeMap containing only entries that satisfy the predicate.
|
|
251
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];
|
|
252
847
|
*/
|
|
253
848
|
filter(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): TreeMap<K, V> {
|
|
254
849
|
const out = new TreeMap<K, V>([], { comparator: this.#userComparator });
|
|
@@ -265,6 +860,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
265
860
|
/**
|
|
266
861
|
* Reduce entries into a single accumulator.
|
|
267
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;
|
|
268
905
|
*/
|
|
269
906
|
reduce<A>(callbackfn: TreeMapReduceCallback<K, V, A, TreeMap<K, V>>, initialValue: A): A {
|
|
270
907
|
let acc = initialValue;
|
|
@@ -276,6 +913,46 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
276
913
|
/**
|
|
277
914
|
* Test whether all entries satisfy a predicate.
|
|
278
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;
|
|
279
956
|
*/
|
|
280
957
|
every(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): boolean {
|
|
281
958
|
let index = 0;
|
|
@@ -291,6 +968,46 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
291
968
|
/**
|
|
292
969
|
* Test whether any entry satisfies a predicate.
|
|
293
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;
|
|
294
1011
|
*/
|
|
295
1012
|
some(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): boolean {
|
|
296
1013
|
let index = 0;
|
|
@@ -307,6 +1024,46 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
307
1024
|
* Find the first entry that satisfies a predicate.
|
|
308
1025
|
* @returns The first matching `[key, value]` tuple, or `undefined`.
|
|
309
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;
|
|
310
1067
|
*/
|
|
311
1068
|
find(callbackfn: TreeMapEntryCallback<K, V, boolean, TreeMap<K, V>>, thisArg?: unknown): [K, V | undefined] | undefined {
|
|
312
1069
|
let index = 0;
|
|
@@ -322,6 +1079,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
322
1079
|
/**
|
|
323
1080
|
* Materialize the map into an array of `[key, value]` tuples.
|
|
324
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']];
|
|
325
1124
|
*/
|
|
326
1125
|
toArray(): Array<[K, V | undefined]> {
|
|
327
1126
|
return [...this];
|
|
@@ -330,6 +1129,48 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
330
1129
|
/**
|
|
331
1130
|
* Print a human-friendly representation.
|
|
332
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();
|
|
333
1174
|
*/
|
|
334
1175
|
print(): void {
|
|
335
1176
|
// Delegate to the underlying tree's visualization.
|
|
@@ -341,6 +1182,43 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
341
1182
|
|
|
342
1183
|
/**
|
|
343
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;
|
|
344
1222
|
*/
|
|
345
1223
|
first(): [K, V | undefined] | undefined {
|
|
346
1224
|
const k = this.#core.getLeftMost();
|
|
@@ -349,6 +1227,27 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
349
1227
|
|
|
350
1228
|
/**
|
|
351
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'];
|
|
352
1251
|
*/
|
|
353
1252
|
last(): [K, V | undefined] | undefined {
|
|
354
1253
|
const k = this.#core.getRightMost();
|
|
@@ -357,6 +1256,29 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
357
1256
|
|
|
358
1257
|
/**
|
|
359
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;
|
|
360
1282
|
*/
|
|
361
1283
|
pollFirst(): [K, V | undefined] | undefined {
|
|
362
1284
|
const entry = this.first();
|
|
@@ -367,6 +1289,29 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
367
1289
|
|
|
368
1290
|
/**
|
|
369
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'];
|
|
370
1315
|
*/
|
|
371
1316
|
pollLast(): [K, V | undefined] | undefined {
|
|
372
1317
|
const entry = this.last();
|
|
@@ -377,6 +1322,75 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
377
1322
|
|
|
378
1323
|
/**
|
|
379
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'];
|
|
380
1394
|
*/
|
|
381
1395
|
ceiling(key: K): [K, V | undefined] | undefined {
|
|
382
1396
|
this._validateKey(key);
|
|
@@ -386,6 +1400,59 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
386
1400
|
|
|
387
1401
|
/**
|
|
388
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;
|
|
389
1456
|
*/
|
|
390
1457
|
floor(key: K): [K, V | undefined] | undefined {
|
|
391
1458
|
this._validateKey(key);
|
|
@@ -395,6 +1462,59 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
395
1462
|
|
|
396
1463
|
/**
|
|
397
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;
|
|
398
1518
|
*/
|
|
399
1519
|
higher(key: K): [K, V | undefined] | undefined {
|
|
400
1520
|
this._validateKey(key);
|
|
@@ -404,6 +1524,57 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
404
1524
|
|
|
405
1525
|
/**
|
|
406
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;
|
|
407
1578
|
*/
|
|
408
1579
|
lower(key: K): [K, V | undefined] | undefined {
|
|
409
1580
|
this._validateKey(key);
|
|
@@ -416,6 +1587,74 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
416
1587
|
*
|
|
417
1588
|
* @param range `[low, high]`
|
|
418
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;
|
|
419
1658
|
*/
|
|
420
1659
|
rangeSearch(range: [K, K], options: TreeMapRangeOptions = {}): Array<[K, V | undefined]> {
|
|
421
1660
|
const { lowInclusive = true, highInclusive = true } = options;
|
|
@@ -428,7 +1667,7 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
428
1667
|
const cmp = this.#core.comparator;
|
|
429
1668
|
|
|
430
1669
|
for (const k of keys) {
|
|
431
|
-
if (k === undefined) continue;
|
|
1670
|
+
/* istanbul ignore next -- defensive: tree keys are never undefined */ if (k === undefined) continue;
|
|
432
1671
|
if (!lowInclusive && cmp(k, low) === 0) continue;
|
|
433
1672
|
if (!highInclusive && cmp(k, high) === 0) continue;
|
|
434
1673
|
out.push(this._entryFromKey(k));
|
|
@@ -440,11 +1679,51 @@ export class TreeMap<K = any, V = any, R = [K, V]> implements Iterable<[K, V | u
|
|
|
440
1679
|
/**
|
|
441
1680
|
* Creates a shallow clone of this map.
|
|
442
1681
|
* @remarks Time O(n log n), Space O(n)
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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;
|
|
448
1727
|
*/
|
|
449
1728
|
clone(): TreeMap<K, V> {
|
|
450
1729
|
return new TreeMap<K, V>(this, {
|