avl-tree-typed 2.4.5 → 2.5.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/cjs/index.cjs +2379 -570
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +2372 -563
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +2379 -570
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +2372 -563
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/base/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/base/iterable-entry-base.d.ts +8 -8
- package/dist/types/data-structures/base/linear-base.d.ts +3 -3
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +380 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +487 -147
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +956 -80
- package/dist/types/data-structures/binary-tree/bst.d.ts +816 -29
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +610 -31
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +326 -135
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +3781 -6
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +3607 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +2874 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +3528 -6
- package/dist/types/data-structures/graph/abstract-graph.d.ts +4 -4
- package/dist/types/data-structures/graph/directed-graph.d.ts +429 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +393 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +473 -89
- package/dist/types/data-structures/heap/heap.d.ts +581 -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 +646 -47
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +596 -68
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +793 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +499 -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 +593 -71
- package/dist/types/data-structures/queue/queue.d.ts +463 -42
- package/dist/types/data-structures/stack/stack.d.ts +384 -32
- package/dist/types/data-structures/trie/trie.d.ts +470 -48
- package/dist/types/interfaces/graph.d.ts +1 -1
- package/dist/types/types/common.d.ts +2 -2
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/heap/heap.d.ts +1 -0
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +1 -0
- package/dist/types/types/utils/validate-type.d.ts +4 -4
- package/dist/umd/avl-tree-typed.js +2371 -562
- package/dist/umd/avl-tree-typed.js.map +1 -1
- package/dist/umd/avl-tree-typed.min.js +2 -2
- package/dist/umd/avl-tree-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/base/index.ts +1 -0
- package/src/data-structures/base/iterable-element-base.ts +4 -5
- package/src/data-structures/base/iterable-entry-base.ts +8 -8
- package/src/data-structures/base/linear-base.ts +3 -3
- package/src/data-structures/binary-tree/avl-tree.ts +386 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +596 -247
- package/src/data-structures/binary-tree/binary-tree.ts +956 -81
- package/src/data-structures/binary-tree/bst.ts +840 -35
- package/src/data-structures/binary-tree/red-black-tree.ts +689 -97
- package/src/data-structures/binary-tree/segment-tree.ts +498 -249
- package/src/data-structures/binary-tree/tree-map.ts +3784 -7
- package/src/data-structures/binary-tree/tree-multi-map.ts +3614 -211
- package/src/data-structures/binary-tree/tree-multi-set.ts +2874 -65
- package/src/data-structures/binary-tree/tree-set.ts +3531 -10
- package/src/data-structures/graph/abstract-graph.ts +4 -4
- package/src/data-structures/graph/directed-graph.ts +429 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +393 -59
- package/src/data-structures/hash/hash-map.ts +476 -92
- package/src/data-structures/heap/heap.ts +581 -99
- package/src/data-structures/heap/max-heap.ts +46 -0
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +646 -47
- package/src/data-structures/linked-list/singly-linked-list.ts +596 -68
- package/src/data-structures/linked-list/skip-linked-list.ts +1067 -90
- package/src/data-structures/matrix/matrix.ts +584 -12
- package/src/data-structures/priority-queue/max-priority-queue.ts +57 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +592 -70
- package/src/data-structures/queue/queue.ts +463 -42
- package/src/data-structures/stack/stack.ts +384 -32
- package/src/data-structures/trie/trie.ts +470 -48
- package/src/interfaces/graph.ts +1 -1
- package/src/types/common.ts +2 -2
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/heap/heap.ts +1 -0
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
- package/src/types/data-structures/priority-queue/priority-queue.ts +1 -0
- package/src/types/utils/validate-type.ts +4 -4
package/dist/cjs/index.cjs
CHANGED
|
@@ -59,50 +59,6 @@ function makeTrampoline(fn) {
|
|
|
59
59
|
}
|
|
60
60
|
__name(makeTrampoline, "makeTrampoline");
|
|
61
61
|
|
|
62
|
-
// src/common/error.ts
|
|
63
|
-
var ERR = {
|
|
64
|
-
// Range / index
|
|
65
|
-
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
66
|
-
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
67
|
-
// Type / argument
|
|
68
|
-
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
69
|
-
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
70
|
-
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
71
|
-
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
72
|
-
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
73
|
-
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
74
|
-
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
75
|
-
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
76
|
-
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
77
|
-
// State / operation
|
|
78
|
-
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
79
|
-
// Matrix
|
|
80
|
-
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
81
|
-
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
82
|
-
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
83
|
-
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
84
|
-
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// src/common/index.ts
|
|
88
|
-
var Range = class {
|
|
89
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
90
|
-
this.low = low;
|
|
91
|
-
this.high = high;
|
|
92
|
-
this.includeLow = includeLow;
|
|
93
|
-
this.includeHigh = includeHigh;
|
|
94
|
-
}
|
|
95
|
-
static {
|
|
96
|
-
__name(this, "Range");
|
|
97
|
-
}
|
|
98
|
-
// Determine whether a key is within the range
|
|
99
|
-
isInRange(key, comparator) {
|
|
100
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
101
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
102
|
-
return lowCheck && highCheck;
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
62
|
// src/data-structures/base/iterable-element-base.ts
|
|
107
63
|
var IterableElementBase = class {
|
|
108
64
|
static {
|
|
@@ -121,7 +77,7 @@ var IterableElementBase = class {
|
|
|
121
77
|
if (options) {
|
|
122
78
|
const { toElementFn } = options;
|
|
123
79
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
124
|
-
else if (toElementFn) throw new TypeError(
|
|
80
|
+
else if (toElementFn) throw new TypeError("toElementFn must be a function type");
|
|
125
81
|
}
|
|
126
82
|
}
|
|
127
83
|
/**
|
|
@@ -284,7 +240,7 @@ var IterableElementBase = class {
|
|
|
284
240
|
acc = initialValue;
|
|
285
241
|
} else {
|
|
286
242
|
const first = iter.next();
|
|
287
|
-
if (first.done) throw new TypeError(
|
|
243
|
+
if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
|
|
288
244
|
acc = first.value;
|
|
289
245
|
index = 1;
|
|
290
246
|
}
|
|
@@ -519,6 +475,232 @@ var LinearBase = class _LinearBase extends IterableElementBase {
|
|
|
519
475
|
}
|
|
520
476
|
};
|
|
521
477
|
|
|
478
|
+
// src/common/error.ts
|
|
479
|
+
var ERR = {
|
|
480
|
+
// Range / index
|
|
481
|
+
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
482
|
+
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
483
|
+
// Type / argument
|
|
484
|
+
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
485
|
+
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
486
|
+
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
487
|
+
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
488
|
+
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
489
|
+
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
490
|
+
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
491
|
+
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
492
|
+
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
493
|
+
// State / operation
|
|
494
|
+
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
495
|
+
// Matrix
|
|
496
|
+
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
497
|
+
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
498
|
+
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
499
|
+
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
500
|
+
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
// src/common/index.ts
|
|
504
|
+
var Range = class {
|
|
505
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
506
|
+
this.low = low;
|
|
507
|
+
this.high = high;
|
|
508
|
+
this.includeLow = includeLow;
|
|
509
|
+
this.includeHigh = includeHigh;
|
|
510
|
+
}
|
|
511
|
+
static {
|
|
512
|
+
__name(this, "Range");
|
|
513
|
+
}
|
|
514
|
+
// Determine whether a key is within the range
|
|
515
|
+
isInRange(key, comparator) {
|
|
516
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
517
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
518
|
+
return lowCheck && highCheck;
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
523
|
+
var IterableEntryBase = class {
|
|
524
|
+
static {
|
|
525
|
+
__name(this, "IterableEntryBase");
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Default iterator yielding `[key, value]` entries.
|
|
529
|
+
* @returns Iterator of `[K, V]`.
|
|
530
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
531
|
+
*/
|
|
532
|
+
*[Symbol.iterator](...args) {
|
|
533
|
+
yield* this._getIterator(...args);
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
537
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
538
|
+
* @remarks Time O(n), Space O(1)
|
|
539
|
+
*/
|
|
540
|
+
*entries() {
|
|
541
|
+
for (const item of this) {
|
|
542
|
+
yield item;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Iterate over keys only.
|
|
547
|
+
* @returns Iterator of keys.
|
|
548
|
+
* @remarks Time O(n), Space O(1)
|
|
549
|
+
*/
|
|
550
|
+
*keys() {
|
|
551
|
+
for (const item of this) {
|
|
552
|
+
yield item[0];
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Iterate over values only.
|
|
557
|
+
* @returns Iterator of values.
|
|
558
|
+
* @remarks Time O(n), Space O(1)
|
|
559
|
+
*/
|
|
560
|
+
*values() {
|
|
561
|
+
for (const item of this) {
|
|
562
|
+
yield item[1];
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Test whether all entries satisfy the predicate.
|
|
567
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
568
|
+
* @param thisArg - Optional `this` for callback.
|
|
569
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
570
|
+
* @remarks Time O(n), Space O(1)
|
|
571
|
+
*/
|
|
572
|
+
every(predicate, thisArg) {
|
|
573
|
+
let index = 0;
|
|
574
|
+
for (const item of this) {
|
|
575
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Test whether any entry satisfies the predicate.
|
|
583
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
584
|
+
* @param thisArg - Optional `this` for callback.
|
|
585
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
586
|
+
* @remarks Time O(n), Space O(1)
|
|
587
|
+
*/
|
|
588
|
+
some(predicate, thisArg) {
|
|
589
|
+
let index = 0;
|
|
590
|
+
for (const item of this) {
|
|
591
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Visit each entry, left-to-right.
|
|
599
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
600
|
+
* @param thisArg - Optional `this` for callback.
|
|
601
|
+
* @remarks Time O(n), Space O(1)
|
|
602
|
+
*/
|
|
603
|
+
forEach(callbackfn, thisArg) {
|
|
604
|
+
let index = 0;
|
|
605
|
+
for (const item of this) {
|
|
606
|
+
const [key, value] = item;
|
|
607
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Find the first entry that matches a predicate.
|
|
612
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
613
|
+
* @param thisArg - Optional `this` for callback.
|
|
614
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
615
|
+
* @remarks Time O(n), Space O(1)
|
|
616
|
+
*/
|
|
617
|
+
find(callbackfn, thisArg) {
|
|
618
|
+
let index = 0;
|
|
619
|
+
for (const item of this) {
|
|
620
|
+
const [key, value] = item;
|
|
621
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
622
|
+
}
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Whether the given key exists.
|
|
627
|
+
* @param key - Key to test.
|
|
628
|
+
* @returns `true` if found; otherwise `false`.
|
|
629
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
630
|
+
*/
|
|
631
|
+
has(key) {
|
|
632
|
+
for (const item of this) {
|
|
633
|
+
const [itemKey] = item;
|
|
634
|
+
if (itemKey === key) return true;
|
|
635
|
+
}
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Whether there exists an entry with the given value.
|
|
640
|
+
* @param value - Value to test.
|
|
641
|
+
* @returns `true` if found; otherwise `false`.
|
|
642
|
+
* @remarks Time O(n), Space O(1)
|
|
643
|
+
*/
|
|
644
|
+
hasValue(value) {
|
|
645
|
+
for (const [, elementValue] of this) {
|
|
646
|
+
if (elementValue === value) return true;
|
|
647
|
+
}
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Get the value under a key.
|
|
652
|
+
* @param key - Key to look up.
|
|
653
|
+
* @returns Value or `undefined`.
|
|
654
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
655
|
+
*/
|
|
656
|
+
get(key) {
|
|
657
|
+
for (const item of this) {
|
|
658
|
+
const [itemKey, value] = item;
|
|
659
|
+
if (itemKey === key) return value;
|
|
660
|
+
}
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Reduce entries into a single accumulator.
|
|
665
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
666
|
+
* @param initialValue - Initial accumulator.
|
|
667
|
+
* @returns Final accumulator.
|
|
668
|
+
* @remarks Time O(n), Space O(1)
|
|
669
|
+
*/
|
|
670
|
+
reduce(callbackfn, initialValue) {
|
|
671
|
+
let accumulator = initialValue;
|
|
672
|
+
let index = 0;
|
|
673
|
+
for (const item of this) {
|
|
674
|
+
const [key, value] = item;
|
|
675
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
676
|
+
}
|
|
677
|
+
return accumulator;
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Converts data structure to `[key, value]` pairs.
|
|
681
|
+
* @returns Array of entries.
|
|
682
|
+
* @remarks Time O(n), Space O(n)
|
|
683
|
+
*/
|
|
684
|
+
toArray() {
|
|
685
|
+
return [...this];
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
689
|
+
* @returns Array of entries (default) or a string.
|
|
690
|
+
* @remarks Time O(n), Space O(n)
|
|
691
|
+
*/
|
|
692
|
+
toVisual() {
|
|
693
|
+
return [...this];
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Print a human-friendly representation to the console.
|
|
697
|
+
* @remarks Time O(n), Space O(n)
|
|
698
|
+
*/
|
|
699
|
+
print() {
|
|
700
|
+
console.log(this.toVisual());
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
|
|
522
704
|
// src/data-structures/queue/queue.ts
|
|
523
705
|
var Queue = class _Queue extends LinearBase {
|
|
524
706
|
static {
|
|
@@ -576,18 +758,94 @@ var Queue = class _Queue extends LinearBase {
|
|
|
576
758
|
this._autoCompactRatio = value;
|
|
577
759
|
}
|
|
578
760
|
/**
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
761
|
+
* Get the number of elements currently in the queue.
|
|
762
|
+
* @remarks Time O(1), Space O(1)
|
|
763
|
+
* @returns Current length.
|
|
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
|
+
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
* @example
|
|
797
|
+
* // Track queue length
|
|
798
|
+
* const q = new Queue<number>();
|
|
799
|
+
* console.log(q.length); // 0;
|
|
800
|
+
* q.push(1);
|
|
801
|
+
* q.push(2);
|
|
802
|
+
* console.log(q.length); // 2;
|
|
803
|
+
*/
|
|
583
804
|
get length() {
|
|
584
805
|
return this.elements.length - this._offset;
|
|
585
806
|
}
|
|
586
807
|
/**
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
808
|
+
* Get the first element (front) without removing it.
|
|
809
|
+
* @remarks Time O(1), Space O(1)
|
|
810
|
+
* @returns Front element or undefined.
|
|
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
|
+
|
|
843
|
+
* @example
|
|
844
|
+
* // View the front element
|
|
845
|
+
* const q = new Queue<string>(['first', 'second', 'third']);
|
|
846
|
+
* console.log(q.first); // 'first';
|
|
847
|
+
* console.log(q.length); // 3;
|
|
848
|
+
*/
|
|
591
849
|
get first() {
|
|
592
850
|
return this.length > 0 ? this.elements[this._offset] : void 0;
|
|
593
851
|
}
|
|
@@ -610,19 +868,111 @@ var Queue = class _Queue extends LinearBase {
|
|
|
610
868
|
return new _Queue(elements);
|
|
611
869
|
}
|
|
612
870
|
/**
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
871
|
+
* Check whether the queue is empty.
|
|
872
|
+
* @remarks Time O(1), Space O(1)
|
|
873
|
+
* @returns True if length is 0.
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
* @example
|
|
907
|
+
* // Queue for...of iteration and isEmpty check
|
|
908
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
909
|
+
*
|
|
910
|
+
* const elements: string[] = [];
|
|
911
|
+
* for (const item of queue) {
|
|
912
|
+
* elements.push(item);
|
|
913
|
+
* }
|
|
914
|
+
*
|
|
915
|
+
* // Verify all elements are iterated in order
|
|
916
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
917
|
+
*
|
|
918
|
+
* // Process all elements
|
|
919
|
+
* while (queue.length > 0) {
|
|
920
|
+
* queue.shift();
|
|
921
|
+
* }
|
|
922
|
+
*
|
|
923
|
+
* console.log(queue.length); // 0;
|
|
924
|
+
*/
|
|
617
925
|
isEmpty() {
|
|
618
926
|
return this.length === 0;
|
|
619
927
|
}
|
|
620
928
|
/**
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
929
|
+
* Enqueue one element at the back.
|
|
930
|
+
* @remarks Time O(1), Space O(1)
|
|
931
|
+
* @param element - Element to enqueue.
|
|
932
|
+
* @returns True on success.
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
* @example
|
|
966
|
+
* // basic Queue creation and push operation
|
|
967
|
+
* // Create a simple Queue with initial values
|
|
968
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
969
|
+
*
|
|
970
|
+
* // Verify the queue maintains insertion order
|
|
971
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
972
|
+
*
|
|
973
|
+
* // Check length
|
|
974
|
+
* console.log(queue.length); // 5;
|
|
975
|
+
*/
|
|
626
976
|
push(element) {
|
|
627
977
|
this.elements.push(element);
|
|
628
978
|
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
@@ -643,10 +993,56 @@ var Queue = class _Queue extends LinearBase {
|
|
|
643
993
|
return ans;
|
|
644
994
|
}
|
|
645
995
|
/**
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
996
|
+
* Dequeue one element from the front (amortized via offset).
|
|
997
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
998
|
+
* @returns Removed element or undefined.
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
|
|
1030
|
+
|
|
1031
|
+
* @example
|
|
1032
|
+
* // Queue shift and peek operations
|
|
1033
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
1034
|
+
*
|
|
1035
|
+
* // Peek at the front element without removing it
|
|
1036
|
+
* console.log(queue.first); // 10;
|
|
1037
|
+
*
|
|
1038
|
+
* // Remove and get the first element (FIFO)
|
|
1039
|
+
* const first = queue.shift();
|
|
1040
|
+
* console.log(first); // 10;
|
|
1041
|
+
*
|
|
1042
|
+
* // Verify remaining elements and length decreased
|
|
1043
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
1044
|
+
* console.log(queue.length); // 3;
|
|
1045
|
+
*/
|
|
650
1046
|
shift() {
|
|
651
1047
|
if (this.length === 0) return void 0;
|
|
652
1048
|
const first = this.first;
|
|
@@ -655,11 +1051,45 @@ var Queue = class _Queue extends LinearBase {
|
|
|
655
1051
|
return first;
|
|
656
1052
|
}
|
|
657
1053
|
/**
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
1054
|
+
* Delete the first occurrence of a specific element.
|
|
1055
|
+
* @remarks Time O(N), Space O(1)
|
|
1056
|
+
* @param element - Element to remove (strict equality via Object.is).
|
|
1057
|
+
* @returns True if an element was removed.
|
|
1058
|
+
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
* @example
|
|
1088
|
+
* // Remove specific element
|
|
1089
|
+
* const q = new Queue<number>([1, 2, 3, 2]);
|
|
1090
|
+
* q.delete(2);
|
|
1091
|
+
* console.log(q.length); // 3;
|
|
1092
|
+
*/
|
|
663
1093
|
delete(element) {
|
|
664
1094
|
for (let i = this._offset; i < this.elements.length; i++) {
|
|
665
1095
|
if (Object.is(this.elements[i], element)) {
|
|
@@ -670,11 +1100,45 @@ var Queue = class _Queue extends LinearBase {
|
|
|
670
1100
|
return false;
|
|
671
1101
|
}
|
|
672
1102
|
/**
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
1103
|
+
* Get the element at a given logical index.
|
|
1104
|
+
* @remarks Time O(1), Space O(1)
|
|
1105
|
+
* @param index - Zero-based index from the front.
|
|
1106
|
+
* @returns Element or undefined.
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
* @example
|
|
1137
|
+
* // Access element by index
|
|
1138
|
+
* const q = new Queue<string>(['a', 'b', 'c']);
|
|
1139
|
+
* console.log(q.at(0)); // 'a';
|
|
1140
|
+
* console.log(q.at(2)); // 'c';
|
|
1141
|
+
*/
|
|
678
1142
|
at(index) {
|
|
679
1143
|
if (index < 0 || index >= this.length) return void 0;
|
|
680
1144
|
return this._elements[this._offset + index];
|
|
@@ -726,19 +1190,90 @@ var Queue = class _Queue extends LinearBase {
|
|
|
726
1190
|
return this;
|
|
727
1191
|
}
|
|
728
1192
|
/**
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
1193
|
+
* Remove all elements and reset offset.
|
|
1194
|
+
* @remarks Time O(1), Space O(1)
|
|
1195
|
+
* @returns void
|
|
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
|
+
* @example
|
|
1227
|
+
* // Remove all elements
|
|
1228
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1229
|
+
* q.clear();
|
|
1230
|
+
* console.log(q.length); // 0;
|
|
1231
|
+
*/
|
|
733
1232
|
clear() {
|
|
734
1233
|
this._elements = [];
|
|
735
1234
|
this._offset = 0;
|
|
736
1235
|
}
|
|
737
1236
|
/**
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
1237
|
+
* Compact storage by discarding consumed head elements.
|
|
1238
|
+
* @remarks Time O(N), Space O(N)
|
|
1239
|
+
* @returns True when compaction performed.
|
|
1240
|
+
|
|
1241
|
+
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
|
|
1253
|
+
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
|
|
1263
|
+
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
* @example
|
|
1270
|
+
* // Reclaim unused memory
|
|
1271
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1272
|
+
* q.shift();
|
|
1273
|
+
* q.shift();
|
|
1274
|
+
* q.compact();
|
|
1275
|
+
* console.log(q.length); // 3;
|
|
1276
|
+
*/
|
|
742
1277
|
compact() {
|
|
743
1278
|
this._elements = this.elements.slice(this._offset);
|
|
744
1279
|
this._offset = 0;
|
|
@@ -757,315 +1292,239 @@ var Queue = class _Queue extends LinearBase {
|
|
|
757
1292
|
deleteCount = Math.max(0, Math.min(deleteCount, this.length - start));
|
|
758
1293
|
const gi = this._offset + start;
|
|
759
1294
|
const removedArray = this._elements.splice(gi, deleteCount, ...items);
|
|
760
|
-
if (this.elements.length > 0 && this.offset / this.elements.length > this.autoCompactRatio) this.compact();
|
|
761
|
-
const removed = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
762
|
-
removed._setAutoCompactRatio(this._autoCompactRatio);
|
|
763
|
-
removed.pushMany(removedArray);
|
|
764
|
-
return removed;
|
|
765
|
-
}
|
|
766
|
-
/**
|
|
767
|
-
* Deep clone this queue and its parameters.
|
|
768
|
-
* @remarks Time O(N), Space O(N)
|
|
769
|
-
* @returns A new queue with the same content and options.
|
|
770
|
-
*/
|
|
771
|
-
clone() {
|
|
772
|
-
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
773
|
-
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
774
|
-
for (let i = this._offset; i < this.elements.length; i++) out.push(this.elements[i]);
|
|
775
|
-
return out;
|
|
776
|
-
}
|
|
777
|
-
/**
|
|
778
|
-
* Filter elements into a new queue of the same class.
|
|
779
|
-
* @remarks Time O(N), Space O(N)
|
|
780
|
-
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
781
|
-
* @param [thisArg] - Value for `this` inside the predicate.
|
|
782
|
-
* @returns A new queue with kept elements.
|
|
783
|
-
*/
|
|
784
|
-
filter(predicate, thisArg) {
|
|
785
|
-
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
786
|
-
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
787
|
-
let index = 0;
|
|
788
|
-
for (const v of this) {
|
|
789
|
-
if (predicate.call(thisArg, v, index, this)) out.push(v);
|
|
790
|
-
index++;
|
|
791
|
-
}
|
|
792
|
-
return out;
|
|
793
|
-
}
|
|
794
|
-
/**
|
|
795
|
-
* Map each element to a new element in a possibly different-typed queue.
|
|
796
|
-
* @remarks Time O(N), Space O(N)
|
|
797
|
-
* @template EM
|
|
798
|
-
* @template RM
|
|
799
|
-
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
800
|
-
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
801
|
-
* @param [thisArg] - Value for `this` inside the callback.
|
|
802
|
-
* @returns A new Queue with mapped elements.
|
|
803
|
-
*/
|
|
804
|
-
map(callback, options, thisArg) {
|
|
805
|
-
const out = new this.constructor([], {
|
|
806
|
-
toElementFn: options?.toElementFn,
|
|
807
|
-
maxLen: options?.maxLen ?? this._maxLen,
|
|
808
|
-
autoCompactRatio: options?.autoCompactRatio ?? this._autoCompactRatio
|
|
809
|
-
});
|
|
810
|
-
let index = 0;
|
|
811
|
-
for (const v of this)
|
|
812
|
-
out.push(thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this));
|
|
813
|
-
return out;
|
|
814
|
-
}
|
|
815
|
-
/**
|
|
816
|
-
* Map each element to a new value of the same type.
|
|
817
|
-
* @remarks Time O(N), Space O(N)
|
|
818
|
-
* @param callback - Mapping function (element, index, queue) → element.
|
|
819
|
-
* @param [thisArg] - Value for `this` inside the callback.
|
|
820
|
-
* @returns A new queue with mapped elements (same element type).
|
|
821
|
-
*/
|
|
822
|
-
mapSame(callback, thisArg) {
|
|
823
|
-
const Ctor = this.constructor;
|
|
824
|
-
const out = new Ctor([], {
|
|
825
|
-
toElementFn: this.toElementFn,
|
|
826
|
-
maxLen: this._maxLen,
|
|
827
|
-
autoCompactRatio: this._autoCompactRatio
|
|
828
|
-
});
|
|
829
|
-
out._setAutoCompactRatio?.(this._autoCompactRatio);
|
|
830
|
-
let index = 0;
|
|
831
|
-
for (const v of this) {
|
|
832
|
-
const mv = thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
|
|
833
|
-
out.push(mv);
|
|
834
|
-
}
|
|
835
|
-
return out;
|
|
836
|
-
}
|
|
837
|
-
/**
|
|
838
|
-
* (Protected) Set the internal auto-compaction ratio.
|
|
839
|
-
* @remarks Time O(1), Space O(1)
|
|
840
|
-
* @param value - New ratio to assign.
|
|
841
|
-
* @returns void
|
|
842
|
-
*/
|
|
843
|
-
_setAutoCompactRatio(value) {
|
|
844
|
-
this._autoCompactRatio = value;
|
|
845
|
-
}
|
|
846
|
-
/**
|
|
847
|
-
* (Protected) Iterate elements from front to back.
|
|
848
|
-
* @remarks Time O(N), Space O(1)
|
|
849
|
-
* @returns Iterator of E.
|
|
850
|
-
*/
|
|
851
|
-
*_getIterator() {
|
|
852
|
-
for (let i = this._offset; i < this.elements.length; i++) yield this.elements[i];
|
|
853
|
-
}
|
|
854
|
-
/**
|
|
855
|
-
* (Protected) Iterate elements from back to front.
|
|
856
|
-
* @remarks Time O(N), Space O(1)
|
|
857
|
-
* @returns Iterator of E.
|
|
858
|
-
*/
|
|
859
|
-
*_getReverseIterator() {
|
|
860
|
-
for (let i = this.length - 1; i >= 0; i--) {
|
|
861
|
-
const cur = this.at(i);
|
|
862
|
-
if (cur !== void 0) yield cur;
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
/**
|
|
866
|
-
* (Protected) Create an empty instance of the same concrete class.
|
|
867
|
-
* @remarks Time O(1), Space O(1)
|
|
868
|
-
* @param [options] - Options forwarded to the constructor.
|
|
869
|
-
* @returns An empty like-kind queue instance.
|
|
870
|
-
*/
|
|
871
|
-
_createInstance(options) {
|
|
872
|
-
const Ctor = this.constructor;
|
|
873
|
-
return new Ctor([], options);
|
|
874
|
-
}
|
|
875
|
-
/**
|
|
876
|
-
* (Protected) Create a like-kind queue and seed it from an iterable.
|
|
877
|
-
* @remarks Time O(N), Space O(N)
|
|
878
|
-
* @template EM
|
|
879
|
-
* @template RM
|
|
880
|
-
* @param [elements] - Iterable used to seed the new queue.
|
|
881
|
-
* @param [options] - Options forwarded to the constructor.
|
|
882
|
-
* @returns A like-kind Queue instance.
|
|
883
|
-
*/
|
|
884
|
-
_createLike(elements = [], options) {
|
|
885
|
-
const Ctor = this.constructor;
|
|
886
|
-
return new Ctor(elements, options);
|
|
887
|
-
}
|
|
888
|
-
};
|
|
889
|
-
|
|
890
|
-
// src/data-structures/base/iterable-entry-base.ts
|
|
891
|
-
var IterableEntryBase = class {
|
|
892
|
-
static {
|
|
893
|
-
__name(this, "IterableEntryBase");
|
|
894
|
-
}
|
|
895
|
-
/**
|
|
896
|
-
* Default iterator yielding `[key, value]` entries.
|
|
897
|
-
* @returns Iterator of `[K, V]`.
|
|
898
|
-
* @remarks Time O(n) to iterate, Space O(1)
|
|
899
|
-
*/
|
|
900
|
-
*[Symbol.iterator](...args) {
|
|
901
|
-
yield* this._getIterator(...args);
|
|
902
|
-
}
|
|
903
|
-
/**
|
|
904
|
-
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
905
|
-
* @returns Iterator of `[K, V | undefined]`.
|
|
906
|
-
* @remarks Time O(n), Space O(1)
|
|
907
|
-
*/
|
|
908
|
-
*entries() {
|
|
909
|
-
for (const item of this) {
|
|
910
|
-
yield item;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
/**
|
|
914
|
-
* Iterate over keys only.
|
|
915
|
-
* @returns Iterator of keys.
|
|
916
|
-
* @remarks Time O(n), Space O(1)
|
|
917
|
-
*/
|
|
918
|
-
*keys() {
|
|
919
|
-
for (const item of this) {
|
|
920
|
-
yield item[0];
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
/**
|
|
924
|
-
* Iterate over values only.
|
|
925
|
-
* @returns Iterator of values.
|
|
926
|
-
* @remarks Time O(n), Space O(1)
|
|
927
|
-
*/
|
|
928
|
-
*values() {
|
|
929
|
-
for (const item of this) {
|
|
930
|
-
yield item[1];
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
/**
|
|
934
|
-
* Test whether all entries satisfy the predicate.
|
|
935
|
-
* @param predicate - `(key, value, index, self) => boolean`.
|
|
936
|
-
* @param thisArg - Optional `this` for callback.
|
|
937
|
-
* @returns `true` if all pass; otherwise `false`.
|
|
938
|
-
* @remarks Time O(n), Space O(1)
|
|
939
|
-
*/
|
|
940
|
-
every(predicate, thisArg) {
|
|
941
|
-
let index = 0;
|
|
942
|
-
for (const item of this) {
|
|
943
|
-
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
944
|
-
return false;
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
return true;
|
|
1295
|
+
if (this.elements.length > 0 && this.offset / this.elements.length > this.autoCompactRatio) this.compact();
|
|
1296
|
+
const removed = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
1297
|
+
removed._setAutoCompactRatio(this._autoCompactRatio);
|
|
1298
|
+
removed.pushMany(removedArray);
|
|
1299
|
+
return removed;
|
|
948
1300
|
}
|
|
949
1301
|
/**
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
1302
|
+
* Deep clone this queue and its parameters.
|
|
1303
|
+
* @remarks Time O(N), Space O(N)
|
|
1304
|
+
* @returns A new queue with the same content and options.
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
|
|
1309
|
+
|
|
1310
|
+
|
|
1311
|
+
|
|
1312
|
+
|
|
1313
|
+
|
|
1314
|
+
|
|
1315
|
+
|
|
1316
|
+
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
* @example
|
|
1336
|
+
* // Create independent copy
|
|
1337
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1338
|
+
* const copy = q.clone();
|
|
1339
|
+
* copy.shift();
|
|
1340
|
+
* console.log(q.length); // 3;
|
|
1341
|
+
* console.log(copy.length); // 2;
|
|
1342
|
+
*/
|
|
1343
|
+
clone() {
|
|
1344
|
+
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
1345
|
+
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
1346
|
+
for (let i = this._offset; i < this.elements.length; i++) out.push(this.elements[i]);
|
|
1347
|
+
return out;
|
|
964
1348
|
}
|
|
965
1349
|
/**
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1350
|
+
* Filter elements into a new queue of the same class.
|
|
1351
|
+
* @remarks Time O(N), Space O(N)
|
|
1352
|
+
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
1353
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1354
|
+
* @returns A new queue with kept elements.
|
|
1355
|
+
|
|
1356
|
+
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
|
|
1363
|
+
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
|
|
1380
|
+
|
|
1381
|
+
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
* @example
|
|
1386
|
+
* // Filter elements
|
|
1387
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1388
|
+
* const evens = q.filter(x => x % 2 === 0);
|
|
1389
|
+
* console.log(evens.length); // 2;
|
|
1390
|
+
*/
|
|
1391
|
+
filter(predicate, thisArg) {
|
|
1392
|
+
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
1393
|
+
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
972
1394
|
let index = 0;
|
|
973
|
-
for (const
|
|
974
|
-
|
|
975
|
-
|
|
1395
|
+
for (const v of this) {
|
|
1396
|
+
if (predicate.call(thisArg, v, index, this)) out.push(v);
|
|
1397
|
+
index++;
|
|
976
1398
|
}
|
|
1399
|
+
return out;
|
|
977
1400
|
}
|
|
978
1401
|
/**
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1402
|
+
* Map each element to a new element in a possibly different-typed queue.
|
|
1403
|
+
* @remarks Time O(N), Space O(N)
|
|
1404
|
+
* @template EM
|
|
1405
|
+
* @template RM
|
|
1406
|
+
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
1407
|
+
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
1408
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1409
|
+
* @returns A new Queue with mapped elements.
|
|
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
|
+
* @example
|
|
1440
|
+
* // Transform elements
|
|
1441
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1442
|
+
* const doubled = q.map(x => x * 2);
|
|
1443
|
+
* console.log(doubled.toArray()); // [2, 4, 6];
|
|
1444
|
+
*/
|
|
1445
|
+
map(callback, options, thisArg) {
|
|
1446
|
+
const out = new this.constructor([], {
|
|
1447
|
+
toElementFn: options?.toElementFn,
|
|
1448
|
+
maxLen: options?.maxLen ?? this._maxLen,
|
|
1449
|
+
autoCompactRatio: options?.autoCompactRatio ?? this._autoCompactRatio
|
|
1450
|
+
});
|
|
986
1451
|
let index = 0;
|
|
987
|
-
for (const
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
}
|
|
991
|
-
return;
|
|
1452
|
+
for (const v of this)
|
|
1453
|
+
out.push(thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this));
|
|
1454
|
+
return out;
|
|
992
1455
|
}
|
|
993
1456
|
/**
|
|
994
|
-
*
|
|
995
|
-
* @
|
|
996
|
-
* @
|
|
997
|
-
* @
|
|
1457
|
+
* Map each element to a new value of the same type.
|
|
1458
|
+
* @remarks Time O(N), Space O(N)
|
|
1459
|
+
* @param callback - Mapping function (element, index, queue) → element.
|
|
1460
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1461
|
+
* @returns A new queue with mapped elements (same element type).
|
|
998
1462
|
*/
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1463
|
+
mapSame(callback, thisArg) {
|
|
1464
|
+
const Ctor = this.constructor;
|
|
1465
|
+
const out = new Ctor([], {
|
|
1466
|
+
toElementFn: this.toElementFn,
|
|
1467
|
+
maxLen: this._maxLen,
|
|
1468
|
+
autoCompactRatio: this._autoCompactRatio
|
|
1469
|
+
});
|
|
1470
|
+
out._setAutoCompactRatio?.(this._autoCompactRatio);
|
|
1471
|
+
let index = 0;
|
|
1472
|
+
for (const v of this) {
|
|
1473
|
+
const mv = thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
|
|
1474
|
+
out.push(mv);
|
|
1003
1475
|
}
|
|
1004
|
-
return
|
|
1476
|
+
return out;
|
|
1005
1477
|
}
|
|
1006
1478
|
/**
|
|
1007
|
-
*
|
|
1008
|
-
* @
|
|
1009
|
-
* @
|
|
1010
|
-
* @
|
|
1479
|
+
* (Protected) Set the internal auto-compaction ratio.
|
|
1480
|
+
* @remarks Time O(1), Space O(1)
|
|
1481
|
+
* @param value - New ratio to assign.
|
|
1482
|
+
* @returns void
|
|
1011
1483
|
*/
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
if (elementValue === value) return true;
|
|
1015
|
-
}
|
|
1016
|
-
return false;
|
|
1484
|
+
_setAutoCompactRatio(value) {
|
|
1485
|
+
this._autoCompactRatio = value;
|
|
1017
1486
|
}
|
|
1018
1487
|
/**
|
|
1019
|
-
*
|
|
1020
|
-
* @
|
|
1021
|
-
* @returns
|
|
1022
|
-
* @remarks Time O(n) generic, Space O(1)
|
|
1488
|
+
* (Protected) Iterate elements from front to back.
|
|
1489
|
+
* @remarks Time O(N), Space O(1)
|
|
1490
|
+
* @returns Iterator of E.
|
|
1023
1491
|
*/
|
|
1024
|
-
|
|
1025
|
-
for (
|
|
1026
|
-
const [itemKey, value] = item;
|
|
1027
|
-
if (itemKey === key) return value;
|
|
1028
|
-
}
|
|
1029
|
-
return;
|
|
1492
|
+
*_getIterator() {
|
|
1493
|
+
for (let i = this._offset; i < this.elements.length; i++) yield this.elements[i];
|
|
1030
1494
|
}
|
|
1031
1495
|
/**
|
|
1032
|
-
*
|
|
1033
|
-
* @
|
|
1034
|
-
* @
|
|
1035
|
-
* @returns Final accumulator.
|
|
1036
|
-
* @remarks Time O(n), Space O(1)
|
|
1496
|
+
* (Protected) Iterate elements from back to front.
|
|
1497
|
+
* @remarks Time O(N), Space O(1)
|
|
1498
|
+
* @returns Iterator of E.
|
|
1037
1499
|
*/
|
|
1038
|
-
|
|
1039
|
-
let
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
const [key, value] = item;
|
|
1043
|
-
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
1500
|
+
*_getReverseIterator() {
|
|
1501
|
+
for (let i = this.length - 1; i >= 0; i--) {
|
|
1502
|
+
const cur = this.at(i);
|
|
1503
|
+
if (cur !== void 0) yield cur;
|
|
1044
1504
|
}
|
|
1045
|
-
return accumulator;
|
|
1046
|
-
}
|
|
1047
|
-
/**
|
|
1048
|
-
* Converts data structure to `[key, value]` pairs.
|
|
1049
|
-
* @returns Array of entries.
|
|
1050
|
-
* @remarks Time O(n), Space O(n)
|
|
1051
|
-
*/
|
|
1052
|
-
toArray() {
|
|
1053
|
-
return [...this];
|
|
1054
1505
|
}
|
|
1055
1506
|
/**
|
|
1056
|
-
*
|
|
1057
|
-
* @
|
|
1058
|
-
* @
|
|
1507
|
+
* (Protected) Create an empty instance of the same concrete class.
|
|
1508
|
+
* @remarks Time O(1), Space O(1)
|
|
1509
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1510
|
+
* @returns An empty like-kind queue instance.
|
|
1059
1511
|
*/
|
|
1060
|
-
|
|
1061
|
-
|
|
1512
|
+
_createInstance(options) {
|
|
1513
|
+
const Ctor = this.constructor;
|
|
1514
|
+
return new Ctor([], options);
|
|
1062
1515
|
}
|
|
1063
1516
|
/**
|
|
1064
|
-
*
|
|
1065
|
-
* @remarks Time O(
|
|
1517
|
+
* (Protected) Create a like-kind queue and seed it from an iterable.
|
|
1518
|
+
* @remarks Time O(N), Space O(N)
|
|
1519
|
+
* @template EM
|
|
1520
|
+
* @template RM
|
|
1521
|
+
* @param [elements] - Iterable used to seed the new queue.
|
|
1522
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1523
|
+
* @returns A like-kind Queue instance.
|
|
1066
1524
|
*/
|
|
1067
|
-
|
|
1068
|
-
|
|
1525
|
+
_createLike(elements = [], options) {
|
|
1526
|
+
const Ctor = this.constructor;
|
|
1527
|
+
return new Ctor(elements, options);
|
|
1069
1528
|
}
|
|
1070
1529
|
};
|
|
1071
1530
|
|
|
@@ -1442,23 +1901,113 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1442
1901
|
return isComparable(key);
|
|
1443
1902
|
}
|
|
1444
1903
|
/**
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1904
|
+
* Adds a new node to the tree.
|
|
1905
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation adds the node at the first available position in a level-order (BFS) traversal. This is NOT a Binary Search Tree insertion. Time O(N), where N is the number of nodes. It must traverse level-by-level to find an empty slot. Space O(N) in the worst case for the BFS queue (e.g., a full last level).
|
|
1906
|
+
*
|
|
1907
|
+
* @param keyNodeOrEntry - The key, node, or entry to add.
|
|
1908
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1909
|
+
|
|
1910
|
+
|
|
1911
|
+
|
|
1912
|
+
|
|
1913
|
+
|
|
1914
|
+
|
|
1915
|
+
|
|
1916
|
+
|
|
1917
|
+
|
|
1918
|
+
|
|
1919
|
+
|
|
1920
|
+
|
|
1921
|
+
|
|
1922
|
+
|
|
1923
|
+
|
|
1924
|
+
|
|
1925
|
+
|
|
1926
|
+
|
|
1927
|
+
|
|
1928
|
+
|
|
1929
|
+
|
|
1930
|
+
|
|
1931
|
+
|
|
1932
|
+
|
|
1933
|
+
|
|
1934
|
+
|
|
1935
|
+
|
|
1936
|
+
* @example
|
|
1937
|
+
* // Add a single node
|
|
1938
|
+
* const tree = new BinaryTree<number>();
|
|
1939
|
+
* tree.add(1);
|
|
1940
|
+
* tree.add(2);
|
|
1941
|
+
* tree.add(3);
|
|
1942
|
+
* console.log(tree.size); // 3;
|
|
1943
|
+
* console.log(tree.has(1)); // true;
|
|
1944
|
+
*/
|
|
1451
1945
|
add(keyNodeOrEntry) {
|
|
1452
1946
|
return this.set(keyNodeOrEntry);
|
|
1453
1947
|
}
|
|
1454
1948
|
/**
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1949
|
+
* Adds or updates a new node to the tree.
|
|
1950
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation sets the node at the first available position in a level-order (BFS) traversal. This is NOT a Binary Search Tree insertion. Time O(N), where N is the number of nodes. It must traverse level-by-level to find an empty slot. Space O(N) in the worst case for the BFS queue (e.g., a full last level).
|
|
1951
|
+
*
|
|
1952
|
+
* @param keyNodeOrEntry - The key, node, or entry to set or update.
|
|
1953
|
+
* @param [value] - The value, if providing just a key.
|
|
1954
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1955
|
+
|
|
1956
|
+
|
|
1957
|
+
|
|
1958
|
+
|
|
1959
|
+
|
|
1960
|
+
|
|
1961
|
+
|
|
1962
|
+
|
|
1963
|
+
|
|
1964
|
+
|
|
1965
|
+
|
|
1966
|
+
|
|
1967
|
+
|
|
1968
|
+
|
|
1969
|
+
|
|
1970
|
+
|
|
1971
|
+
|
|
1972
|
+
|
|
1973
|
+
|
|
1974
|
+
|
|
1975
|
+
|
|
1976
|
+
|
|
1977
|
+
|
|
1978
|
+
|
|
1979
|
+
|
|
1980
|
+
|
|
1981
|
+
|
|
1982
|
+
|
|
1983
|
+
|
|
1984
|
+
|
|
1985
|
+
|
|
1986
|
+
|
|
1987
|
+
* @example
|
|
1988
|
+
* // basic BinaryTree creation and insertion
|
|
1989
|
+
* // Create a BinaryTree with entries
|
|
1990
|
+
* const entries: [number, string][] = [
|
|
1991
|
+
* [6, 'six'],
|
|
1992
|
+
* [1, 'one'],
|
|
1993
|
+
* [2, 'two'],
|
|
1994
|
+
* [7, 'seven'],
|
|
1995
|
+
* [5, 'five'],
|
|
1996
|
+
* [3, 'three'],
|
|
1997
|
+
* [4, 'four'],
|
|
1998
|
+
* [9, 'nine'],
|
|
1999
|
+
* [8, 'eight']
|
|
2000
|
+
* ];
|
|
2001
|
+
*
|
|
2002
|
+
* const tree = new BinaryTree(entries);
|
|
2003
|
+
*
|
|
2004
|
+
* // Verify size
|
|
2005
|
+
* console.log(tree.size); // 9;
|
|
2006
|
+
*
|
|
2007
|
+
* // Add new element
|
|
2008
|
+
* tree.set(10, 'ten');
|
|
2009
|
+
* console.log(tree.size); // 10;
|
|
2010
|
+
*/
|
|
1462
2011
|
set(keyNodeOrEntry, value) {
|
|
1463
2012
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
1464
2013
|
if (newNode === void 0) return false;
|
|
@@ -1503,23 +2052,86 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1503
2052
|
return false;
|
|
1504
2053
|
}
|
|
1505
2054
|
/**
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
2055
|
+
* Adds multiple items to the tree.
|
|
2056
|
+
* @remarks Time O(N * M), where N is the number of items to set and M is the size of the tree at insertion (due to O(M) `set` operation). Space O(M) (from `set`) + O(N) (for the `inserted` array).
|
|
2057
|
+
*
|
|
2058
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
2059
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
2060
|
+
|
|
2061
|
+
|
|
2062
|
+
|
|
2063
|
+
|
|
2064
|
+
|
|
2065
|
+
|
|
2066
|
+
|
|
2067
|
+
|
|
2068
|
+
|
|
2069
|
+
|
|
2070
|
+
|
|
2071
|
+
|
|
2072
|
+
|
|
2073
|
+
|
|
2074
|
+
|
|
2075
|
+
|
|
2076
|
+
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
|
|
2086
|
+
|
|
2087
|
+
|
|
2088
|
+
|
|
2089
|
+
|
|
2090
|
+
* @example
|
|
2091
|
+
* // Bulk add
|
|
2092
|
+
* const tree = new BinaryTree<number>();
|
|
2093
|
+
* tree.addMany([1, 2, 3, 4, 5]);
|
|
2094
|
+
* console.log(tree.size); // 5;
|
|
2095
|
+
*/
|
|
1512
2096
|
addMany(keysNodesEntriesOrRaws) {
|
|
1513
2097
|
return this.setMany(keysNodesEntriesOrRaws);
|
|
1514
2098
|
}
|
|
1515
2099
|
/**
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
2100
|
+
* Adds or updates multiple items to the tree.
|
|
2101
|
+
* @remarks Time O(N * M), where N is the number of items to set and M is the size of the tree at insertion (due to O(M) `set` operation). Space O(M) (from `set`) + O(N) (for the `inserted` array).
|
|
2102
|
+
*
|
|
2103
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set or update.
|
|
2104
|
+
* @param [values] - An optional parallel iterable of values.
|
|
2105
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
2106
|
+
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
|
|
2110
|
+
|
|
2111
|
+
|
|
2112
|
+
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
|
|
2116
|
+
|
|
2117
|
+
|
|
2118
|
+
|
|
2119
|
+
|
|
2120
|
+
|
|
2121
|
+
|
|
2122
|
+
|
|
2123
|
+
|
|
2124
|
+
|
|
2125
|
+
|
|
2126
|
+
|
|
2127
|
+
|
|
2128
|
+
|
|
2129
|
+
* @example
|
|
2130
|
+
* // Set multiple entries
|
|
2131
|
+
* const tree = new BinaryTree<number, string>();
|
|
2132
|
+
* tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
2133
|
+
* console.log(tree.size); // 3;
|
|
2134
|
+
*/
|
|
1523
2135
|
setMany(keysNodesEntriesOrRaws, values) {
|
|
1524
2136
|
const inserted = [];
|
|
1525
2137
|
let valuesIterator;
|
|
@@ -1540,11 +2152,47 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1540
2152
|
return inserted;
|
|
1541
2153
|
}
|
|
1542
2154
|
/**
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
2155
|
+
* Merges another tree into this one by seting all its nodes.
|
|
2156
|
+
* @remarks Time O(N * M), same as `setMany`, where N is the size of `anotherTree` and M is the size of this tree. Space O(M) (from `set`).
|
|
2157
|
+
*
|
|
2158
|
+
* @param anotherTree - The tree to merge.
|
|
2159
|
+
|
|
2160
|
+
|
|
2161
|
+
|
|
2162
|
+
|
|
2163
|
+
|
|
2164
|
+
|
|
2165
|
+
|
|
2166
|
+
|
|
2167
|
+
|
|
2168
|
+
|
|
2169
|
+
|
|
2170
|
+
|
|
2171
|
+
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
|
|
2177
|
+
|
|
2178
|
+
|
|
2179
|
+
|
|
2180
|
+
|
|
2181
|
+
|
|
2182
|
+
|
|
2183
|
+
|
|
2184
|
+
|
|
2185
|
+
|
|
2186
|
+
|
|
2187
|
+
|
|
2188
|
+
|
|
2189
|
+
* @example
|
|
2190
|
+
* // Combine trees
|
|
2191
|
+
* const t1 = new BinaryTree<number>([1, 2]);
|
|
2192
|
+
* const t2 = new BinaryTree<number>([3, 4]);
|
|
2193
|
+
* t1.merge(t2);
|
|
2194
|
+
* console.log(t1.size); // 4;
|
|
2195
|
+
*/
|
|
1548
2196
|
merge(anotherTree) {
|
|
1549
2197
|
this.setMany(anotherTree, []);
|
|
1550
2198
|
}
|
|
@@ -1560,12 +2208,50 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1560
2208
|
this.setMany(keysNodesEntriesOrRaws, values);
|
|
1561
2209
|
}
|
|
1562
2210
|
/**
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
2211
|
+
* Deletes a node from the tree.
|
|
2212
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation finds the node, and if it has two children, swaps it with the rightmost node of its left subtree (in-order predecessor) before deleting. Time O(N) in the worst case. O(N) to find the node (`getNode`) and O(H) (which is O(N) worst-case) to find the rightmost node. Space O(1) (if `getNode` is iterative, which it is).
|
|
2213
|
+
*
|
|
2214
|
+
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
2215
|
+
* @returns An array containing deletion results (for compatibility with self-balancing trees).
|
|
2216
|
+
|
|
2217
|
+
|
|
2218
|
+
|
|
2219
|
+
|
|
2220
|
+
|
|
2221
|
+
|
|
2222
|
+
|
|
2223
|
+
|
|
2224
|
+
|
|
2225
|
+
|
|
2226
|
+
|
|
2227
|
+
|
|
2228
|
+
|
|
2229
|
+
|
|
2230
|
+
|
|
2231
|
+
|
|
2232
|
+
|
|
2233
|
+
|
|
2234
|
+
|
|
2235
|
+
|
|
2236
|
+
|
|
2237
|
+
|
|
2238
|
+
|
|
2239
|
+
|
|
2240
|
+
|
|
2241
|
+
|
|
2242
|
+
|
|
2243
|
+
|
|
2244
|
+
|
|
2245
|
+
|
|
2246
|
+
|
|
2247
|
+
|
|
2248
|
+
* @example
|
|
2249
|
+
* // Remove a node
|
|
2250
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2251
|
+
* tree.delete(3);
|
|
2252
|
+
* console.log(tree.has(3)); // false;
|
|
2253
|
+
* console.log(tree.size); // 4;
|
|
2254
|
+
*/
|
|
1569
2255
|
delete(keyNodeEntryRawOrPredicate) {
|
|
1570
2256
|
const deletedResult = [];
|
|
1571
2257
|
if (!this._root) return deletedResult;
|
|
@@ -1659,14 +2345,48 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1659
2345
|
return this.search(keyNodeEntryOrPredicate, onlyOne, (node) => node, startNode, iterationType);
|
|
1660
2346
|
}
|
|
1661
2347
|
/**
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
2348
|
+
* Gets the first node matching a predicate.
|
|
2349
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Time O(N) in the worst case (via `search`). Space O(H) or O(N) (via `search`).
|
|
2350
|
+
*
|
|
2351
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
2352
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
2353
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2354
|
+
* @returns The first matching node, or undefined if not found.
|
|
2355
|
+
|
|
2356
|
+
|
|
2357
|
+
|
|
2358
|
+
|
|
2359
|
+
|
|
2360
|
+
|
|
2361
|
+
|
|
2362
|
+
|
|
2363
|
+
|
|
2364
|
+
|
|
2365
|
+
|
|
2366
|
+
|
|
2367
|
+
|
|
2368
|
+
|
|
2369
|
+
|
|
2370
|
+
|
|
2371
|
+
|
|
2372
|
+
|
|
2373
|
+
|
|
2374
|
+
|
|
2375
|
+
|
|
2376
|
+
|
|
2377
|
+
|
|
2378
|
+
|
|
2379
|
+
|
|
2380
|
+
|
|
2381
|
+
|
|
2382
|
+
|
|
2383
|
+
|
|
2384
|
+
|
|
2385
|
+
* @example
|
|
2386
|
+
* // Get node by key
|
|
2387
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
|
|
2388
|
+
* console.log(tree.getNode(2)?.value); // 'child';
|
|
2389
|
+
*/
|
|
1670
2390
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1671
2391
|
if (this._isMapMode && keyNodeEntryOrPredicate !== null && keyNodeEntryOrPredicate !== void 0) {
|
|
1672
2392
|
if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
@@ -1678,14 +2398,51 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1678
2398
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType)[0];
|
|
1679
2399
|
}
|
|
1680
2400
|
/**
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
2401
|
+
* Gets the value associated with a key.
|
|
2402
|
+
* @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Time O(1) if in Map mode. O(N) if not in Map mode (uses `getNode`). Space O(1) if in Map mode. O(H) or O(N) otherwise.
|
|
2403
|
+
*
|
|
2404
|
+
* @param keyNodeEntryOrPredicate - The key, node, or entry to get the value for.
|
|
2405
|
+
* @param [startNode=this._root] - The node to start searching from (if not in Map mode).
|
|
2406
|
+
* @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
|
|
2407
|
+
* @returns The associated value, or undefined.
|
|
2408
|
+
|
|
2409
|
+
|
|
2410
|
+
|
|
2411
|
+
|
|
2412
|
+
|
|
2413
|
+
|
|
2414
|
+
|
|
2415
|
+
|
|
2416
|
+
|
|
2417
|
+
|
|
2418
|
+
|
|
2419
|
+
|
|
2420
|
+
|
|
2421
|
+
|
|
2422
|
+
|
|
2423
|
+
|
|
2424
|
+
|
|
2425
|
+
|
|
2426
|
+
|
|
2427
|
+
|
|
2428
|
+
|
|
2429
|
+
|
|
2430
|
+
|
|
2431
|
+
|
|
2432
|
+
|
|
2433
|
+
|
|
2434
|
+
|
|
2435
|
+
|
|
2436
|
+
|
|
2437
|
+
|
|
2438
|
+
|
|
2439
|
+
|
|
2440
|
+
* @example
|
|
2441
|
+
* // Retrieve value by key
|
|
2442
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
|
|
2443
|
+
* console.log(tree.get(2)); // 'left';
|
|
2444
|
+
* console.log(tree.get(99)); // undefined;
|
|
2445
|
+
*/
|
|
1689
2446
|
get(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1690
2447
|
if (this._isMapMode) {
|
|
1691
2448
|
const key = this._extractKey(keyNodeEntryOrPredicate);
|
|
@@ -1705,19 +2462,87 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1705
2462
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType).length > 0;
|
|
1706
2463
|
}
|
|
1707
2464
|
/**
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
2465
|
+
* Clears the tree of all nodes and values.
|
|
2466
|
+
* @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
|
|
2467
|
+
|
|
2468
|
+
|
|
2469
|
+
|
|
2470
|
+
|
|
2471
|
+
|
|
2472
|
+
|
|
2473
|
+
|
|
2474
|
+
|
|
2475
|
+
|
|
2476
|
+
|
|
2477
|
+
|
|
2478
|
+
|
|
2479
|
+
|
|
2480
|
+
|
|
2481
|
+
|
|
2482
|
+
|
|
2483
|
+
|
|
2484
|
+
|
|
2485
|
+
|
|
2486
|
+
|
|
2487
|
+
|
|
2488
|
+
|
|
2489
|
+
|
|
2490
|
+
|
|
2491
|
+
|
|
2492
|
+
|
|
2493
|
+
|
|
2494
|
+
|
|
2495
|
+
|
|
2496
|
+
|
|
2497
|
+
* @example
|
|
2498
|
+
* // Remove all nodes
|
|
2499
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2500
|
+
* tree.clear();
|
|
2501
|
+
* console.log(tree.isEmpty()); // true;
|
|
2502
|
+
*/
|
|
1711
2503
|
clear() {
|
|
1712
2504
|
this._clearNodes();
|
|
1713
2505
|
if (this._isMapMode) this._clearValues();
|
|
1714
2506
|
}
|
|
1715
2507
|
/**
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
2508
|
+
* Checks if the tree is empty.
|
|
2509
|
+
* @remarks Time O(1), Space O(1)
|
|
2510
|
+
*
|
|
2511
|
+
* @returns True if the tree has no nodes, false otherwise.
|
|
2512
|
+
|
|
2513
|
+
|
|
2514
|
+
|
|
2515
|
+
|
|
2516
|
+
|
|
2517
|
+
|
|
2518
|
+
|
|
2519
|
+
|
|
2520
|
+
|
|
2521
|
+
|
|
2522
|
+
|
|
2523
|
+
|
|
2524
|
+
|
|
2525
|
+
|
|
2526
|
+
|
|
2527
|
+
|
|
2528
|
+
|
|
2529
|
+
|
|
2530
|
+
|
|
2531
|
+
|
|
2532
|
+
|
|
2533
|
+
|
|
2534
|
+
|
|
2535
|
+
|
|
2536
|
+
|
|
2537
|
+
|
|
2538
|
+
|
|
2539
|
+
|
|
2540
|
+
|
|
2541
|
+
|
|
2542
|
+
* @example
|
|
2543
|
+
* // Check empty
|
|
2544
|
+
* console.log(new BinaryTree().isEmpty()); // true;
|
|
2545
|
+
*/
|
|
1721
2546
|
isEmpty() {
|
|
1722
2547
|
return this._size === 0;
|
|
1723
2548
|
}
|
|
@@ -1732,13 +2557,48 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1732
2557
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
1733
2558
|
}
|
|
1734
2559
|
/**
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
2560
|
+
* Checks if the tree is a valid Binary Search Tree (BST).
|
|
2561
|
+
* @remarks Time O(N), as it must visit every node. Space O(H) for the call stack (recursive) or explicit stack (iterative), where H is the tree height (O(N) worst-case).
|
|
2562
|
+
*
|
|
2563
|
+
* @param [startNode=this._root] - The node to start checking from.
|
|
2564
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2565
|
+
* @returns True if it's a valid BST, false otherwise.
|
|
2566
|
+
|
|
2567
|
+
|
|
2568
|
+
|
|
2569
|
+
|
|
2570
|
+
|
|
2571
|
+
|
|
2572
|
+
|
|
2573
|
+
|
|
2574
|
+
|
|
2575
|
+
|
|
2576
|
+
|
|
2577
|
+
|
|
2578
|
+
|
|
2579
|
+
|
|
2580
|
+
|
|
2581
|
+
|
|
2582
|
+
|
|
2583
|
+
|
|
2584
|
+
|
|
2585
|
+
|
|
2586
|
+
|
|
2587
|
+
|
|
2588
|
+
|
|
2589
|
+
|
|
2590
|
+
|
|
2591
|
+
|
|
2592
|
+
|
|
2593
|
+
|
|
2594
|
+
|
|
2595
|
+
|
|
2596
|
+
* @example
|
|
2597
|
+
* // Check BST property
|
|
2598
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2599
|
+
* // BinaryTree doesn't guarantee BST order
|
|
2600
|
+
* console.log(typeof tree.isBST()); // 'boolean';
|
|
2601
|
+
*/
|
|
1742
2602
|
isBST(startNode = this._root, iterationType = this.iterationType) {
|
|
1743
2603
|
const startNodeSired = this.ensureNode(startNode);
|
|
1744
2604
|
if (!startNodeSired) return true;
|
|
@@ -1776,13 +2636,50 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1776
2636
|
}
|
|
1777
2637
|
}
|
|
1778
2638
|
/**
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
2639
|
+
* Gets the depth of a node (distance from `startNode`).
|
|
2640
|
+
* @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
|
|
2641
|
+
*
|
|
2642
|
+
* @param dist - The node to find the depth of.
|
|
2643
|
+
* @param [startNode=this._root] - The node to measure depth from (defaults to root).
|
|
2644
|
+
* @returns The depth (0 if `dist` is `startNode`).
|
|
2645
|
+
|
|
2646
|
+
|
|
2647
|
+
|
|
2648
|
+
|
|
2649
|
+
|
|
2650
|
+
|
|
2651
|
+
|
|
2652
|
+
|
|
2653
|
+
|
|
2654
|
+
|
|
2655
|
+
|
|
2656
|
+
|
|
2657
|
+
|
|
2658
|
+
|
|
2659
|
+
|
|
2660
|
+
|
|
2661
|
+
|
|
2662
|
+
|
|
2663
|
+
|
|
2664
|
+
|
|
2665
|
+
|
|
2666
|
+
|
|
2667
|
+
|
|
2668
|
+
|
|
2669
|
+
|
|
2670
|
+
|
|
2671
|
+
|
|
2672
|
+
|
|
2673
|
+
|
|
2674
|
+
|
|
2675
|
+
|
|
2676
|
+
|
|
2677
|
+
* @example
|
|
2678
|
+
* // Get depth of a node
|
|
2679
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2680
|
+
* const node = tree.getNode(4);
|
|
2681
|
+
* console.log(tree.getDepth(node!)); // 2;
|
|
2682
|
+
*/
|
|
1786
2683
|
getDepth(dist, startNode = this._root) {
|
|
1787
2684
|
let distEnsured = this.ensureNode(dist);
|
|
1788
2685
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
@@ -1797,13 +2694,49 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1797
2694
|
return depth;
|
|
1798
2695
|
}
|
|
1799
2696
|
/**
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
2697
|
+
* Gets the maximum height of the tree (longest path from startNode to a leaf).
|
|
2698
|
+
* @remarks Time O(N), as it must visit every node. Space O(H) for recursive stack (O(N) worst-case) or O(N) for iterative stack (storing node + depth).
|
|
2699
|
+
*
|
|
2700
|
+
* @param [startNode=this._root] - The node to start measuring from.
|
|
2701
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2702
|
+
* @returns The height ( -1 for an empty tree, 0 for a single-node tree).
|
|
2703
|
+
|
|
2704
|
+
|
|
2705
|
+
|
|
2706
|
+
|
|
2707
|
+
|
|
2708
|
+
|
|
2709
|
+
|
|
2710
|
+
|
|
2711
|
+
|
|
2712
|
+
|
|
2713
|
+
|
|
2714
|
+
|
|
2715
|
+
|
|
2716
|
+
|
|
2717
|
+
|
|
2718
|
+
|
|
2719
|
+
|
|
2720
|
+
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
|
|
2728
|
+
|
|
2729
|
+
|
|
2730
|
+
|
|
2731
|
+
|
|
2732
|
+
|
|
2733
|
+
|
|
2734
|
+
|
|
2735
|
+
* @example
|
|
2736
|
+
* // Get tree height
|
|
2737
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2738
|
+
* console.log(tree.getHeight()); // 2;
|
|
2739
|
+
*/
|
|
1807
2740
|
getHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
1808
2741
|
startNode = this.ensureNode(startNode);
|
|
1809
2742
|
if (!this.isRealNode(startNode)) return -1;
|
|
@@ -2239,24 +3172,95 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2239
3172
|
return ans;
|
|
2240
3173
|
}
|
|
2241
3174
|
/**
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
3175
|
+
* Clones the tree.
|
|
3176
|
+
* @remarks Time O(N * M), where N is the number of nodes and M is the tree size during insertion (due to `bfs` + `set`, and `set` is O(M)). Space O(N) for the new tree and the BFS queue.
|
|
3177
|
+
*
|
|
3178
|
+
* @returns A new, cloned instance of the tree.
|
|
3179
|
+
|
|
3180
|
+
|
|
3181
|
+
|
|
3182
|
+
|
|
3183
|
+
|
|
3184
|
+
|
|
3185
|
+
|
|
3186
|
+
|
|
3187
|
+
|
|
3188
|
+
|
|
3189
|
+
|
|
3190
|
+
|
|
3191
|
+
|
|
3192
|
+
|
|
3193
|
+
|
|
3194
|
+
|
|
3195
|
+
|
|
3196
|
+
|
|
3197
|
+
|
|
3198
|
+
|
|
3199
|
+
|
|
3200
|
+
|
|
3201
|
+
|
|
3202
|
+
|
|
3203
|
+
|
|
3204
|
+
|
|
3205
|
+
|
|
3206
|
+
|
|
3207
|
+
|
|
3208
|
+
|
|
3209
|
+
* @example
|
|
3210
|
+
* // Deep copy
|
|
3211
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
3212
|
+
* const copy = tree.clone();
|
|
3213
|
+
* copy.delete(1);
|
|
3214
|
+
* console.log(tree.has(1)); // true;
|
|
3215
|
+
*/
|
|
2247
3216
|
clone() {
|
|
2248
3217
|
const out = this._createInstance();
|
|
2249
3218
|
this._clone(out);
|
|
2250
3219
|
return out;
|
|
2251
3220
|
}
|
|
2252
3221
|
/**
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
3222
|
+
* Creates a new tree containing only the entries that satisfy the predicate.
|
|
3223
|
+
* @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion (O(N) iteration + O(M) `set` for each item). Space O(N) for the new tree.
|
|
3224
|
+
*
|
|
3225
|
+
* @param predicate - A function to test each [key, value] pair.
|
|
3226
|
+
* @param [thisArg] - `this` context for the predicate.
|
|
3227
|
+
* @returns A new, filtered tree.
|
|
3228
|
+
|
|
3229
|
+
|
|
3230
|
+
|
|
3231
|
+
|
|
3232
|
+
|
|
3233
|
+
|
|
3234
|
+
|
|
3235
|
+
|
|
3236
|
+
|
|
3237
|
+
|
|
3238
|
+
|
|
3239
|
+
|
|
3240
|
+
|
|
3241
|
+
|
|
3242
|
+
|
|
3243
|
+
|
|
3244
|
+
|
|
3245
|
+
|
|
3246
|
+
|
|
3247
|
+
|
|
3248
|
+
|
|
3249
|
+
|
|
3250
|
+
|
|
3251
|
+
|
|
3252
|
+
|
|
3253
|
+
|
|
3254
|
+
|
|
3255
|
+
|
|
3256
|
+
|
|
3257
|
+
|
|
3258
|
+
* @example
|
|
3259
|
+
* // Filter nodes by condition
|
|
3260
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4]);
|
|
3261
|
+
* const result = tree.filter((_, key) => key > 2);
|
|
3262
|
+
* console.log(result.size); // 2;
|
|
3263
|
+
*/
|
|
2260
3264
|
filter(predicate, thisArg) {
|
|
2261
3265
|
const out = this._createInstance();
|
|
2262
3266
|
let i = 0;
|
|
@@ -2264,17 +3268,52 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2264
3268
|
return out;
|
|
2265
3269
|
}
|
|
2266
3270
|
/**
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
3271
|
+
* Creates a new tree by mapping each [key, value] pair to a new entry.
|
|
3272
|
+
* @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion. Space O(N) for the new tree.
|
|
3273
|
+
*
|
|
3274
|
+
* @template MK - New key type.
|
|
3275
|
+
* @template MV - New value type.
|
|
3276
|
+
* @template MR - New raw type.
|
|
3277
|
+
* @param cb - A function to map each [key, value] pair.
|
|
3278
|
+
* @param [options] - Options for the new tree.
|
|
3279
|
+
* @param [thisArg] - `this` context for the callback.
|
|
3280
|
+
* @returns A new, mapped tree.
|
|
3281
|
+
|
|
3282
|
+
|
|
3283
|
+
|
|
3284
|
+
|
|
3285
|
+
|
|
3286
|
+
|
|
3287
|
+
|
|
3288
|
+
|
|
3289
|
+
|
|
3290
|
+
|
|
3291
|
+
|
|
3292
|
+
|
|
3293
|
+
|
|
3294
|
+
|
|
3295
|
+
|
|
3296
|
+
|
|
3297
|
+
|
|
3298
|
+
|
|
3299
|
+
|
|
3300
|
+
|
|
3301
|
+
|
|
3302
|
+
|
|
3303
|
+
|
|
3304
|
+
|
|
3305
|
+
|
|
3306
|
+
|
|
3307
|
+
|
|
3308
|
+
|
|
3309
|
+
|
|
3310
|
+
|
|
3311
|
+
* @example
|
|
3312
|
+
* // Transform to new tree
|
|
3313
|
+
* const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
|
|
3314
|
+
* const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
|
|
3315
|
+
* console.log([...mapped.values()]); // contains 11;
|
|
3316
|
+
*/
|
|
2278
3317
|
map(cb, options, thisArg) {
|
|
2279
3318
|
const out = this._createLike([], options);
|
|
2280
3319
|
let i = 0;
|
|
@@ -2312,12 +3351,46 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2312
3351
|
return output;
|
|
2313
3352
|
}
|
|
2314
3353
|
/**
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
3354
|
+
* Prints a visual representation of the tree to the console.
|
|
3355
|
+
* @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
|
|
3356
|
+
*
|
|
3357
|
+
* @param [options] - Options to control the output.
|
|
3358
|
+
* @param [startNode=this._root] - The node to start printing from.
|
|
3359
|
+
|
|
3360
|
+
|
|
3361
|
+
|
|
3362
|
+
|
|
3363
|
+
|
|
3364
|
+
|
|
3365
|
+
|
|
3366
|
+
|
|
3367
|
+
|
|
3368
|
+
|
|
3369
|
+
|
|
3370
|
+
|
|
3371
|
+
|
|
3372
|
+
|
|
3373
|
+
|
|
3374
|
+
|
|
3375
|
+
|
|
3376
|
+
|
|
3377
|
+
|
|
3378
|
+
|
|
3379
|
+
|
|
3380
|
+
|
|
3381
|
+
|
|
3382
|
+
|
|
3383
|
+
|
|
3384
|
+
|
|
3385
|
+
|
|
3386
|
+
|
|
3387
|
+
|
|
3388
|
+
|
|
3389
|
+
* @example
|
|
3390
|
+
* // Display tree
|
|
3391
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
3392
|
+
* expect(() => tree.print()).not.toThrow();
|
|
3393
|
+
*/
|
|
2321
3394
|
print(options, startNode = this._root) {
|
|
2322
3395
|
console.log(this.toVisual(startNode, options));
|
|
2323
3396
|
}
|
|
@@ -2556,7 +3629,6 @@ var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2556
3629
|
* @returns Layout information for this subtree.
|
|
2557
3630
|
*/
|
|
2558
3631
|
_displayAux(node, options) {
|
|
2559
|
-
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
2560
3632
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
2561
3633
|
const newFrame = /* @__PURE__ */ __name((n) => ({
|
|
2562
3634
|
node: n,
|
|
@@ -2852,6 +3924,7 @@ var BSTNode = class {
|
|
|
2852
3924
|
*
|
|
2853
3925
|
* @returns The height.
|
|
2854
3926
|
*/
|
|
3927
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
2855
3928
|
get height() {
|
|
2856
3929
|
return this._height;
|
|
2857
3930
|
}
|
|
@@ -2861,6 +3934,7 @@ var BSTNode = class {
|
|
|
2861
3934
|
*
|
|
2862
3935
|
* @param value - The new height.
|
|
2863
3936
|
*/
|
|
3937
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
2864
3938
|
set height(value) {
|
|
2865
3939
|
this._height = value;
|
|
2866
3940
|
}
|
|
@@ -2871,6 +3945,7 @@ var BSTNode = class {
|
|
|
2871
3945
|
*
|
|
2872
3946
|
* @returns The node's color.
|
|
2873
3947
|
*/
|
|
3948
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
2874
3949
|
get color() {
|
|
2875
3950
|
return this._color;
|
|
2876
3951
|
}
|
|
@@ -2880,6 +3955,7 @@ var BSTNode = class {
|
|
|
2880
3955
|
*
|
|
2881
3956
|
* @param value - The new color.
|
|
2882
3957
|
*/
|
|
3958
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
2883
3959
|
set color(value) {
|
|
2884
3960
|
this._color = value;
|
|
2885
3961
|
}
|
|
@@ -2890,6 +3966,7 @@ var BSTNode = class {
|
|
|
2890
3966
|
*
|
|
2891
3967
|
* @returns The subtree node count.
|
|
2892
3968
|
*/
|
|
3969
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
2893
3970
|
get count() {
|
|
2894
3971
|
return this._count;
|
|
2895
3972
|
}
|
|
@@ -2899,6 +3976,7 @@ var BSTNode = class {
|
|
|
2899
3976
|
*
|
|
2900
3977
|
* @param value - The new count.
|
|
2901
3978
|
*/
|
|
3979
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
2902
3980
|
set count(value) {
|
|
2903
3981
|
this._count = value;
|
|
2904
3982
|
}
|
|
@@ -3053,14 +4131,81 @@ var BST = class extends BinaryTree {
|
|
|
3053
4131
|
return super.listLevels(callback, startNode, iterationType, false);
|
|
3054
4132
|
}
|
|
3055
4133
|
/**
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
4134
|
+
* Gets the first node matching a predicate.
|
|
4135
|
+
* @remarks Time O(log N) if searching by key, O(N) if searching by predicate. Space O(log N) or O(N).
|
|
4136
|
+
*
|
|
4137
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
4138
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
4139
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
4140
|
+
* @returns The first matching node, or undefined if not found.
|
|
4141
|
+
|
|
4142
|
+
|
|
4143
|
+
|
|
4144
|
+
|
|
4145
|
+
|
|
4146
|
+
|
|
4147
|
+
|
|
4148
|
+
|
|
4149
|
+
|
|
4150
|
+
|
|
4151
|
+
|
|
4152
|
+
|
|
4153
|
+
|
|
4154
|
+
|
|
4155
|
+
|
|
4156
|
+
|
|
4157
|
+
|
|
4158
|
+
|
|
4159
|
+
|
|
4160
|
+
|
|
4161
|
+
|
|
4162
|
+
|
|
4163
|
+
|
|
4164
|
+
|
|
4165
|
+
|
|
4166
|
+
|
|
4167
|
+
|
|
4168
|
+
|
|
4169
|
+
|
|
4170
|
+
|
|
4171
|
+
|
|
4172
|
+
|
|
4173
|
+
|
|
4174
|
+
|
|
4175
|
+
|
|
4176
|
+
|
|
4177
|
+
|
|
4178
|
+
|
|
4179
|
+
|
|
4180
|
+
|
|
4181
|
+
|
|
4182
|
+
|
|
4183
|
+
|
|
4184
|
+
|
|
4185
|
+
|
|
4186
|
+
|
|
4187
|
+
|
|
4188
|
+
|
|
4189
|
+
|
|
4190
|
+
|
|
4191
|
+
|
|
4192
|
+
|
|
4193
|
+
|
|
4194
|
+
|
|
4195
|
+
|
|
4196
|
+
|
|
4197
|
+
|
|
4198
|
+
|
|
4199
|
+
|
|
4200
|
+
|
|
4201
|
+
|
|
4202
|
+
* @example
|
|
4203
|
+
* // Get node object by key
|
|
4204
|
+
* const bst = new BST<number, string>([[5, 'root'], [3, 'left'], [7, 'right']]);
|
|
4205
|
+
* const node = bst.getNode(3);
|
|
4206
|
+
* console.log(node?.key); // 3;
|
|
4207
|
+
* console.log(node?.value); // 'left';
|
|
4208
|
+
*/
|
|
3064
4209
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
3065
4210
|
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === void 0) return void 0;
|
|
3066
4211
|
if (this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
@@ -3209,13 +4354,107 @@ var BST = class extends BinaryTree {
|
|
|
3209
4354
|
return this.search(searchRange, false, callback, startNode, iterationType);
|
|
3210
4355
|
}
|
|
3211
4356
|
/**
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
4357
|
+
* Adds a new node to the BST based on key comparison.
|
|
4358
|
+
* @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
|
|
4359
|
+
*
|
|
4360
|
+
* @param keyNodeOrEntry - The key, node, or entry to set.
|
|
4361
|
+
* @param [value] - The value, if providing just a key.
|
|
4362
|
+
* @returns True if the addition was successful, false otherwise.
|
|
4363
|
+
|
|
4364
|
+
|
|
4365
|
+
|
|
4366
|
+
|
|
4367
|
+
|
|
4368
|
+
|
|
4369
|
+
|
|
4370
|
+
|
|
4371
|
+
|
|
4372
|
+
|
|
4373
|
+
|
|
4374
|
+
|
|
4375
|
+
|
|
4376
|
+
|
|
4377
|
+
|
|
4378
|
+
|
|
4379
|
+
|
|
4380
|
+
|
|
4381
|
+
|
|
4382
|
+
|
|
4383
|
+
|
|
4384
|
+
|
|
4385
|
+
|
|
4386
|
+
|
|
4387
|
+
|
|
4388
|
+
|
|
4389
|
+
|
|
4390
|
+
|
|
4391
|
+
|
|
4392
|
+
|
|
4393
|
+
|
|
4394
|
+
|
|
4395
|
+
|
|
4396
|
+
|
|
4397
|
+
|
|
4398
|
+
|
|
4399
|
+
|
|
4400
|
+
|
|
4401
|
+
|
|
4402
|
+
|
|
4403
|
+
|
|
4404
|
+
|
|
4405
|
+
|
|
4406
|
+
|
|
4407
|
+
|
|
4408
|
+
|
|
4409
|
+
|
|
4410
|
+
|
|
4411
|
+
|
|
4412
|
+
|
|
4413
|
+
|
|
4414
|
+
|
|
4415
|
+
|
|
4416
|
+
|
|
4417
|
+
|
|
4418
|
+
|
|
4419
|
+
|
|
4420
|
+
|
|
4421
|
+
|
|
4422
|
+
|
|
4423
|
+
|
|
4424
|
+
|
|
4425
|
+
|
|
4426
|
+
|
|
4427
|
+
|
|
4428
|
+
|
|
4429
|
+
|
|
4430
|
+
|
|
4431
|
+
|
|
4432
|
+
|
|
4433
|
+
|
|
4434
|
+
|
|
4435
|
+
|
|
4436
|
+
|
|
4437
|
+
|
|
4438
|
+
|
|
4439
|
+
|
|
4440
|
+
|
|
4441
|
+
|
|
4442
|
+
|
|
4443
|
+
|
|
4444
|
+
|
|
4445
|
+
|
|
4446
|
+
|
|
4447
|
+
|
|
4448
|
+
|
|
4449
|
+
|
|
4450
|
+
|
|
4451
|
+
* @example
|
|
4452
|
+
* // Set a key-value pair
|
|
4453
|
+
* const bst = new BST<number, string>();
|
|
4454
|
+
* bst.set(1, 'one');
|
|
4455
|
+
* bst.set(2, 'two');
|
|
4456
|
+
* console.log(bst.get(1)); // 'one';
|
|
4457
|
+
*/
|
|
3219
4458
|
set(keyNodeOrEntry, value) {
|
|
3220
4459
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
3221
4460
|
if (newNode === void 0) return false;
|
|
@@ -3252,17 +4491,76 @@ var BST = class extends BinaryTree {
|
|
|
3252
4491
|
return false;
|
|
3253
4492
|
}
|
|
3254
4493
|
/**
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
4494
|
+
* Adds multiple items to the tree.
|
|
4495
|
+
* @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced set).
|
|
4496
|
+
* If false, adds items one by one. Time O(N * H), which is O(N^2) worst-case.
|
|
4497
|
+
* Space O(N) for sorting and recursion/iteration stack.
|
|
4498
|
+
*
|
|
4499
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
4500
|
+
* @param [values] - An optional parallel iterable of values.
|
|
4501
|
+
* @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
|
|
4502
|
+
* @param [iterationType=this.iterationType] - The traversal method for balanced set (recursive or iterative).
|
|
4503
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
4504
|
+
|
|
4505
|
+
|
|
4506
|
+
|
|
4507
|
+
|
|
4508
|
+
|
|
4509
|
+
|
|
4510
|
+
|
|
4511
|
+
|
|
4512
|
+
|
|
4513
|
+
|
|
4514
|
+
|
|
4515
|
+
|
|
4516
|
+
|
|
4517
|
+
|
|
4518
|
+
|
|
4519
|
+
|
|
4520
|
+
|
|
4521
|
+
|
|
4522
|
+
|
|
4523
|
+
|
|
4524
|
+
|
|
4525
|
+
|
|
4526
|
+
|
|
4527
|
+
|
|
4528
|
+
|
|
4529
|
+
|
|
4530
|
+
|
|
4531
|
+
|
|
4532
|
+
|
|
4533
|
+
|
|
4534
|
+
|
|
4535
|
+
|
|
4536
|
+
|
|
4537
|
+
|
|
4538
|
+
|
|
4539
|
+
|
|
4540
|
+
|
|
4541
|
+
|
|
4542
|
+
|
|
4543
|
+
|
|
4544
|
+
|
|
4545
|
+
|
|
4546
|
+
|
|
4547
|
+
|
|
4548
|
+
|
|
4549
|
+
|
|
4550
|
+
|
|
4551
|
+
|
|
4552
|
+
|
|
4553
|
+
|
|
4554
|
+
|
|
4555
|
+
|
|
4556
|
+
|
|
4557
|
+
* @example
|
|
4558
|
+
* // Set multiple key-value pairs
|
|
4559
|
+
* const bst = new BST<number, string>();
|
|
4560
|
+
* bst.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
4561
|
+
* console.log(bst.size); // 3;
|
|
4562
|
+
* console.log(bst.get(2)); // 'b';
|
|
4563
|
+
*/
|
|
3266
4564
|
setMany(keysNodesEntriesOrRaws, values, isBalanceAdd = true, iterationType = this.iterationType) {
|
|
3267
4565
|
const inserted = [];
|
|
3268
4566
|
const valuesIterator = values?.[Symbol.iterator]();
|
|
@@ -3505,12 +4803,50 @@ var BST = class extends BinaryTree {
|
|
|
3505
4803
|
}
|
|
3506
4804
|
}
|
|
3507
4805
|
/**
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
4806
|
+
* Rebuilds the tree to be perfectly balanced.
|
|
4807
|
+
* @remarks Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
|
|
4808
|
+
*
|
|
4809
|
+
* @param [iterationType=this.iterationType] - The traversal method for the initial node export.
|
|
4810
|
+
* @returns True if successful, false if the tree was empty.
|
|
4811
|
+
|
|
4812
|
+
|
|
4813
|
+
|
|
4814
|
+
|
|
4815
|
+
|
|
4816
|
+
|
|
4817
|
+
|
|
4818
|
+
|
|
4819
|
+
|
|
4820
|
+
|
|
4821
|
+
|
|
4822
|
+
|
|
4823
|
+
|
|
4824
|
+
|
|
4825
|
+
|
|
4826
|
+
|
|
4827
|
+
|
|
4828
|
+
|
|
4829
|
+
|
|
4830
|
+
|
|
4831
|
+
|
|
4832
|
+
|
|
4833
|
+
|
|
4834
|
+
|
|
4835
|
+
|
|
4836
|
+
|
|
4837
|
+
|
|
4838
|
+
|
|
4839
|
+
|
|
4840
|
+
|
|
4841
|
+
* @example
|
|
4842
|
+
* // Rebalance the tree
|
|
4843
|
+
* const bst = new BST<number>();
|
|
4844
|
+
* // Insert in sorted order (worst case for BST)
|
|
4845
|
+
* for (let i = 1; i <= 7; i++) bst.add(i);
|
|
4846
|
+
* console.log(bst.isAVLBalanced()); // false;
|
|
4847
|
+
* bst.perfectlyBalance();
|
|
4848
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
4849
|
+
*/
|
|
3514
4850
|
perfectlyBalance(iterationType = this.iterationType) {
|
|
3515
4851
|
const nodes = this.dfs((node) => node, "IN", false, this._root, iterationType);
|
|
3516
4852
|
const n = nodes.length;
|
|
@@ -3533,12 +4869,46 @@ var BST = class extends BinaryTree {
|
|
|
3533
4869
|
return true;
|
|
3534
4870
|
}
|
|
3535
4871
|
/**
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
4872
|
+
* Checks if the tree meets the AVL balance condition (height difference <= 1).
|
|
4873
|
+
* @remarks Time O(N), as it must visit every node to compute height. Space O(log N) for recursion or O(N) for iterative map.
|
|
4874
|
+
*
|
|
4875
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
4876
|
+
* @returns True if the tree is AVL balanced, false otherwise.
|
|
4877
|
+
|
|
4878
|
+
|
|
4879
|
+
|
|
4880
|
+
|
|
4881
|
+
|
|
4882
|
+
|
|
4883
|
+
|
|
4884
|
+
|
|
4885
|
+
|
|
4886
|
+
|
|
4887
|
+
|
|
4888
|
+
|
|
4889
|
+
|
|
4890
|
+
|
|
4891
|
+
|
|
4892
|
+
|
|
4893
|
+
|
|
4894
|
+
|
|
4895
|
+
|
|
4896
|
+
|
|
4897
|
+
|
|
4898
|
+
|
|
4899
|
+
|
|
4900
|
+
|
|
4901
|
+
|
|
4902
|
+
|
|
4903
|
+
|
|
4904
|
+
|
|
4905
|
+
|
|
4906
|
+
|
|
4907
|
+
* @example
|
|
4908
|
+
* // Check if tree is height-balanced
|
|
4909
|
+
* const bst = new BST<number>([3, 1, 5, 2, 4]);
|
|
4910
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
4911
|
+
*/
|
|
3542
4912
|
isAVLBalanced(iterationType = this.iterationType) {
|
|
3543
4913
|
if (!this._root) return true;
|
|
3544
4914
|
let balanced = true;
|
|
@@ -3578,18 +4948,84 @@ var BST = class extends BinaryTree {
|
|
|
3578
4948
|
return balanced;
|
|
3579
4949
|
}
|
|
3580
4950
|
/**
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
4951
|
+
* Creates a new BST by mapping each [key, value] pair to a new entry.
|
|
4952
|
+
* @remarks Time O(N * H), where N is nodes in this tree, and H is height of the new tree during insertion.
|
|
4953
|
+
* Space O(N) for the new tree.
|
|
4954
|
+
*
|
|
4955
|
+
* @template MK - New key type.
|
|
4956
|
+
* @template MV - New value type.
|
|
4957
|
+
* @template MR - New raw type.
|
|
4958
|
+
* @param callback - A function to map each [key, value] pair.
|
|
4959
|
+
* @param [options] - Options for the new BST.
|
|
4960
|
+
* @param [thisArg] - `this` context for the callback.
|
|
4961
|
+
* @returns A new, mapped BST.
|
|
4962
|
+
|
|
4963
|
+
|
|
4964
|
+
|
|
4965
|
+
|
|
4966
|
+
|
|
4967
|
+
|
|
4968
|
+
|
|
4969
|
+
|
|
4970
|
+
|
|
4971
|
+
|
|
4972
|
+
|
|
4973
|
+
|
|
4974
|
+
|
|
4975
|
+
|
|
4976
|
+
|
|
4977
|
+
|
|
4978
|
+
|
|
4979
|
+
|
|
4980
|
+
|
|
4981
|
+
|
|
4982
|
+
|
|
4983
|
+
|
|
4984
|
+
|
|
4985
|
+
|
|
4986
|
+
|
|
4987
|
+
|
|
4988
|
+
|
|
4989
|
+
|
|
4990
|
+
|
|
4991
|
+
|
|
4992
|
+
|
|
4993
|
+
|
|
4994
|
+
|
|
4995
|
+
|
|
4996
|
+
|
|
4997
|
+
|
|
4998
|
+
|
|
4999
|
+
|
|
5000
|
+
|
|
5001
|
+
|
|
5002
|
+
|
|
5003
|
+
|
|
5004
|
+
|
|
5005
|
+
|
|
5006
|
+
|
|
5007
|
+
|
|
5008
|
+
|
|
5009
|
+
|
|
5010
|
+
|
|
5011
|
+
|
|
5012
|
+
|
|
5013
|
+
|
|
5014
|
+
|
|
5015
|
+
|
|
5016
|
+
|
|
5017
|
+
|
|
5018
|
+
|
|
5019
|
+
|
|
5020
|
+
|
|
5021
|
+
|
|
5022
|
+
|
|
5023
|
+
* @example
|
|
5024
|
+
* // Transform to new tree
|
|
5025
|
+
* const bst = new BST<number, number>([[1, 10], [2, 20], [3, 30]]);
|
|
5026
|
+
* const doubled = bst.map((value, key) => [key, (value ?? 0) * 2] as [number, number]);
|
|
5027
|
+
* console.log([...doubled.values()]); // [20, 40, 60];
|
|
5028
|
+
*/
|
|
3593
5029
|
map(callback, options, thisArg) {
|
|
3594
5030
|
const out = this._createLike([], options);
|
|
3595
5031
|
let index = 0;
|
|
@@ -4160,15 +5596,12 @@ var AVLTreeNode = class {
|
|
|
4160
5596
|
*
|
|
4161
5597
|
* @returns The node's color.
|
|
4162
5598
|
*/
|
|
5599
|
+
/* istanbul ignore next -- inherited field, used by RedBlackTree subclass */
|
|
5600
|
+
/* istanbul ignore next -- inherited field, not used by AVLTree */
|
|
4163
5601
|
get color() {
|
|
4164
5602
|
return this._color;
|
|
4165
5603
|
}
|
|
4166
|
-
|
|
4167
|
-
* Sets the color of the node.
|
|
4168
|
-
* @remarks Time O(1), Space O(1)
|
|
4169
|
-
*
|
|
4170
|
-
* @param value - The new color.
|
|
4171
|
-
*/
|
|
5604
|
+
/* istanbul ignore next -- inherited field, not used by AVLTree */
|
|
4172
5605
|
set color(value) {
|
|
4173
5606
|
this._color = value;
|
|
4174
5607
|
}
|
|
@@ -4179,15 +5612,11 @@ var AVLTreeNode = class {
|
|
|
4179
5612
|
*
|
|
4180
5613
|
* @returns The subtree node count.
|
|
4181
5614
|
*/
|
|
5615
|
+
/* istanbul ignore next -- inherited field, not used by AVLTree */
|
|
4182
5616
|
get count() {
|
|
4183
5617
|
return this._count;
|
|
4184
5618
|
}
|
|
4185
|
-
|
|
4186
|
-
* Sets the count of nodes in the subtree.
|
|
4187
|
-
* @remarks Time O(1), Space O(1)
|
|
4188
|
-
*
|
|
4189
|
-
* @param value - The new count.
|
|
4190
|
-
*/
|
|
5619
|
+
/* istanbul ignore next -- inherited field, not used by AVLTree */
|
|
4191
5620
|
set count(value) {
|
|
4192
5621
|
this._count = value;
|
|
4193
5622
|
}
|
|
@@ -4246,13 +5675,139 @@ var AVLTree = class extends BST {
|
|
|
4246
5675
|
return keyNodeOrEntry instanceof AVLTreeNode;
|
|
4247
5676
|
}
|
|
4248
5677
|
/**
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
5678
|
+
* Sets a new node to the AVL tree and balances the tree path.
|
|
5679
|
+
* @remarks Time O(log N) (O(H) for BST set + O(H) for `_balancePath`). Space O(H) for path/recursion.
|
|
5680
|
+
*
|
|
5681
|
+
* @param keyNodeOrEntry - The key, node, or entry to set.
|
|
5682
|
+
* @param [value] - The value, if providing just a key.
|
|
5683
|
+
* @returns True if the addition was successful, false otherwise.
|
|
5684
|
+
|
|
5685
|
+
|
|
5686
|
+
|
|
5687
|
+
|
|
5688
|
+
|
|
5689
|
+
|
|
5690
|
+
|
|
5691
|
+
|
|
5692
|
+
|
|
5693
|
+
|
|
5694
|
+
|
|
5695
|
+
|
|
5696
|
+
|
|
5697
|
+
|
|
5698
|
+
|
|
5699
|
+
|
|
5700
|
+
|
|
5701
|
+
|
|
5702
|
+
|
|
5703
|
+
|
|
5704
|
+
|
|
5705
|
+
|
|
5706
|
+
|
|
5707
|
+
|
|
5708
|
+
|
|
5709
|
+
|
|
5710
|
+
|
|
5711
|
+
|
|
5712
|
+
|
|
5713
|
+
|
|
5714
|
+
|
|
5715
|
+
|
|
5716
|
+
|
|
5717
|
+
|
|
5718
|
+
|
|
5719
|
+
|
|
5720
|
+
|
|
5721
|
+
|
|
5722
|
+
|
|
5723
|
+
|
|
5724
|
+
|
|
5725
|
+
|
|
5726
|
+
|
|
5727
|
+
|
|
5728
|
+
|
|
5729
|
+
|
|
5730
|
+
|
|
5731
|
+
|
|
5732
|
+
|
|
5733
|
+
|
|
5734
|
+
|
|
5735
|
+
|
|
5736
|
+
|
|
5737
|
+
|
|
5738
|
+
|
|
5739
|
+
|
|
5740
|
+
|
|
5741
|
+
|
|
5742
|
+
|
|
5743
|
+
|
|
5744
|
+
|
|
5745
|
+
|
|
5746
|
+
|
|
5747
|
+
|
|
5748
|
+
|
|
5749
|
+
|
|
5750
|
+
|
|
5751
|
+
|
|
5752
|
+
|
|
5753
|
+
|
|
5754
|
+
|
|
5755
|
+
|
|
5756
|
+
|
|
5757
|
+
|
|
5758
|
+
|
|
5759
|
+
|
|
5760
|
+
|
|
5761
|
+
|
|
5762
|
+
|
|
5763
|
+
|
|
5764
|
+
|
|
5765
|
+
|
|
5766
|
+
|
|
5767
|
+
|
|
5768
|
+
|
|
5769
|
+
|
|
5770
|
+
|
|
5771
|
+
|
|
5772
|
+
|
|
5773
|
+
|
|
5774
|
+
|
|
5775
|
+
|
|
5776
|
+
|
|
5777
|
+
|
|
5778
|
+
|
|
5779
|
+
|
|
5780
|
+
|
|
5781
|
+
|
|
5782
|
+
|
|
5783
|
+
|
|
5784
|
+
|
|
5785
|
+
|
|
5786
|
+
|
|
5787
|
+
|
|
5788
|
+
|
|
5789
|
+
|
|
5790
|
+
|
|
5791
|
+
|
|
5792
|
+
|
|
5793
|
+
|
|
5794
|
+
|
|
5795
|
+
|
|
5796
|
+
|
|
5797
|
+
|
|
5798
|
+
|
|
5799
|
+
|
|
5800
|
+
|
|
5801
|
+
|
|
5802
|
+
|
|
5803
|
+
|
|
5804
|
+
* @example
|
|
5805
|
+
* // Set a key-value pair
|
|
5806
|
+
* const avl = new AVLTree<number, string>();
|
|
5807
|
+
* avl.set(1, 'one');
|
|
5808
|
+
* avl.set(2, 'two');
|
|
5809
|
+
* console.log(avl.get(1)); // 'one';
|
|
5810
|
+
*/
|
|
4256
5811
|
set(keyNodeOrEntry, value) {
|
|
4257
5812
|
if (keyNodeOrEntry === null) return false;
|
|
4258
5813
|
const inserted = super.set(keyNodeOrEntry, value);
|
|
@@ -4260,12 +5815,114 @@ var AVLTree = class extends BST {
|
|
|
4260
5815
|
return inserted;
|
|
4261
5816
|
}
|
|
4262
5817
|
/**
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
5818
|
+
* Deletes a node from the AVL tree and re-balances the tree.
|
|
5819
|
+
* @remarks Time O(log N) (O(H) for BST delete + O(H) for `_balancePath`). Space O(H) for path/recursion.
|
|
5820
|
+
*
|
|
5821
|
+
* @param keyNodeOrEntry - The node to delete.
|
|
5822
|
+
* @returns An array containing deletion results.
|
|
5823
|
+
|
|
5824
|
+
|
|
5825
|
+
|
|
5826
|
+
|
|
5827
|
+
|
|
5828
|
+
|
|
5829
|
+
|
|
5830
|
+
|
|
5831
|
+
|
|
5832
|
+
|
|
5833
|
+
|
|
5834
|
+
|
|
5835
|
+
|
|
5836
|
+
|
|
5837
|
+
|
|
5838
|
+
|
|
5839
|
+
|
|
5840
|
+
|
|
5841
|
+
|
|
5842
|
+
|
|
5843
|
+
|
|
5844
|
+
|
|
5845
|
+
|
|
5846
|
+
|
|
5847
|
+
|
|
5848
|
+
|
|
5849
|
+
|
|
5850
|
+
|
|
5851
|
+
|
|
5852
|
+
|
|
5853
|
+
|
|
5854
|
+
|
|
5855
|
+
|
|
5856
|
+
|
|
5857
|
+
|
|
5858
|
+
|
|
5859
|
+
|
|
5860
|
+
|
|
5861
|
+
|
|
5862
|
+
|
|
5863
|
+
|
|
5864
|
+
|
|
5865
|
+
|
|
5866
|
+
|
|
5867
|
+
|
|
5868
|
+
|
|
5869
|
+
|
|
5870
|
+
|
|
5871
|
+
|
|
5872
|
+
|
|
5873
|
+
|
|
5874
|
+
|
|
5875
|
+
|
|
5876
|
+
|
|
5877
|
+
|
|
5878
|
+
|
|
5879
|
+
|
|
5880
|
+
|
|
5881
|
+
|
|
5882
|
+
|
|
5883
|
+
|
|
5884
|
+
|
|
5885
|
+
|
|
5886
|
+
|
|
5887
|
+
|
|
5888
|
+
|
|
5889
|
+
|
|
5890
|
+
|
|
5891
|
+
|
|
5892
|
+
|
|
5893
|
+
|
|
5894
|
+
|
|
5895
|
+
|
|
5896
|
+
|
|
5897
|
+
|
|
5898
|
+
|
|
5899
|
+
|
|
5900
|
+
|
|
5901
|
+
|
|
5902
|
+
|
|
5903
|
+
|
|
5904
|
+
|
|
5905
|
+
|
|
5906
|
+
|
|
5907
|
+
|
|
5908
|
+
|
|
5909
|
+
|
|
5910
|
+
|
|
5911
|
+
|
|
5912
|
+
|
|
5913
|
+
|
|
5914
|
+
|
|
5915
|
+
|
|
5916
|
+
|
|
5917
|
+
|
|
5918
|
+
|
|
5919
|
+
* @example
|
|
5920
|
+
* // Remove nodes and verify structure
|
|
5921
|
+
* const avl = new AVLTree<number>([5, 3, 7, 1, 4, 6, 8]);
|
|
5922
|
+
* avl.delete(3);
|
|
5923
|
+
* console.log(avl.has(3)); // false;
|
|
5924
|
+
* console.log(avl.size); // 6;
|
|
5925
|
+
*/
|
|
4269
5926
|
delete(keyNodeOrEntry) {
|
|
4270
5927
|
const deletedResults = super.delete(keyNodeOrEntry);
|
|
4271
5928
|
for (const { needBalanced } of deletedResults) {
|
|
@@ -4276,13 +5933,75 @@ var AVLTree = class extends BST {
|
|
|
4276
5933
|
return deletedResults;
|
|
4277
5934
|
}
|
|
4278
5935
|
/**
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
5936
|
+
* Rebuilds the tree to be perfectly balanced.
|
|
5937
|
+
* @remarks AVL trees are already height-balanced, but this makes them *perfectly* balanced (minimal height and all leaves at N or N-1).
|
|
5938
|
+
* Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
|
|
5939
|
+
*
|
|
5940
|
+
* @param [iterationType=this.iterationType] - The traversal method for the initial node export.
|
|
5941
|
+
* @returns True if successful, false if the tree was empty.
|
|
5942
|
+
|
|
5943
|
+
|
|
5944
|
+
|
|
5945
|
+
|
|
5946
|
+
|
|
5947
|
+
|
|
5948
|
+
|
|
5949
|
+
|
|
5950
|
+
|
|
5951
|
+
|
|
5952
|
+
|
|
5953
|
+
|
|
5954
|
+
|
|
5955
|
+
|
|
5956
|
+
|
|
5957
|
+
|
|
5958
|
+
|
|
5959
|
+
|
|
5960
|
+
|
|
5961
|
+
|
|
5962
|
+
|
|
5963
|
+
|
|
5964
|
+
|
|
5965
|
+
|
|
5966
|
+
|
|
5967
|
+
|
|
5968
|
+
|
|
5969
|
+
|
|
5970
|
+
|
|
5971
|
+
|
|
5972
|
+
|
|
5973
|
+
|
|
5974
|
+
|
|
5975
|
+
|
|
5976
|
+
|
|
5977
|
+
|
|
5978
|
+
|
|
5979
|
+
|
|
5980
|
+
|
|
5981
|
+
|
|
5982
|
+
|
|
5983
|
+
|
|
5984
|
+
|
|
5985
|
+
|
|
5986
|
+
|
|
5987
|
+
|
|
5988
|
+
|
|
5989
|
+
|
|
5990
|
+
|
|
5991
|
+
|
|
5992
|
+
|
|
5993
|
+
|
|
5994
|
+
|
|
5995
|
+
|
|
5996
|
+
* @example
|
|
5997
|
+
* // Rebalance the tree
|
|
5998
|
+
* const avl = new AVLTree<number>();
|
|
5999
|
+
* // Insert in sorted order (worst case for BST)
|
|
6000
|
+
* for (let i = 1; i <= 7; i++) avl.add(i);
|
|
6001
|
+
* console.log(avl.isAVLBalanced()); // false;
|
|
6002
|
+
* avl.perfectlyBalance();
|
|
6003
|
+
* console.log(avl.isAVLBalanced()); // true;
|
|
6004
|
+
*/
|
|
4286
6005
|
perfectlyBalance(iterationType = this.iterationType) {
|
|
4287
6006
|
const nodes = this.dfs((node) => node, "IN", false, this._root, iterationType);
|
|
4288
6007
|
const n = nodes.length;
|
|
@@ -4306,17 +6025,107 @@ var AVLTree = class extends BST {
|
|
|
4306
6025
|
return true;
|
|
4307
6026
|
}
|
|
4308
6027
|
/**
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
6028
|
+
* Creates a new AVLTree by mapping each [key, value] pair.
|
|
6029
|
+
* @remarks Time O(N log N) (O(N) iteration + O(log M) `set` for each item into the new tree). Space O(N) for the new tree.
|
|
6030
|
+
*
|
|
6031
|
+
* @template MK - New key type.
|
|
6032
|
+
* @template MV - New value type.
|
|
6033
|
+
* @template MR - New raw type.
|
|
6034
|
+
* @param callback - A function to map each [key, value] pair.
|
|
6035
|
+
* @param [options] - Options for the new AVLTree.
|
|
6036
|
+
* @param [thisArg] - `this` context for the callback.
|
|
6037
|
+
* @returns A new, mapped AVLTree.
|
|
6038
|
+
|
|
6039
|
+
|
|
6040
|
+
|
|
6041
|
+
|
|
6042
|
+
|
|
6043
|
+
|
|
6044
|
+
|
|
6045
|
+
|
|
6046
|
+
|
|
6047
|
+
|
|
6048
|
+
|
|
6049
|
+
|
|
6050
|
+
|
|
6051
|
+
|
|
6052
|
+
|
|
6053
|
+
|
|
6054
|
+
|
|
6055
|
+
|
|
6056
|
+
|
|
6057
|
+
|
|
6058
|
+
|
|
6059
|
+
|
|
6060
|
+
|
|
6061
|
+
|
|
6062
|
+
|
|
6063
|
+
|
|
6064
|
+
|
|
6065
|
+
|
|
6066
|
+
|
|
6067
|
+
|
|
6068
|
+
|
|
6069
|
+
|
|
6070
|
+
|
|
6071
|
+
|
|
6072
|
+
|
|
6073
|
+
|
|
6074
|
+
|
|
6075
|
+
|
|
6076
|
+
|
|
6077
|
+
|
|
6078
|
+
|
|
6079
|
+
|
|
6080
|
+
|
|
6081
|
+
|
|
6082
|
+
|
|
6083
|
+
|
|
6084
|
+
|
|
6085
|
+
|
|
6086
|
+
|
|
6087
|
+
|
|
6088
|
+
|
|
6089
|
+
|
|
6090
|
+
|
|
6091
|
+
|
|
6092
|
+
|
|
6093
|
+
|
|
6094
|
+
|
|
6095
|
+
|
|
6096
|
+
|
|
6097
|
+
|
|
6098
|
+
|
|
6099
|
+
|
|
6100
|
+
|
|
6101
|
+
|
|
6102
|
+
|
|
6103
|
+
|
|
6104
|
+
|
|
6105
|
+
|
|
6106
|
+
|
|
6107
|
+
|
|
6108
|
+
|
|
6109
|
+
|
|
6110
|
+
|
|
6111
|
+
|
|
6112
|
+
|
|
6113
|
+
|
|
6114
|
+
|
|
6115
|
+
|
|
6116
|
+
|
|
6117
|
+
|
|
6118
|
+
|
|
6119
|
+
|
|
6120
|
+
|
|
6121
|
+
|
|
6122
|
+
|
|
6123
|
+
* @example
|
|
6124
|
+
* // Transform to new tree
|
|
6125
|
+
* const avl = new AVLTree<number, number>([[1, 10], [2, 20], [3, 30]]);
|
|
6126
|
+
* const doubled = avl.map((value, key) => [key, (value ?? 0) * 2] as [number, number]);
|
|
6127
|
+
* console.log([...doubled.values()]); // [20, 40, 60];
|
|
6128
|
+
*/
|
|
4320
6129
|
map(callback, options, thisArg) {
|
|
4321
6130
|
const out = this._createLike([], options);
|
|
4322
6131
|
let index = 0;
|