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
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import type { Comparator } from '../../types';
|
|
11
11
|
import type { TreeSetElementCallback, TreeSetOptions, TreeSetRangeOptions, TreeSetReduceCallback } from '../../types';
|
|
12
|
+
import { ERR } from '../../common';
|
|
12
13
|
import { RedBlackTree } from './red-black-tree';
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -16,6 +17,11 @@ import { RedBlackTree } from './red-black-tree';
|
|
|
16
17
|
*
|
|
17
18
|
* - Iteration order is ascending by key.
|
|
18
19
|
* - No node exposure: all APIs use keys only.
|
|
20
|
+
* @example
|
|
21
|
+
* // Set multiple key-value pairs
|
|
22
|
+
* const ts = new TreeSet<number, string>();
|
|
23
|
+
* ts.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
24
|
+
* console.log(ts.size); // 3;
|
|
19
25
|
*/
|
|
20
26
|
export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
21
27
|
readonly #core: RedBlackTree<K, undefined>;
|
|
@@ -66,27 +72,26 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
66
72
|
return (a: K, b: K): number => {
|
|
67
73
|
// numbers
|
|
68
74
|
if (typeof a === 'number' && typeof b === 'number') {
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
/* istanbul ignore next -- _validateKey prevents NaN from entering the tree */
|
|
76
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN('TreeSet'));
|
|
71
77
|
const aa = Object.is(a, -0) ? 0 : a;
|
|
72
78
|
const bb = Object.is(b, -0) ? 0 : b;
|
|
73
79
|
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
74
80
|
}
|
|
75
81
|
|
|
76
|
-
// strings
|
|
77
82
|
if (typeof a === 'string' && typeof b === 'string') {
|
|
78
83
|
return a > b ? 1 : a < b ? -1 : 0;
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
// Date
|
|
82
86
|
if (a instanceof Date && b instanceof Date) {
|
|
83
87
|
const ta = a.getTime();
|
|
84
88
|
const tb = b.getTime();
|
|
85
|
-
|
|
89
|
+
/* istanbul ignore next -- _validateKey prevents invalid Date from entering the tree */
|
|
90
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate('TreeSet'));
|
|
86
91
|
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
87
92
|
}
|
|
88
93
|
|
|
89
|
-
throw new TypeError('TreeSet
|
|
94
|
+
throw new TypeError(ERR.comparatorRequired('TreeSet'));
|
|
90
95
|
};
|
|
91
96
|
}
|
|
92
97
|
|
|
@@ -99,6 +104,47 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
99
104
|
|
|
100
105
|
/**
|
|
101
106
|
* Whether the set is empty.
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
* @example
|
|
146
|
+
* // Check empty
|
|
147
|
+
* console.log(new TreeSet().isEmpty()); // true;
|
|
102
148
|
*/
|
|
103
149
|
isEmpty(): boolean {
|
|
104
150
|
return this.size === 0;
|
|
@@ -108,24 +154,76 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
108
154
|
if (!this.#isDefaultComparator) return;
|
|
109
155
|
|
|
110
156
|
if (typeof key === 'number') {
|
|
111
|
-
if (Number.isNaN(key)) throw new TypeError('TreeSet
|
|
157
|
+
if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN('TreeSet'));
|
|
112
158
|
return;
|
|
113
159
|
}
|
|
114
160
|
|
|
115
161
|
if (typeof key === 'string') return;
|
|
116
162
|
|
|
117
163
|
if (key instanceof Date) {
|
|
118
|
-
if (Number.isNaN(key.getTime())) throw new TypeError('TreeSet
|
|
164
|
+
if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate('TreeSet'));
|
|
119
165
|
return;
|
|
120
166
|
}
|
|
121
167
|
|
|
122
168
|
// Other key types should have provided a comparator, so reaching here means misuse.
|
|
123
|
-
throw new TypeError('TreeSet
|
|
169
|
+
throw new TypeError(ERR.comparatorRequired('TreeSet'));
|
|
124
170
|
}
|
|
125
171
|
|
|
126
172
|
/**
|
|
127
173
|
* Add a key to the set (no-op if already present).
|
|
128
174
|
* @remarks Expected time O(log n)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
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
|
+
* @example
|
|
217
|
+
* // Unique tags with sorted order
|
|
218
|
+
* const tags = new TreeSet<string>(['javascript', 'typescript', 'react', 'typescript', 'node']);
|
|
219
|
+
*
|
|
220
|
+
* // Duplicates removed, sorted alphabetically
|
|
221
|
+
* console.log([...tags]); // ['javascript', 'node', 'react', 'typescript'];
|
|
222
|
+
* console.log(tags.size); // 4;
|
|
223
|
+
*
|
|
224
|
+
* tags.add('angular');
|
|
225
|
+
* console.log(tags.first()); // 'angular';
|
|
226
|
+
* console.log(tags.last()); // 'typescript';
|
|
129
227
|
*/
|
|
130
228
|
add(key: K): this {
|
|
131
229
|
this._validateKey(key);
|
|
@@ -137,6 +235,61 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
137
235
|
/**
|
|
138
236
|
* Test whether a key exists.
|
|
139
237
|
* @remarks Expected time O(log n)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
* @example
|
|
288
|
+
* // Checking membership in a sorted collection
|
|
289
|
+
* const allowed = new TreeSet<string>(['admin', 'editor', 'viewer']);
|
|
290
|
+
*
|
|
291
|
+
* console.log(allowed.has('admin')); // true;
|
|
292
|
+
* console.log(allowed.has('guest')); // false;
|
|
140
293
|
*/
|
|
141
294
|
has(key: K): boolean {
|
|
142
295
|
this._validateKey(key);
|
|
@@ -147,6 +300,62 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
147
300
|
* Delete a key.
|
|
148
301
|
* @returns `true` if the key existed; otherwise `false`.
|
|
149
302
|
* @remarks Expected time O(log n)
|
|
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
|
+
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
* @example
|
|
353
|
+
* // Removing elements while maintaining order
|
|
354
|
+
* const nums = new TreeSet<number>([1, 3, 5, 7, 9]);
|
|
355
|
+
*
|
|
356
|
+
* console.log(nums.delete(5)); // true;
|
|
357
|
+
* console.log(nums.delete(5)); // false; // already gone
|
|
358
|
+
* console.log([...nums]); // [1, 3, 7, 9];
|
|
150
359
|
*/
|
|
151
360
|
delete(key: K): boolean {
|
|
152
361
|
this._validateKey(key);
|
|
@@ -156,6 +365,49 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
156
365
|
|
|
157
366
|
/**
|
|
158
367
|
* Remove all keys.
|
|
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
|
+
|
|
405
|
+
|
|
406
|
+
* @example
|
|
407
|
+
* // Remove all
|
|
408
|
+
* const ts = new TreeSet<number>([1, 2]);
|
|
409
|
+
* ts.clear();
|
|
410
|
+
* console.log(ts.isEmpty()); // true;
|
|
159
411
|
*/
|
|
160
412
|
clear(): void {
|
|
161
413
|
this.#core.clear();
|
|
@@ -163,6 +415,48 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
163
415
|
|
|
164
416
|
/**
|
|
165
417
|
* Iterate over keys in ascending order.
|
|
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
|
+
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
* @example
|
|
457
|
+
* // Get sorted keys
|
|
458
|
+
* const ts = new TreeSet<number>([30, 10, 20]);
|
|
459
|
+
* console.log([...ts.keys()]); // [10, 20, 30];
|
|
166
460
|
*/
|
|
167
461
|
keys(): IterableIterator<K> {
|
|
168
462
|
return this.#core.keys();
|
|
@@ -172,6 +466,48 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
172
466
|
* Iterate over values in ascending order.
|
|
173
467
|
*
|
|
174
468
|
* Note: for Set-like containers, `values()` is the same as `keys()`.
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
|
|
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
|
+
* @example
|
|
508
|
+
* // Get values (same as keys for Set)
|
|
509
|
+
* const ts = new TreeSet<number>([2, 1, 3]);
|
|
510
|
+
* console.log([...ts.values()]); // [1, 2, 3];
|
|
175
511
|
*/
|
|
176
512
|
values(): IterableIterator<K> {
|
|
177
513
|
return this.keys();
|
|
@@ -181,6 +517,48 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
181
517
|
* Iterate over `[value, value]` pairs (native Set convention).
|
|
182
518
|
*
|
|
183
519
|
* Note: TreeSet stores only keys internally; `[k, k]` is created on-the-fly during iteration.
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
* @example
|
|
559
|
+
* // Iterate entries
|
|
560
|
+
* const ts = new TreeSet<number>([3, 1, 2]);
|
|
561
|
+
* console.log([...ts.entries()].map(([k]) => k)); // [1, 2, 3];
|
|
184
562
|
*/
|
|
185
563
|
*entries(): IterableIterator<[K, K]> {
|
|
186
564
|
for (const k of this.keys()) yield [k, k];
|
|
@@ -194,6 +572,50 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
194
572
|
* Visit each value in ascending order.
|
|
195
573
|
*
|
|
196
574
|
* Callback follows native Set convention: `(value, value2, set)`.
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
* @example
|
|
614
|
+
* // Execute for each
|
|
615
|
+
* const ts = new TreeSet<number>([3, 1, 2]);
|
|
616
|
+
* const keys: number[] = [];
|
|
617
|
+
* ts.forEach(k => keys.push(k));
|
|
618
|
+
* console.log(keys); // [1, 2, 3];
|
|
197
619
|
*/
|
|
198
620
|
forEach(cb: (value: K, value2: K, set: TreeSet<K>) => void, thisArg?: any): void {
|
|
199
621
|
for (const k of this) cb.call(thisArg, k, k, this);
|
|
@@ -204,6 +626,49 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
204
626
|
*
|
|
205
627
|
* This mirrors `RedBlackTree.map`: mapping produces a new ordered container.
|
|
206
628
|
* @remarks Time O(n log n) expected, Space O(n)
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
* @example
|
|
668
|
+
* // Transform
|
|
669
|
+
* const ts = new TreeSet<number>([1, 2, 3]);
|
|
670
|
+
* const doubled = ts.map(k => k * 2);
|
|
671
|
+
* console.log([...doubled]); // [2, 4, 6];
|
|
207
672
|
*/
|
|
208
673
|
map<MK>(
|
|
209
674
|
callbackfn: TreeSetElementCallback<K, MK, TreeSet<K>>,
|
|
@@ -224,6 +689,49 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
224
689
|
/**
|
|
225
690
|
* Create a new TreeSet containing only values that satisfy the predicate.
|
|
226
691
|
* @remarks Time O(n log n) expected, Space O(n)
|
|
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
|
+
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
* @example
|
|
731
|
+
* // Filter
|
|
732
|
+
* const ts = new TreeSet<number>([1, 2, 3, 4, 5]);
|
|
733
|
+
* const evens = ts.filter(k => k % 2 === 0);
|
|
734
|
+
* console.log([...evens]); // [2, 4];
|
|
227
735
|
*/
|
|
228
736
|
filter(callbackfn: TreeSetElementCallback<K, boolean, TreeSet<K>>, thisArg?: unknown): TreeSet<K> {
|
|
229
737
|
const out = new TreeSet<K>([], { comparator: this.#userComparator });
|
|
@@ -240,6 +748,49 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
240
748
|
/**
|
|
241
749
|
* Reduce values into a single accumulator.
|
|
242
750
|
* @remarks Time O(n), Space O(1)
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
* @example
|
|
790
|
+
* // Aggregate
|
|
791
|
+
* const ts = new TreeSet<number>([1, 2, 3]);
|
|
792
|
+
* const sum = ts.reduce((acc, k) => acc + k, 0);
|
|
793
|
+
* console.log(sum); // 6;
|
|
243
794
|
*/
|
|
244
795
|
reduce<A>(callbackfn: TreeSetReduceCallback<K, A, TreeSet<K>>, initialValue: A): A {
|
|
245
796
|
let acc = initialValue;
|
|
@@ -251,6 +802,46 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
251
802
|
/**
|
|
252
803
|
* Test whether all values satisfy a predicate.
|
|
253
804
|
* @remarks Time O(n), Space O(1)
|
|
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
|
+
* @example
|
|
842
|
+
* // Test all
|
|
843
|
+
* const ts = new TreeSet<number>([2, 4, 6]);
|
|
844
|
+
* console.log(ts.every(k => k > 0)); // true;
|
|
254
845
|
*/
|
|
255
846
|
every(callbackfn: TreeSetElementCallback<K, boolean, TreeSet<K>>, thisArg?: unknown): boolean {
|
|
256
847
|
let index = 0;
|
|
@@ -266,6 +857,46 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
266
857
|
/**
|
|
267
858
|
* Test whether any value satisfies a predicate.
|
|
268
859
|
* @remarks Time O(n), Space O(1)
|
|
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
|
+
* @example
|
|
897
|
+
* // Test any
|
|
898
|
+
* const ts = new TreeSet<number>([1, 3, 5]);
|
|
899
|
+
* console.log(ts.some(k => k === 3)); // true;
|
|
269
900
|
*/
|
|
270
901
|
some(callbackfn: TreeSetElementCallback<K, boolean, TreeSet<K>>, thisArg?: unknown): boolean {
|
|
271
902
|
let index = 0;
|
|
@@ -281,6 +912,47 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
281
912
|
/**
|
|
282
913
|
* Find the first value that satisfies a predicate.
|
|
283
914
|
* @remarks Time O(n), Space O(1)
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
* @example
|
|
952
|
+
* // Find entry
|
|
953
|
+
* const ts = new TreeSet<number>([1, 2, 3]);
|
|
954
|
+
* const found = ts.find(k => k === 2);
|
|
955
|
+
* console.log(found); // 2;
|
|
284
956
|
*/
|
|
285
957
|
find(callbackfn: TreeSetElementCallback<K, boolean, TreeSet<K>>, thisArg?: unknown): K | undefined {
|
|
286
958
|
let index = 0;
|
|
@@ -296,6 +968,48 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
296
968
|
/**
|
|
297
969
|
* Materialize the set into an array of keys.
|
|
298
970
|
* @remarks Time O(n), Space O(n)
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
* @example
|
|
1010
|
+
* // Convert to array
|
|
1011
|
+
* const ts = new TreeSet<number>([3, 1, 2]);
|
|
1012
|
+
* console.log(ts.toArray()); // [1, 2, 3];
|
|
299
1013
|
*/
|
|
300
1014
|
toArray(): K[] {
|
|
301
1015
|
return [...this];
|
|
@@ -304,6 +1018,48 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
304
1018
|
/**
|
|
305
1019
|
* Print a human-friendly representation.
|
|
306
1020
|
* @remarks Time O(n), Space O(n)
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
* @example
|
|
1060
|
+
* // Display tree
|
|
1061
|
+
* const ts = new TreeSet<number>([1, 2, 3]);
|
|
1062
|
+
* expect(() => ts.print()).not.toThrow();
|
|
307
1063
|
*/
|
|
308
1064
|
print(): void {
|
|
309
1065
|
// Delegate to the underlying tree's visualization.
|
|
@@ -314,6 +1070,44 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
314
1070
|
|
|
315
1071
|
/**
|
|
316
1072
|
* Smallest key in the set.
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
* @example
|
|
1085
|
+
* // Student grade ranking with custom comparator
|
|
1086
|
+
* interface Student {
|
|
1087
|
+
* name: string;
|
|
1088
|
+
* gpa: number;
|
|
1089
|
+
* }
|
|
1090
|
+
*
|
|
1091
|
+
* const ranking = new TreeSet<Student>(
|
|
1092
|
+
* [
|
|
1093
|
+
* { name: 'Alice', gpa: 3.8 },
|
|
1094
|
+
* { name: 'Bob', gpa: 3.5 },
|
|
1095
|
+
* { name: 'Charlie', gpa: 3.9 },
|
|
1096
|
+
* { name: 'Diana', gpa: 3.5 }
|
|
1097
|
+
* ],
|
|
1098
|
+
* { comparator: (a, b) => b.gpa - a.gpa || a.name.localeCompare(b.name) }
|
|
1099
|
+
* );
|
|
1100
|
+
*
|
|
1101
|
+
* // Sorted by GPA descending, then name ascending
|
|
1102
|
+
* const names = [...ranking].map(s => s.name);
|
|
1103
|
+
* console.log(names); // ['Charlie', 'Alice', 'Bob', 'Diana'];
|
|
1104
|
+
*
|
|
1105
|
+
* // Top student
|
|
1106
|
+
* console.log(ranking.first()?.name); // 'Charlie';
|
|
1107
|
+
*
|
|
1108
|
+
* // Filter students with GPA >= 3.8
|
|
1109
|
+
* const honors = ranking.filter(s => s.gpa >= 3.8);
|
|
1110
|
+
* console.log(honors.toArray().map(s => s.name)); // ['Charlie', 'Alice'];
|
|
317
1111
|
*/
|
|
318
1112
|
first(): K | undefined {
|
|
319
1113
|
return this.#core.getLeftMost();
|
|
@@ -321,6 +1115,22 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
321
1115
|
|
|
322
1116
|
/**
|
|
323
1117
|
* Largest key in the set.
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
|
|
1129
|
+
* @example
|
|
1130
|
+
* // Get the maximum element
|
|
1131
|
+
* const temps = new TreeSet<number>([18, 22, 15, 30, 25]);
|
|
1132
|
+
* console.log(temps.last()); // 30;
|
|
1133
|
+
* console.log(temps.first()); // 15;
|
|
324
1134
|
*/
|
|
325
1135
|
last(): K | undefined {
|
|
326
1136
|
return this.#core.getRightMost();
|
|
@@ -328,6 +1138,24 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
328
1138
|
|
|
329
1139
|
/**
|
|
330
1140
|
* Remove and return the smallest key.
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
* @example
|
|
1153
|
+
* // Remove and return minimum
|
|
1154
|
+
* const queue = new TreeSet<number>([5, 1, 8, 3]);
|
|
1155
|
+
*
|
|
1156
|
+
* console.log(queue.pollFirst()); // 1;
|
|
1157
|
+
* console.log(queue.pollFirst()); // 3;
|
|
1158
|
+
* console.log(queue.size); // 2;
|
|
331
1159
|
*/
|
|
332
1160
|
pollFirst(): K | undefined {
|
|
333
1161
|
const k = this.first();
|
|
@@ -338,6 +1166,23 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
338
1166
|
|
|
339
1167
|
/**
|
|
340
1168
|
* Remove and return the largest key.
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
* @example
|
|
1181
|
+
* // Remove and return maximum
|
|
1182
|
+
* const stack = new TreeSet<number>([10, 20, 30]);
|
|
1183
|
+
*
|
|
1184
|
+
* console.log(stack.pollLast()); // 30;
|
|
1185
|
+
* console.log(stack.size); // 2;
|
|
341
1186
|
*/
|
|
342
1187
|
pollLast(): K | undefined {
|
|
343
1188
|
const k = this.last();
|
|
@@ -348,6 +1193,60 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
348
1193
|
|
|
349
1194
|
/**
|
|
350
1195
|
* Smallest key that is >= the given key.
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
* @example
|
|
1235
|
+
* // Finding nearest available time slot
|
|
1236
|
+
* // Available appointment times (minutes from midnight)
|
|
1237
|
+
* const slots = new TreeSet<number>([540, 600, 660, 720, 840, 900]);
|
|
1238
|
+
*
|
|
1239
|
+
* // Customer wants something around 10:30 (630 min)
|
|
1240
|
+
* const nearest = slots.ceiling(630);
|
|
1241
|
+
* console.log(nearest); // 660; // 11:00 AM
|
|
1242
|
+
*
|
|
1243
|
+
* // What's the latest slot before 2:00 PM (840)?
|
|
1244
|
+
* const before2pm = slots.lower(840);
|
|
1245
|
+
* console.log(before2pm); // 720; // 12:00 PM
|
|
1246
|
+
*
|
|
1247
|
+
* // Book the 11:00 slot
|
|
1248
|
+
* slots.delete(660);
|
|
1249
|
+
* console.log(slots.ceiling(630)); // 720;
|
|
351
1250
|
*/
|
|
352
1251
|
ceiling(key: K): K | undefined {
|
|
353
1252
|
this._validateKey(key);
|
|
@@ -356,6 +1255,52 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
356
1255
|
|
|
357
1256
|
/**
|
|
358
1257
|
* Largest key that is <= the given key.
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
|
|
1263
|
+
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
|
|
1276
|
+
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
|
|
1289
|
+
|
|
1290
|
+
|
|
1291
|
+
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
* @example
|
|
1297
|
+
* // Largest element ≤ target
|
|
1298
|
+
* const breakpoints = new TreeSet<number>([320, 768, 1024, 1280, 1920]);
|
|
1299
|
+
*
|
|
1300
|
+
* // Current width is 800 → which breakpoint applies?
|
|
1301
|
+
* console.log(breakpoints.floor(800)); // 768;
|
|
1302
|
+
* console.log(breakpoints.floor(1024)); // 1024; // exact match
|
|
1303
|
+
* console.log(breakpoints.floor(100)); // undefined;
|
|
359
1304
|
*/
|
|
360
1305
|
floor(key: K): K | undefined {
|
|
361
1306
|
this._validateKey(key);
|
|
@@ -364,6 +1309,50 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
364
1309
|
|
|
365
1310
|
/**
|
|
366
1311
|
* Smallest key that is > the given key.
|
|
1312
|
+
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
|
|
1316
|
+
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
|
|
1345
|
+
|
|
1346
|
+
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
|
|
1350
|
+
* @example
|
|
1351
|
+
* // Smallest element strictly > target
|
|
1352
|
+
* const levels = new TreeSet<number>([1, 5, 10, 25, 50, 100]);
|
|
1353
|
+
*
|
|
1354
|
+
* console.log(levels.higher(10)); // 25;
|
|
1355
|
+
* console.log(levels.higher(100)); // undefined;
|
|
367
1356
|
*/
|
|
368
1357
|
higher(key: K): K | undefined {
|
|
369
1358
|
this._validateKey(key);
|
|
@@ -372,6 +1361,50 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
372
1361
|
|
|
373
1362
|
/**
|
|
374
1363
|
* Largest key that is < the given key.
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
|
|
1380
|
+
|
|
1381
|
+
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
|
|
1397
|
+
|
|
1398
|
+
|
|
1399
|
+
|
|
1400
|
+
|
|
1401
|
+
|
|
1402
|
+
* @example
|
|
1403
|
+
* // Largest element strictly < target
|
|
1404
|
+
* const tiers = new TreeSet<number>([100, 200, 500, 1000]);
|
|
1405
|
+
*
|
|
1406
|
+
* console.log(tiers.lower(500)); // 200;
|
|
1407
|
+
* console.log(tiers.lower(100)); // undefined;
|
|
375
1408
|
*/
|
|
376
1409
|
lower(key: K): K | undefined {
|
|
377
1410
|
this._validateKey(key);
|
|
@@ -383,6 +1416,61 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
383
1416
|
*
|
|
384
1417
|
* @param range `[low, high]`
|
|
385
1418
|
* @param options Inclusive/exclusive bounds (defaults to inclusive).
|
|
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
|
+
* @example
|
|
1458
|
+
* // IP address blocklist with range checking
|
|
1459
|
+
* // Simplified: use numeric IP representation
|
|
1460
|
+
* const blocklist = new TreeSet<number>([
|
|
1461
|
+
* 167772160, // 10.0.0.0
|
|
1462
|
+
* 167772416, // 10.0.1.0
|
|
1463
|
+
* 167772672, // 10.0.2.0
|
|
1464
|
+
* 167773184 // 10.0.4.0
|
|
1465
|
+
* ]);
|
|
1466
|
+
*
|
|
1467
|
+
* // Check if any blocked IP is in range 10.0.1.0 - 10.0.3.0
|
|
1468
|
+
* const inRange = blocklist.rangeSearch([167772416, 167772928]);
|
|
1469
|
+
* console.log(inRange); // [167772416, 167772672];
|
|
1470
|
+
*
|
|
1471
|
+
* // Quick membership check
|
|
1472
|
+
* console.log(blocklist.has(167772416)); // true;
|
|
1473
|
+
* console.log(blocklist.has(167772800)); // false;
|
|
386
1474
|
*/
|
|
387
1475
|
rangeSearch(range: [K, K], options: TreeSetRangeOptions = {}): K[] {
|
|
388
1476
|
const { lowInclusive = true, highInclusive = true } = options;
|
|
@@ -396,7 +1484,7 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
396
1484
|
const cmp = this.#core.comparator;
|
|
397
1485
|
|
|
398
1486
|
for (const k of keys) {
|
|
399
|
-
if (k === undefined) continue;
|
|
1487
|
+
/* istanbul ignore next -- defensive: tree keys are never undefined */ if (k === undefined) continue;
|
|
400
1488
|
if (!lowInclusive && cmp(k, low) === 0) continue;
|
|
401
1489
|
if (!highInclusive && cmp(k, high) === 0) continue;
|
|
402
1490
|
out.push(k);
|
|
@@ -408,11 +1496,51 @@ export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
|
408
1496
|
/**
|
|
409
1497
|
* Creates a shallow clone of this set.
|
|
410
1498
|
* @remarks Time O(n log n), Space O(n)
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
1499
|
+
|
|
1500
|
+
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
|
|
1504
|
+
|
|
1505
|
+
|
|
1506
|
+
|
|
1507
|
+
|
|
1508
|
+
|
|
1509
|
+
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
|
|
1519
|
+
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
|
|
1523
|
+
|
|
1524
|
+
|
|
1525
|
+
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
|
|
1529
|
+
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
|
|
1534
|
+
|
|
1535
|
+
|
|
1536
|
+
|
|
1537
|
+
|
|
1538
|
+
* @example
|
|
1539
|
+
* // Deep clone
|
|
1540
|
+
* const ts = new TreeSet<number>([1, 2, 3]);
|
|
1541
|
+
* const copy = ts.clone();
|
|
1542
|
+
* copy.delete(1);
|
|
1543
|
+
* console.log(ts.has(1)); // true;
|
|
416
1544
|
*/
|
|
417
1545
|
clone(): TreeSet<K> {
|
|
418
1546
|
return new TreeSet<K>(this, {
|