max-priority-queue-typed 2.3.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/data-structures/base/linear-base.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/bst.d.ts +2 -1
- package/dist/types/data-structures/binary-tree/index.d.ts +3 -3
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +150 -20
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +188 -0
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +238 -147
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +270 -0
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +181 -0
- package/dist/types/interfaces/binary-tree.d.ts +2 -2
- package/dist/types/types/data-structures/binary-tree/index.d.ts +3 -3
- package/dist/types/types/data-structures/binary-tree/tree-map.d.ts +33 -0
- package/dist/types/types/data-structures/binary-tree/tree-multi-set.d.ts +16 -0
- package/dist/types/types/data-structures/binary-tree/tree-set.d.ts +33 -0
- package/package.json +2 -2
- package/src/data-structures/base/linear-base.ts +2 -12
- package/src/data-structures/binary-tree/avl-tree.ts +1 -1
- package/src/data-structures/binary-tree/binary-tree.ts +45 -21
- package/src/data-structures/binary-tree/bst.ts +85 -10
- package/src/data-structures/binary-tree/index.ts +3 -3
- package/src/data-structures/binary-tree/red-black-tree.ts +568 -76
- package/src/data-structures/binary-tree/tree-map.ts +439 -0
- package/src/data-structures/binary-tree/tree-multi-map.ts +488 -325
- package/src/data-structures/binary-tree/tree-multi-set.ts +502 -0
- package/src/data-structures/binary-tree/tree-set.ts +407 -0
- package/src/data-structures/queue/deque.ts +10 -0
- package/src/interfaces/binary-tree.ts +2 -2
- package/src/types/data-structures/binary-tree/index.ts +3 -3
- package/src/types/data-structures/binary-tree/tree-map.ts +45 -0
- package/src/types/data-structures/binary-tree/tree-multi-set.ts +19 -0
- package/src/types/data-structures/binary-tree/tree-set.ts +39 -0
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +0 -236
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +0 -197
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +0 -243
- package/dist/types/types/data-structures/binary-tree/avl-tree-counter.d.ts +0 -2
- package/dist/types/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +0 -2
- package/dist/types/types/data-structures/binary-tree/tree-counter.d.ts +0 -2
- package/src/data-structures/binary-tree/avl-tree-counter.ts +0 -539
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +0 -438
- package/src/data-structures/binary-tree/tree-counter.ts +0 -575
- package/src/types/data-structures/binary-tree/avl-tree-counter.ts +0 -3
- package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +0 -3
- package/src/types/data-structures/binary-tree/tree-counter.ts +0 -3
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TreeSet (ordered set) — a restricted, native-like API backed by RedBlackTree.
|
|
3
|
+
*
|
|
4
|
+
* Design goals:
|
|
5
|
+
* - No node exposure (no node inputs/outputs)
|
|
6
|
+
* - Native Set-like surface + Java NavigableSet-like helpers
|
|
7
|
+
* - Strict default comparator (number/string/Date), otherwise require comparator
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Comparator } from '../../types';
|
|
11
|
+
import type { TreeSetElementCallback, TreeSetOptions, TreeSetRangeOptions, TreeSetReduceCallback } from '../../types';
|
|
12
|
+
import { RedBlackTree } from './red-black-tree';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* An ordered Set backed by a red-black tree.
|
|
16
|
+
*
|
|
17
|
+
* - Iteration order is ascending by key.
|
|
18
|
+
* - No node exposure: all APIs use keys only.
|
|
19
|
+
*/
|
|
20
|
+
export class TreeSet<K = any, R = K> implements Iterable<K> {
|
|
21
|
+
readonly #core: RedBlackTree<K, undefined>;
|
|
22
|
+
readonly #isDefaultComparator: boolean;
|
|
23
|
+
readonly #userComparator?: Comparator<K>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create a TreeSet from an iterable of keys or raw elements.
|
|
27
|
+
*
|
|
28
|
+
* @param elements - Iterable of keys, or raw elements if `toElementFn` is provided.
|
|
29
|
+
* @param options - Configuration options including optional `toElementFn` to transform raw elements.
|
|
30
|
+
* @throws {TypeError} When using the default comparator and encountering unsupported key types,
|
|
31
|
+
* or invalid keys (e.g. `NaN`, invalid `Date`).
|
|
32
|
+
* @example
|
|
33
|
+
* // Standard usage with keys
|
|
34
|
+
* const set = new TreeSet([3, 1, 2]);
|
|
35
|
+
*
|
|
36
|
+
* // Using toElementFn to transform raw objects
|
|
37
|
+
* const users = [{ id: 3, name: 'Alice' }, { id: 1, name: 'Bob' }];
|
|
38
|
+
* const set = new TreeSet<number, User>(users, { toElementFn: u => u.id });
|
|
39
|
+
*/
|
|
40
|
+
constructor(elements: Iterable<R> | Iterable<K> = [], options: TreeSetOptions<K, R> = {}) {
|
|
41
|
+
this.#userComparator = options.comparator;
|
|
42
|
+
const toElementFn = options.toElementFn;
|
|
43
|
+
const comparator = options.comparator ?? TreeSet.createDefaultComparator<K>();
|
|
44
|
+
this.#isDefaultComparator = options.comparator === undefined;
|
|
45
|
+
|
|
46
|
+
// RedBlackTree expects an iterable of keys/entries/nodes/raws; for TreeSet we only accept keys.
|
|
47
|
+
this.#core = new RedBlackTree<K, undefined>([], { comparator, isMapMode: options.isMapMode });
|
|
48
|
+
|
|
49
|
+
for (const item of elements) {
|
|
50
|
+
const k = toElementFn ? toElementFn(item as R) : item as K;
|
|
51
|
+
this.add(k);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Create the strict default comparator.
|
|
57
|
+
*
|
|
58
|
+
* Supports:
|
|
59
|
+
* - `number` (rejects `NaN`; treats `-0` and `0` as equal)
|
|
60
|
+
* - `string`
|
|
61
|
+
* - `Date` (orders by `getTime()`, rejects invalid dates)
|
|
62
|
+
*
|
|
63
|
+
* For other key types, a custom comparator must be provided.
|
|
64
|
+
*/
|
|
65
|
+
static createDefaultComparator<K>(): Comparator<K> {
|
|
66
|
+
return (a: K, b: K): number => {
|
|
67
|
+
// numbers
|
|
68
|
+
if (typeof a === 'number' && typeof b === 'number') {
|
|
69
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError('TreeSet: NaN is not a valid key');
|
|
70
|
+
// treat -0 and 0 as equal
|
|
71
|
+
const aa = Object.is(a, -0) ? 0 : a;
|
|
72
|
+
const bb = Object.is(b, -0) ? 0 : b;
|
|
73
|
+
return aa > bb ? 1 : aa < bb ? -1 : 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// strings
|
|
77
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
78
|
+
return a > b ? 1 : a < b ? -1 : 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Date
|
|
82
|
+
if (a instanceof Date && b instanceof Date) {
|
|
83
|
+
const ta = a.getTime();
|
|
84
|
+
const tb = b.getTime();
|
|
85
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError('TreeSet: invalid Date key');
|
|
86
|
+
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
throw new TypeError('TreeSet: comparator is required for non-number/non-string/non-Date keys');
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Number of elements in the set.
|
|
95
|
+
*/
|
|
96
|
+
get size(): number {
|
|
97
|
+
return this.#core.size;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Whether the set is empty.
|
|
102
|
+
*/
|
|
103
|
+
isEmpty(): boolean {
|
|
104
|
+
return this.size === 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private _validateKey(key: K): void {
|
|
108
|
+
if (!this.#isDefaultComparator) return;
|
|
109
|
+
|
|
110
|
+
if (typeof key === 'number') {
|
|
111
|
+
if (Number.isNaN(key)) throw new TypeError('TreeSet: NaN is not a valid key');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (typeof key === 'string') return;
|
|
116
|
+
|
|
117
|
+
if (key instanceof Date) {
|
|
118
|
+
if (Number.isNaN(key.getTime())) throw new TypeError('TreeSet: invalid Date key');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Other key types should have provided a comparator, so reaching here means misuse.
|
|
123
|
+
throw new TypeError('TreeSet: comparator is required for non-number/non-string/non-Date keys');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Add a key to the set (no-op if already present).
|
|
128
|
+
* @remarks Expected time O(log n)
|
|
129
|
+
*/
|
|
130
|
+
add(key: K): this {
|
|
131
|
+
this._validateKey(key);
|
|
132
|
+
// RBT.set returns boolean; Set.add returns this.
|
|
133
|
+
this.#core.set(key, undefined);
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Test whether a key exists.
|
|
139
|
+
* @remarks Expected time O(log n)
|
|
140
|
+
*/
|
|
141
|
+
has(key: K): boolean {
|
|
142
|
+
this._validateKey(key);
|
|
143
|
+
return this.#core.has(key);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Delete a key.
|
|
148
|
+
* @returns `true` if the key existed; otherwise `false`.
|
|
149
|
+
* @remarks Expected time O(log n)
|
|
150
|
+
*/
|
|
151
|
+
delete(key: K): boolean {
|
|
152
|
+
this._validateKey(key);
|
|
153
|
+
const res = this.#core.delete(key);
|
|
154
|
+
return Array.isArray(res) && res.length > 0 && !!res[0]?.deleted;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Remove all keys.
|
|
159
|
+
*/
|
|
160
|
+
clear(): void {
|
|
161
|
+
this.#core.clear();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Iterate over keys in ascending order.
|
|
166
|
+
*/
|
|
167
|
+
keys(): IterableIterator<K> {
|
|
168
|
+
return this.#core.keys();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Iterate over values in ascending order.
|
|
173
|
+
*
|
|
174
|
+
* Note: for Set-like containers, `values()` is the same as `keys()`.
|
|
175
|
+
*/
|
|
176
|
+
values(): IterableIterator<K> {
|
|
177
|
+
return this.keys();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Iterate over `[value, value]` pairs (native Set convention).
|
|
182
|
+
*
|
|
183
|
+
* Note: TreeSet stores only keys internally; `[k, k]` is created on-the-fly during iteration.
|
|
184
|
+
*/
|
|
185
|
+
*entries(): IterableIterator<[K, K]> {
|
|
186
|
+
for (const k of this.keys()) yield [k, k];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
[Symbol.iterator](): IterableIterator<K> {
|
|
190
|
+
return this.keys();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Visit each value in ascending order.
|
|
195
|
+
*
|
|
196
|
+
* Callback follows native Set convention: `(value, value2, set)`.
|
|
197
|
+
*/
|
|
198
|
+
forEach(cb: (value: K, value2: K, set: TreeSet<K>) => void, thisArg?: any): void {
|
|
199
|
+
for (const k of this) cb.call(thisArg, k, k, this);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Create a new TreeSet by mapping each value to a new key.
|
|
204
|
+
*
|
|
205
|
+
* This mirrors `RedBlackTree.map`: mapping produces a new ordered container.
|
|
206
|
+
* @remarks Time O(n log n) expected, Space O(n)
|
|
207
|
+
*/
|
|
208
|
+
map<MK>(
|
|
209
|
+
callbackfn: TreeSetElementCallback<K, MK, TreeSet<K>>,
|
|
210
|
+
options: Omit<TreeSetOptions<MK>, 'toElementFn'> & { comparator?: (a: MK, b: MK) => number } = {},
|
|
211
|
+
thisArg?: unknown
|
|
212
|
+
): TreeSet<MK> {
|
|
213
|
+
const out = new TreeSet<MK>([], options as TreeSetOptions<MK>);
|
|
214
|
+
let index = 0;
|
|
215
|
+
for (const v of this) {
|
|
216
|
+
const mk = thisArg === undefined
|
|
217
|
+
? callbackfn(v, index++, this)
|
|
218
|
+
: (callbackfn as (this: unknown, v: K, i: number, self: TreeSet<K>) => MK).call(thisArg, v, index++, this);
|
|
219
|
+
out.add(mk);
|
|
220
|
+
}
|
|
221
|
+
return out;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Create a new TreeSet containing only values that satisfy the predicate.
|
|
226
|
+
* @remarks Time O(n log n) expected, Space O(n)
|
|
227
|
+
*/
|
|
228
|
+
filter(callbackfn: TreeSetElementCallback<K, boolean, TreeSet<K>>, thisArg?: unknown): TreeSet<K> {
|
|
229
|
+
const out = new TreeSet<K>([], { comparator: this.#userComparator });
|
|
230
|
+
let index = 0;
|
|
231
|
+
for (const v of this) {
|
|
232
|
+
const ok = thisArg === undefined
|
|
233
|
+
? callbackfn(v, index++, this)
|
|
234
|
+
: (callbackfn as (this: unknown, v: K, i: number, self: TreeSet<K>) => boolean).call(thisArg, v, index++, this);
|
|
235
|
+
if (ok) out.add(v);
|
|
236
|
+
}
|
|
237
|
+
return out;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Reduce values into a single accumulator.
|
|
242
|
+
* @remarks Time O(n), Space O(1)
|
|
243
|
+
*/
|
|
244
|
+
reduce<A>(callbackfn: TreeSetReduceCallback<K, A, TreeSet<K>>, initialValue: A): A {
|
|
245
|
+
let acc = initialValue;
|
|
246
|
+
let index = 0;
|
|
247
|
+
for (const v of this) acc = callbackfn(acc, v, index++, this);
|
|
248
|
+
return acc;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Test whether all values satisfy a predicate.
|
|
253
|
+
* @remarks Time O(n), Space O(1)
|
|
254
|
+
*/
|
|
255
|
+
every(callbackfn: TreeSetElementCallback<K, boolean, TreeSet<K>>, thisArg?: unknown): boolean {
|
|
256
|
+
let index = 0;
|
|
257
|
+
for (const v of this) {
|
|
258
|
+
const ok = thisArg === undefined
|
|
259
|
+
? callbackfn(v, index++, this)
|
|
260
|
+
: (callbackfn as (this: unknown, v: K, i: number, self: TreeSet<K>) => boolean).call(thisArg, v, index++, this);
|
|
261
|
+
if (!ok) return false;
|
|
262
|
+
}
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Test whether any value satisfies a predicate.
|
|
268
|
+
* @remarks Time O(n), Space O(1)
|
|
269
|
+
*/
|
|
270
|
+
some(callbackfn: TreeSetElementCallback<K, boolean, TreeSet<K>>, thisArg?: unknown): boolean {
|
|
271
|
+
let index = 0;
|
|
272
|
+
for (const v of this) {
|
|
273
|
+
const ok = thisArg === undefined
|
|
274
|
+
? callbackfn(v, index++, this)
|
|
275
|
+
: (callbackfn as (this: unknown, v: K, i: number, self: TreeSet<K>) => boolean).call(thisArg, v, index++, this);
|
|
276
|
+
if (ok) return true;
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Find the first value that satisfies a predicate.
|
|
283
|
+
* @remarks Time O(n), Space O(1)
|
|
284
|
+
*/
|
|
285
|
+
find(callbackfn: TreeSetElementCallback<K, boolean, TreeSet<K>>, thisArg?: unknown): K | undefined {
|
|
286
|
+
let index = 0;
|
|
287
|
+
for (const v of this) {
|
|
288
|
+
const ok = thisArg === undefined
|
|
289
|
+
? callbackfn(v, index++, this)
|
|
290
|
+
: (callbackfn as (this: unknown, v: K, i: number, self: TreeSet<K>) => boolean).call(thisArg, v, index++, this);
|
|
291
|
+
if (ok) return v;
|
|
292
|
+
}
|
|
293
|
+
return undefined;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Materialize the set into an array of keys.
|
|
298
|
+
* @remarks Time O(n), Space O(n)
|
|
299
|
+
*/
|
|
300
|
+
toArray(): K[] {
|
|
301
|
+
return [...this];
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Print a human-friendly representation.
|
|
306
|
+
* @remarks Time O(n), Space O(n)
|
|
307
|
+
*/
|
|
308
|
+
print(): void {
|
|
309
|
+
// Delegate to the underlying tree's visualization.
|
|
310
|
+
this.#core.print();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Navigable operations
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Smallest key in the set.
|
|
317
|
+
*/
|
|
318
|
+
first(): K | undefined {
|
|
319
|
+
return this.#core.getLeftMost();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Largest key in the set.
|
|
324
|
+
*/
|
|
325
|
+
last(): K | undefined {
|
|
326
|
+
return this.#core.getRightMost();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Remove and return the smallest key.
|
|
331
|
+
*/
|
|
332
|
+
pollFirst(): K | undefined {
|
|
333
|
+
const k = this.first();
|
|
334
|
+
if (k === undefined) return undefined;
|
|
335
|
+
this.delete(k);
|
|
336
|
+
return k;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Remove and return the largest key.
|
|
341
|
+
*/
|
|
342
|
+
pollLast(): K | undefined {
|
|
343
|
+
const k = this.last();
|
|
344
|
+
if (k === undefined) return undefined;
|
|
345
|
+
this.delete(k);
|
|
346
|
+
return k;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Smallest key that is >= the given key.
|
|
351
|
+
*/
|
|
352
|
+
ceiling(key: K): K | undefined {
|
|
353
|
+
this._validateKey(key);
|
|
354
|
+
return this.#core.ceiling(key);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Largest key that is <= the given key.
|
|
359
|
+
*/
|
|
360
|
+
floor(key: K): K | undefined {
|
|
361
|
+
this._validateKey(key);
|
|
362
|
+
return this.#core.floor(key);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Smallest key that is > the given key.
|
|
367
|
+
*/
|
|
368
|
+
higher(key: K): K | undefined {
|
|
369
|
+
this._validateKey(key);
|
|
370
|
+
return this.#core.higher(key);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Largest key that is < the given key.
|
|
375
|
+
*/
|
|
376
|
+
lower(key: K): K | undefined {
|
|
377
|
+
this._validateKey(key);
|
|
378
|
+
return this.#core.lower(key);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Return all keys in a given range.
|
|
383
|
+
*
|
|
384
|
+
* @param range `[low, high]`
|
|
385
|
+
* @param options Inclusive/exclusive bounds (defaults to inclusive).
|
|
386
|
+
*/
|
|
387
|
+
rangeSearch(range: [K, K], options: TreeSetRangeOptions = {}): K[] {
|
|
388
|
+
const { lowInclusive = true, highInclusive = true } = options;
|
|
389
|
+
|
|
390
|
+
const [low, high] = range;
|
|
391
|
+
this._validateKey(low);
|
|
392
|
+
this._validateKey(high);
|
|
393
|
+
|
|
394
|
+
const keys = this.#core.rangeSearch([low, high]) as (K | undefined)[];
|
|
395
|
+
const out: K[] = [];
|
|
396
|
+
const cmp = this.#core.comparator;
|
|
397
|
+
|
|
398
|
+
for (const k of keys) {
|
|
399
|
+
if (k === undefined) continue;
|
|
400
|
+
if (!lowInclusive && cmp(k, low) === 0) continue;
|
|
401
|
+
if (!highInclusive && cmp(k, high) === 0) continue;
|
|
402
|
+
out.push(k);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return out;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
@@ -880,6 +880,16 @@ export class Deque<E = any, R = any> extends LinearBase<E, R> {
|
|
|
880
880
|
|
|
881
881
|
protected _setBucketSize(size: number): void {
|
|
882
882
|
this._bucketSize = size;
|
|
883
|
+
|
|
884
|
+
// When adjusting bucketSize on a freshly created empty deque (common in helpers like cut/splice/clone),
|
|
885
|
+
// we must also realign internal pointers/buckets to avoid `_getBucketAndPosition` producing out-of-range
|
|
886
|
+
// indices based on the previous bucketSize.
|
|
887
|
+
if (this._length === 0) {
|
|
888
|
+
this._buckets = [new Array(this._bucketSize)];
|
|
889
|
+
this._bucketCount = 1;
|
|
890
|
+
this._bucketFirst = this._bucketLast = 0;
|
|
891
|
+
this._firstInBucket = this._lastInBucket = this._bucketSize >> 1;
|
|
892
|
+
}
|
|
883
893
|
}
|
|
884
894
|
|
|
885
895
|
/**
|
|
@@ -27,7 +27,7 @@ export interface IBinaryTree<K = any, V = any, R = any> {
|
|
|
27
27
|
iterationType: IterationType;
|
|
28
28
|
// Extra public state/getters implemented by BinaryTree (useful to callers)
|
|
29
29
|
readonly NIL: BinaryTreeNode<K, V>;
|
|
30
|
-
readonly store: Map<K, V
|
|
30
|
+
readonly store: Map<K, BinaryTreeNode<K, V>>;
|
|
31
31
|
readonly toEntryFn?: ToEntryFn<K, V, R>;
|
|
32
32
|
readonly isDuplicate: boolean;
|
|
33
33
|
|
|
@@ -50,7 +50,7 @@ export interface IBinaryTree<K = any, V = any, R = any> {
|
|
|
50
50
|
|
|
51
51
|
// Accept BTNRep, predicate, or raw R for deletion
|
|
52
52
|
delete(
|
|
53
|
-
keyNodeEntryRawOrPredicate:
|
|
53
|
+
keyNodeEntryRawOrPredicate: BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
|
|
54
54
|
): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[];
|
|
55
55
|
|
|
56
56
|
clear(): void;
|
|
@@ -2,8 +2,8 @@ export * from './binary-tree';
|
|
|
2
2
|
export * from './bst';
|
|
3
3
|
export * from './avl-tree';
|
|
4
4
|
export * from './segment-tree';
|
|
5
|
-
export * from './avl-tree-multi-map';
|
|
6
5
|
export * from './red-black-tree';
|
|
7
6
|
export * from './tree-multi-map';
|
|
8
|
-
export * from './tree-
|
|
9
|
-
export * from './
|
|
7
|
+
export * from './tree-set';
|
|
8
|
+
export * from './tree-map';
|
|
9
|
+
export * from './tree-multi-set';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Comparator } from '../../common';
|
|
2
|
+
|
|
3
|
+
export interface TreeMapOptions<K, V, R = [K, V]> {
|
|
4
|
+
comparator?: Comparator<K>;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Pass-through to the underlying RedBlackTree/BST `isMapMode` option.
|
|
8
|
+
*
|
|
9
|
+
* - `true` (default in core): store values in an internal key→value store.
|
|
10
|
+
* - `false`: store values on tree nodes (Node Mode).
|
|
11
|
+
*/
|
|
12
|
+
isMapMode?: boolean;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Transform raw elements into `[key, value]` entries.
|
|
16
|
+
* When provided, the constructor accepts `Iterable<R>` instead of `Iterable<[K, V]>`.
|
|
17
|
+
*/
|
|
18
|
+
toEntryFn?: (rawElement: R) => [K, V];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type TreeMapRangeOptions = {
|
|
22
|
+
lowInclusive?: boolean;
|
|
23
|
+
highInclusive?: boolean;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Callback used by TreeMap entry-wise utilities.
|
|
28
|
+
*
|
|
29
|
+
* `SELF` is intentionally generic to avoid type-layer circular imports.
|
|
30
|
+
* Implementations (e.g. `TreeMap<K, V>`) should bind `SELF` at use sites.
|
|
31
|
+
*/
|
|
32
|
+
export type TreeMapEntryCallback<K, V, R, SELF> = (value: V | undefined, key: K, index: number, map: SELF) => R;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Reducer callback used by TreeMap.
|
|
36
|
+
*
|
|
37
|
+
* `SELF` is intentionally generic to avoid type-layer circular imports.
|
|
38
|
+
*/
|
|
39
|
+
export type TreeMapReduceCallback<K, V, A, SELF> = (
|
|
40
|
+
acc: A,
|
|
41
|
+
value: V | undefined,
|
|
42
|
+
key: K,
|
|
43
|
+
index: number,
|
|
44
|
+
map: SELF
|
|
45
|
+
) => A;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Comparator } from '../../common';
|
|
2
|
+
|
|
3
|
+
export interface TreeMultiSetOptions<K, R = K> {
|
|
4
|
+
comparator?: Comparator<K>;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Pass-through to the underlying RedBlackTree/BST `isMapMode` option.
|
|
8
|
+
*
|
|
9
|
+
* - `true` (recommended): MapMode store uses key→node index for fast lookups.
|
|
10
|
+
* - `false`: Node Mode.
|
|
11
|
+
*/
|
|
12
|
+
isMapMode?: boolean;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Transform raw elements into keys.
|
|
16
|
+
* When provided, the constructor accepts `Iterable<R>` instead of `Iterable<K>`.
|
|
17
|
+
*/
|
|
18
|
+
toElementFn?: (rawElement: R) => K;
|
|
19
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Comparator } from '../../common';
|
|
2
|
+
|
|
3
|
+
export interface TreeSetOptions<K, R = K> {
|
|
4
|
+
comparator?: Comparator<K>;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Pass-through to the underlying RedBlackTree/BST `isMapMode` option.
|
|
8
|
+
*
|
|
9
|
+
* - `true` (default in core): store values in an internal key→value store.
|
|
10
|
+
* - `false`: store values on tree nodes (Node Mode).
|
|
11
|
+
*/
|
|
12
|
+
isMapMode?: boolean;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Transform raw elements into keys.
|
|
16
|
+
* When provided, the constructor accepts `Iterable<R>` instead of `Iterable<K>`.
|
|
17
|
+
*/
|
|
18
|
+
toElementFn?: (rawElement: R) => K;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type TreeSetRangeOptions = {
|
|
22
|
+
lowInclusive?: boolean;
|
|
23
|
+
highInclusive?: boolean;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Callback used by TreeSet element-wise utilities.
|
|
28
|
+
*
|
|
29
|
+
* `SELF` is intentionally generic to avoid type-layer circular imports.
|
|
30
|
+
* Implementations (e.g. `TreeSet<K>`) should bind `SELF` at use sites.
|
|
31
|
+
*/
|
|
32
|
+
export type TreeSetElementCallback<K, R, SELF> = (value: K, index: number, set: SELF) => R;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Reducer callback used by TreeSet.
|
|
36
|
+
*
|
|
37
|
+
* `SELF` is intentionally generic to avoid type-layer circular imports.
|
|
38
|
+
*/
|
|
39
|
+
export type TreeSetReduceCallback<K, A, SELF> = (acc: A, value: K, index: number, set: SELF) => A;
|