bst-typed 2.4.4 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -30
- package/dist/cjs/index.cjs +1228 -544
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +1225 -541
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1228 -545
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +1225 -542
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
- package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
- package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
- package/dist/types/data-structures/heap/heap.d.ts +287 -99
- package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
- package/dist/types/data-structures/queue/deque.d.ts +313 -66
- package/dist/types/data-structures/queue/queue.d.ts +211 -42
- package/dist/types/data-structures/stack/stack.d.ts +174 -32
- package/dist/types/data-structures/trie/trie.d.ts +213 -43
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/umd/bst-typed.js +1221 -537
- package/dist/umd/bst-typed.js.map +1 -1
- package/dist/umd/bst-typed.min.js +2 -2
- package/dist/umd/bst-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
- package/src/data-structures/binary-tree/binary-tree.ts +542 -121
- package/src/data-structures/binary-tree/bst.ts +346 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1292 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
- package/src/data-structures/binary-tree/tree-set.ts +1143 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +223 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +299 -59
- package/src/data-structures/hash/hash-map.ts +243 -79
- package/src/data-structures/heap/heap.ts +291 -102
- package/src/data-structures/heap/max-heap.ts +48 -3
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
- package/src/data-structures/matrix/matrix.ts +425 -22
- package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +343 -68
- package/src/data-structures/queue/queue.ts +211 -42
- package/src/data-structures/stack/stack.ts +174 -32
- package/src/data-structures/trie/trie.ts +215 -44
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
package/dist/umd/bst-typed.js
CHANGED
|
@@ -28,6 +28,7 @@ var bstTyped = (() => {
|
|
|
28
28
|
BinaryTree: () => BinaryTree,
|
|
29
29
|
BinaryTreeNode: () => BinaryTreeNode,
|
|
30
30
|
DFSOperation: () => DFSOperation,
|
|
31
|
+
ERR: () => ERR,
|
|
31
32
|
Range: () => Range
|
|
32
33
|
});
|
|
33
34
|
|
|
@@ -492,6 +493,231 @@ var bstTyped = (() => {
|
|
|
492
493
|
}
|
|
493
494
|
};
|
|
494
495
|
|
|
496
|
+
// src/common/error.ts
|
|
497
|
+
var ERR = {
|
|
498
|
+
// Range / index
|
|
499
|
+
indexOutOfRange: (index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`,
|
|
500
|
+
invalidIndex: (ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`,
|
|
501
|
+
// Type / argument
|
|
502
|
+
invalidArgument: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
503
|
+
comparatorRequired: (ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`,
|
|
504
|
+
invalidKey: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
505
|
+
notAFunction: (name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`,
|
|
506
|
+
invalidEntry: (ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`,
|
|
507
|
+
invalidNaN: (ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`,
|
|
508
|
+
invalidDate: (ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`,
|
|
509
|
+
reduceEmpty: (ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`,
|
|
510
|
+
callbackReturnType: (expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`,
|
|
511
|
+
// State / operation
|
|
512
|
+
invalidOperation: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
513
|
+
// Matrix
|
|
514
|
+
matrixDimensionMismatch: (op) => `Matrix: Dimensions must be compatible for ${op}.`,
|
|
515
|
+
matrixSingular: () => "Matrix: Singular matrix, inverse does not exist.",
|
|
516
|
+
matrixNotSquare: () => "Matrix: Must be square for inversion.",
|
|
517
|
+
matrixNotRectangular: () => "Matrix: Must be rectangular for transposition.",
|
|
518
|
+
matrixRowMismatch: (expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
// src/common/index.ts
|
|
522
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
523
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
524
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
525
|
+
return DFSOperation2;
|
|
526
|
+
})(DFSOperation || {});
|
|
527
|
+
var Range = class {
|
|
528
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
529
|
+
this.low = low;
|
|
530
|
+
this.high = high;
|
|
531
|
+
this.includeLow = includeLow;
|
|
532
|
+
this.includeHigh = includeHigh;
|
|
533
|
+
}
|
|
534
|
+
// Determine whether a key is within the range
|
|
535
|
+
isInRange(key, comparator) {
|
|
536
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
537
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
538
|
+
return lowCheck && highCheck;
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
543
|
+
var IterableEntryBase = class {
|
|
544
|
+
/**
|
|
545
|
+
* Default iterator yielding `[key, value]` entries.
|
|
546
|
+
* @returns Iterator of `[K, V]`.
|
|
547
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
548
|
+
*/
|
|
549
|
+
*[Symbol.iterator](...args) {
|
|
550
|
+
yield* this._getIterator(...args);
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
554
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
555
|
+
* @remarks Time O(n), Space O(1)
|
|
556
|
+
*/
|
|
557
|
+
*entries() {
|
|
558
|
+
for (const item of this) {
|
|
559
|
+
yield item;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Iterate over keys only.
|
|
564
|
+
* @returns Iterator of keys.
|
|
565
|
+
* @remarks Time O(n), Space O(1)
|
|
566
|
+
*/
|
|
567
|
+
*keys() {
|
|
568
|
+
for (const item of this) {
|
|
569
|
+
yield item[0];
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Iterate over values only.
|
|
574
|
+
* @returns Iterator of values.
|
|
575
|
+
* @remarks Time O(n), Space O(1)
|
|
576
|
+
*/
|
|
577
|
+
*values() {
|
|
578
|
+
for (const item of this) {
|
|
579
|
+
yield item[1];
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Test whether all entries satisfy the predicate.
|
|
584
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
585
|
+
* @param thisArg - Optional `this` for callback.
|
|
586
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
587
|
+
* @remarks Time O(n), Space O(1)
|
|
588
|
+
*/
|
|
589
|
+
every(predicate, thisArg) {
|
|
590
|
+
let index = 0;
|
|
591
|
+
for (const item of this) {
|
|
592
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Test whether any entry satisfies the predicate.
|
|
600
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
601
|
+
* @param thisArg - Optional `this` for callback.
|
|
602
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
603
|
+
* @remarks Time O(n), Space O(1)
|
|
604
|
+
*/
|
|
605
|
+
some(predicate, thisArg) {
|
|
606
|
+
let index = 0;
|
|
607
|
+
for (const item of this) {
|
|
608
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Visit each entry, left-to-right.
|
|
616
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
617
|
+
* @param thisArg - Optional `this` for callback.
|
|
618
|
+
* @remarks Time O(n), Space O(1)
|
|
619
|
+
*/
|
|
620
|
+
forEach(callbackfn, thisArg) {
|
|
621
|
+
let index = 0;
|
|
622
|
+
for (const item of this) {
|
|
623
|
+
const [key, value] = item;
|
|
624
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Find the first entry that matches a predicate.
|
|
629
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
630
|
+
* @param thisArg - Optional `this` for callback.
|
|
631
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
632
|
+
* @remarks Time O(n), Space O(1)
|
|
633
|
+
*/
|
|
634
|
+
find(callbackfn, thisArg) {
|
|
635
|
+
let index = 0;
|
|
636
|
+
for (const item of this) {
|
|
637
|
+
const [key, value] = item;
|
|
638
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
639
|
+
}
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Whether the given key exists.
|
|
644
|
+
* @param key - Key to test.
|
|
645
|
+
* @returns `true` if found; otherwise `false`.
|
|
646
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
647
|
+
*/
|
|
648
|
+
has(key) {
|
|
649
|
+
for (const item of this) {
|
|
650
|
+
const [itemKey] = item;
|
|
651
|
+
if (itemKey === key) return true;
|
|
652
|
+
}
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Whether there exists an entry with the given value.
|
|
657
|
+
* @param value - Value to test.
|
|
658
|
+
* @returns `true` if found; otherwise `false`.
|
|
659
|
+
* @remarks Time O(n), Space O(1)
|
|
660
|
+
*/
|
|
661
|
+
hasValue(value) {
|
|
662
|
+
for (const [, elementValue] of this) {
|
|
663
|
+
if (elementValue === value) return true;
|
|
664
|
+
}
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Get the value under a key.
|
|
669
|
+
* @param key - Key to look up.
|
|
670
|
+
* @returns Value or `undefined`.
|
|
671
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
672
|
+
*/
|
|
673
|
+
get(key) {
|
|
674
|
+
for (const item of this) {
|
|
675
|
+
const [itemKey, value] = item;
|
|
676
|
+
if (itemKey === key) return value;
|
|
677
|
+
}
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Reduce entries into a single accumulator.
|
|
682
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
683
|
+
* @param initialValue - Initial accumulator.
|
|
684
|
+
* @returns Final accumulator.
|
|
685
|
+
* @remarks Time O(n), Space O(1)
|
|
686
|
+
*/
|
|
687
|
+
reduce(callbackfn, initialValue) {
|
|
688
|
+
let accumulator = initialValue;
|
|
689
|
+
let index = 0;
|
|
690
|
+
for (const item of this) {
|
|
691
|
+
const [key, value] = item;
|
|
692
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
693
|
+
}
|
|
694
|
+
return accumulator;
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Converts data structure to `[key, value]` pairs.
|
|
698
|
+
* @returns Array of entries.
|
|
699
|
+
* @remarks Time O(n), Space O(n)
|
|
700
|
+
*/
|
|
701
|
+
toArray() {
|
|
702
|
+
return [...this];
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
706
|
+
* @returns Array of entries (default) or a string.
|
|
707
|
+
* @remarks Time O(n), Space O(n)
|
|
708
|
+
*/
|
|
709
|
+
toVisual() {
|
|
710
|
+
return [...this];
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Print a human-friendly representation to the console.
|
|
714
|
+
* @remarks Time O(n), Space O(n)
|
|
715
|
+
*/
|
|
716
|
+
print() {
|
|
717
|
+
console.log(this.toVisual());
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
|
|
495
721
|
// src/data-structures/queue/queue.ts
|
|
496
722
|
var Queue = class _Queue extends LinearBase {
|
|
497
723
|
/**
|
|
@@ -546,18 +772,52 @@ var bstTyped = (() => {
|
|
|
546
772
|
this._autoCompactRatio = value;
|
|
547
773
|
}
|
|
548
774
|
/**
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
775
|
+
* Get the number of elements currently in the queue.
|
|
776
|
+
* @remarks Time O(1), Space O(1)
|
|
777
|
+
* @returns Current length.
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
* @example
|
|
790
|
+
* // Track queue length
|
|
791
|
+
* const q = new Queue<number>();
|
|
792
|
+
* console.log(q.length); // 0;
|
|
793
|
+
* q.push(1);
|
|
794
|
+
* q.push(2);
|
|
795
|
+
* console.log(q.length); // 2;
|
|
796
|
+
*/
|
|
553
797
|
get length() {
|
|
554
798
|
return this.elements.length - this._offset;
|
|
555
799
|
}
|
|
556
800
|
/**
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
801
|
+
* Get the first element (front) without removing it.
|
|
802
|
+
* @remarks Time O(1), Space O(1)
|
|
803
|
+
* @returns Front element or undefined.
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
* @example
|
|
816
|
+
* // View the front element
|
|
817
|
+
* const q = new Queue<string>(['first', 'second', 'third']);
|
|
818
|
+
* console.log(q.first); // 'first';
|
|
819
|
+
* console.log(q.length); // 3;
|
|
820
|
+
*/
|
|
561
821
|
get first() {
|
|
562
822
|
return this.length > 0 ? this.elements[this._offset] : void 0;
|
|
563
823
|
}
|
|
@@ -580,19 +840,69 @@ var bstTyped = (() => {
|
|
|
580
840
|
return new _Queue(elements);
|
|
581
841
|
}
|
|
582
842
|
/**
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
843
|
+
* Check whether the queue is empty.
|
|
844
|
+
* @remarks Time O(1), Space O(1)
|
|
845
|
+
* @returns True if length is 0.
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
* @example
|
|
858
|
+
* // Queue for...of iteration and isEmpty check
|
|
859
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
860
|
+
*
|
|
861
|
+
* const elements: string[] = [];
|
|
862
|
+
* for (const item of queue) {
|
|
863
|
+
* elements.push(item);
|
|
864
|
+
* }
|
|
865
|
+
*
|
|
866
|
+
* // Verify all elements are iterated in order
|
|
867
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
868
|
+
*
|
|
869
|
+
* // Process all elements
|
|
870
|
+
* while (queue.length > 0) {
|
|
871
|
+
* queue.shift();
|
|
872
|
+
* }
|
|
873
|
+
*
|
|
874
|
+
* console.log(queue.length); // 0;
|
|
875
|
+
*/
|
|
587
876
|
isEmpty() {
|
|
588
877
|
return this.length === 0;
|
|
589
878
|
}
|
|
590
879
|
/**
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
880
|
+
* Enqueue one element at the back.
|
|
881
|
+
* @remarks Time O(1), Space O(1)
|
|
882
|
+
* @param element - Element to enqueue.
|
|
883
|
+
* @returns True on success.
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
* @example
|
|
896
|
+
* // basic Queue creation and push operation
|
|
897
|
+
* // Create a simple Queue with initial values
|
|
898
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
899
|
+
*
|
|
900
|
+
* // Verify the queue maintains insertion order
|
|
901
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
902
|
+
*
|
|
903
|
+
* // Check length
|
|
904
|
+
* console.log(queue.length); // 5;
|
|
905
|
+
*/
|
|
596
906
|
push(element) {
|
|
597
907
|
this.elements.push(element);
|
|
598
908
|
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
@@ -613,10 +923,35 @@ var bstTyped = (() => {
|
|
|
613
923
|
return ans;
|
|
614
924
|
}
|
|
615
925
|
/**
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
926
|
+
* Dequeue one element from the front (amortized via offset).
|
|
927
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
928
|
+
* @returns Removed element or undefined.
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
* @example
|
|
941
|
+
* // Queue shift and peek operations
|
|
942
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
943
|
+
*
|
|
944
|
+
* // Peek at the front element without removing it
|
|
945
|
+
* console.log(queue.first); // 10;
|
|
946
|
+
*
|
|
947
|
+
* // Remove and get the first element (FIFO)
|
|
948
|
+
* const first = queue.shift();
|
|
949
|
+
* console.log(first); // 10;
|
|
950
|
+
*
|
|
951
|
+
* // Verify remaining elements and length decreased
|
|
952
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
953
|
+
* console.log(queue.length); // 3;
|
|
954
|
+
*/
|
|
620
955
|
shift() {
|
|
621
956
|
if (this.length === 0) return void 0;
|
|
622
957
|
const first = this.first;
|
|
@@ -625,11 +960,24 @@ var bstTyped = (() => {
|
|
|
625
960
|
return first;
|
|
626
961
|
}
|
|
627
962
|
/**
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
963
|
+
* Delete the first occurrence of a specific element.
|
|
964
|
+
* @remarks Time O(N), Space O(1)
|
|
965
|
+
* @param element - Element to remove (strict equality via Object.is).
|
|
966
|
+
* @returns True if an element was removed.
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
* @example
|
|
976
|
+
* // Remove specific element
|
|
977
|
+
* const q = new Queue<number>([1, 2, 3, 2]);
|
|
978
|
+
* q.delete(2);
|
|
979
|
+
* console.log(q.length); // 3;
|
|
980
|
+
*/
|
|
633
981
|
delete(element) {
|
|
634
982
|
for (let i = this._offset; i < this.elements.length; i++) {
|
|
635
983
|
if (Object.is(this.elements[i], element)) {
|
|
@@ -640,11 +988,24 @@ var bstTyped = (() => {
|
|
|
640
988
|
return false;
|
|
641
989
|
}
|
|
642
990
|
/**
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
991
|
+
* Get the element at a given logical index.
|
|
992
|
+
* @remarks Time O(1), Space O(1)
|
|
993
|
+
* @param index - Zero-based index from the front.
|
|
994
|
+
* @returns Element or undefined.
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
* @example
|
|
1004
|
+
* // Access element by index
|
|
1005
|
+
* const q = new Queue<string>(['a', 'b', 'c']);
|
|
1006
|
+
* console.log(q.at(0)); // 'a';
|
|
1007
|
+
* console.log(q.at(2)); // 'c';
|
|
1008
|
+
*/
|
|
648
1009
|
at(index) {
|
|
649
1010
|
if (index < 0 || index >= this.length) return void 0;
|
|
650
1011
|
return this._elements[this._offset + index];
|
|
@@ -696,19 +1057,48 @@ var bstTyped = (() => {
|
|
|
696
1057
|
return this;
|
|
697
1058
|
}
|
|
698
1059
|
/**
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
1060
|
+
* Remove all elements and reset offset.
|
|
1061
|
+
* @remarks Time O(1), Space O(1)
|
|
1062
|
+
* @returns void
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
* @example
|
|
1073
|
+
* // Remove all elements
|
|
1074
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1075
|
+
* q.clear();
|
|
1076
|
+
* console.log(q.length); // 0;
|
|
1077
|
+
*/
|
|
703
1078
|
clear() {
|
|
704
1079
|
this._elements = [];
|
|
705
1080
|
this._offset = 0;
|
|
706
1081
|
}
|
|
707
1082
|
/**
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
1083
|
+
* Compact storage by discarding consumed head elements.
|
|
1084
|
+
* @remarks Time O(N), Space O(N)
|
|
1085
|
+
* @returns True when compaction performed.
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
* @example
|
|
1095
|
+
* // Reclaim unused memory
|
|
1096
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1097
|
+
* q.shift();
|
|
1098
|
+
* q.shift();
|
|
1099
|
+
* q.compact();
|
|
1100
|
+
* console.log(q.length); // 3;
|
|
1101
|
+
*/
|
|
712
1102
|
compact() {
|
|
713
1103
|
this._elements = this.elements.slice(this._offset);
|
|
714
1104
|
this._offset = 0;
|
|
@@ -734,10 +1124,26 @@ var bstTyped = (() => {
|
|
|
734
1124
|
return removed;
|
|
735
1125
|
}
|
|
736
1126
|
/**
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
1127
|
+
* Deep clone this queue and its parameters.
|
|
1128
|
+
* @remarks Time O(N), Space O(N)
|
|
1129
|
+
* @returns A new queue with the same content and options.
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
* @example
|
|
1140
|
+
* // Create independent copy
|
|
1141
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1142
|
+
* const copy = q.clone();
|
|
1143
|
+
* copy.shift();
|
|
1144
|
+
* console.log(q.length); // 3;
|
|
1145
|
+
* console.log(copy.length); // 2;
|
|
1146
|
+
*/
|
|
741
1147
|
clone() {
|
|
742
1148
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
743
1149
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -745,317 +1151,144 @@ var bstTyped = (() => {
|
|
|
745
1151
|
return out;
|
|
746
1152
|
}
|
|
747
1153
|
/**
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
* @param [thisArg] - Value for `this` inside the callback.
|
|
772
|
-
* @returns A new Queue with mapped elements.
|
|
773
|
-
*/
|
|
774
|
-
map(callback, options, thisArg) {
|
|
775
|
-
var _a, _b;
|
|
776
|
-
const out = new this.constructor([], {
|
|
777
|
-
toElementFn: options == null ? void 0 : options.toElementFn,
|
|
778
|
-
maxLen: (_a = options == null ? void 0 : options.maxLen) != null ? _a : this._maxLen,
|
|
779
|
-
autoCompactRatio: (_b = options == null ? void 0 : options.autoCompactRatio) != null ? _b : this._autoCompactRatio
|
|
780
|
-
});
|
|
781
|
-
let index = 0;
|
|
782
|
-
for (const v of this)
|
|
783
|
-
out.push(thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this));
|
|
784
|
-
return out;
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Map each element to a new value of the same type.
|
|
788
|
-
* @remarks Time O(N), Space O(N)
|
|
789
|
-
* @param callback - Mapping function (element, index, queue) → element.
|
|
790
|
-
* @param [thisArg] - Value for `this` inside the callback.
|
|
791
|
-
* @returns A new queue with mapped elements (same element type).
|
|
792
|
-
*/
|
|
793
|
-
mapSame(callback, thisArg) {
|
|
794
|
-
var _a;
|
|
795
|
-
const Ctor = this.constructor;
|
|
796
|
-
const out = new Ctor([], {
|
|
797
|
-
toElementFn: this.toElementFn,
|
|
798
|
-
maxLen: this._maxLen,
|
|
799
|
-
autoCompactRatio: this._autoCompactRatio
|
|
800
|
-
});
|
|
801
|
-
(_a = out._setAutoCompactRatio) == null ? void 0 : _a.call(out, this._autoCompactRatio);
|
|
802
|
-
let index = 0;
|
|
803
|
-
for (const v of this) {
|
|
804
|
-
const mv = thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
|
|
805
|
-
out.push(mv);
|
|
806
|
-
}
|
|
807
|
-
return out;
|
|
808
|
-
}
|
|
809
|
-
/**
|
|
810
|
-
* (Protected) Set the internal auto-compaction ratio.
|
|
811
|
-
* @remarks Time O(1), Space O(1)
|
|
812
|
-
* @param value - New ratio to assign.
|
|
813
|
-
* @returns void
|
|
814
|
-
*/
|
|
815
|
-
_setAutoCompactRatio(value) {
|
|
816
|
-
this._autoCompactRatio = value;
|
|
817
|
-
}
|
|
818
|
-
/**
|
|
819
|
-
* (Protected) Iterate elements from front to back.
|
|
820
|
-
* @remarks Time O(N), Space O(1)
|
|
821
|
-
* @returns Iterator of E.
|
|
822
|
-
*/
|
|
823
|
-
*_getIterator() {
|
|
824
|
-
for (let i = this._offset; i < this.elements.length; i++) yield this.elements[i];
|
|
825
|
-
}
|
|
826
|
-
/**
|
|
827
|
-
* (Protected) Iterate elements from back to front.
|
|
828
|
-
* @remarks Time O(N), Space O(1)
|
|
829
|
-
* @returns Iterator of E.
|
|
830
|
-
*/
|
|
831
|
-
*_getReverseIterator() {
|
|
832
|
-
for (let i = this.length - 1; i >= 0; i--) {
|
|
833
|
-
const cur = this.at(i);
|
|
834
|
-
if (cur !== void 0) yield cur;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
/**
|
|
838
|
-
* (Protected) Create an empty instance of the same concrete class.
|
|
839
|
-
* @remarks Time O(1), Space O(1)
|
|
840
|
-
* @param [options] - Options forwarded to the constructor.
|
|
841
|
-
* @returns An empty like-kind queue instance.
|
|
842
|
-
*/
|
|
843
|
-
_createInstance(options) {
|
|
844
|
-
const Ctor = this.constructor;
|
|
845
|
-
return new Ctor([], options);
|
|
846
|
-
}
|
|
847
|
-
/**
|
|
848
|
-
* (Protected) Create a like-kind queue and seed it from an iterable.
|
|
849
|
-
* @remarks Time O(N), Space O(N)
|
|
850
|
-
* @template EM
|
|
851
|
-
* @template RM
|
|
852
|
-
* @param [elements] - Iterable used to seed the new queue.
|
|
853
|
-
* @param [options] - Options forwarded to the constructor.
|
|
854
|
-
* @returns A like-kind Queue instance.
|
|
855
|
-
*/
|
|
856
|
-
_createLike(elements = [], options) {
|
|
857
|
-
const Ctor = this.constructor;
|
|
858
|
-
return new Ctor(elements, options);
|
|
859
|
-
}
|
|
860
|
-
};
|
|
861
|
-
|
|
862
|
-
// src/data-structures/base/iterable-entry-base.ts
|
|
863
|
-
var IterableEntryBase = class {
|
|
864
|
-
/**
|
|
865
|
-
* Default iterator yielding `[key, value]` entries.
|
|
866
|
-
* @returns Iterator of `[K, V]`.
|
|
867
|
-
* @remarks Time O(n) to iterate, Space O(1)
|
|
868
|
-
*/
|
|
869
|
-
*[Symbol.iterator](...args) {
|
|
870
|
-
yield* this._getIterator(...args);
|
|
871
|
-
}
|
|
872
|
-
/**
|
|
873
|
-
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
874
|
-
* @returns Iterator of `[K, V | undefined]`.
|
|
875
|
-
* @remarks Time O(n), Space O(1)
|
|
876
|
-
*/
|
|
877
|
-
*entries() {
|
|
878
|
-
for (const item of this) {
|
|
879
|
-
yield item;
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
/**
|
|
883
|
-
* Iterate over keys only.
|
|
884
|
-
* @returns Iterator of keys.
|
|
885
|
-
* @remarks Time O(n), Space O(1)
|
|
886
|
-
*/
|
|
887
|
-
*keys() {
|
|
888
|
-
for (const item of this) {
|
|
889
|
-
yield item[0];
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
/**
|
|
893
|
-
* Iterate over values only.
|
|
894
|
-
* @returns Iterator of values.
|
|
895
|
-
* @remarks Time O(n), Space O(1)
|
|
896
|
-
*/
|
|
897
|
-
*values() {
|
|
898
|
-
for (const item of this) {
|
|
899
|
-
yield item[1];
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
/**
|
|
903
|
-
* Test whether all entries satisfy the predicate.
|
|
904
|
-
* @param predicate - `(key, value, index, self) => boolean`.
|
|
905
|
-
* @param thisArg - Optional `this` for callback.
|
|
906
|
-
* @returns `true` if all pass; otherwise `false`.
|
|
907
|
-
* @remarks Time O(n), Space O(1)
|
|
908
|
-
*/
|
|
909
|
-
every(predicate, thisArg) {
|
|
910
|
-
let index = 0;
|
|
911
|
-
for (const item of this) {
|
|
912
|
-
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
913
|
-
return false;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
return true;
|
|
917
|
-
}
|
|
918
|
-
/**
|
|
919
|
-
* Test whether any entry satisfies the predicate.
|
|
920
|
-
* @param predicate - `(key, value, index, self) => boolean`.
|
|
921
|
-
* @param thisArg - Optional `this` for callback.
|
|
922
|
-
* @returns `true` if any passes; otherwise `false`.
|
|
923
|
-
* @remarks Time O(n), Space O(1)
|
|
924
|
-
*/
|
|
925
|
-
some(predicate, thisArg) {
|
|
926
|
-
let index = 0;
|
|
927
|
-
for (const item of this) {
|
|
928
|
-
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
929
|
-
return true;
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
return false;
|
|
933
|
-
}
|
|
934
|
-
/**
|
|
935
|
-
* Visit each entry, left-to-right.
|
|
936
|
-
* @param callbackfn - `(key, value, index, self) => void`.
|
|
937
|
-
* @param thisArg - Optional `this` for callback.
|
|
938
|
-
* @remarks Time O(n), Space O(1)
|
|
939
|
-
*/
|
|
940
|
-
forEach(callbackfn, thisArg) {
|
|
1154
|
+
* Filter elements into a new queue of the same class.
|
|
1155
|
+
* @remarks Time O(N), Space O(N)
|
|
1156
|
+
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
1157
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1158
|
+
* @returns A new queue with kept elements.
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
* @example
|
|
1169
|
+
* // Filter elements
|
|
1170
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1171
|
+
* const evens = q.filter(x => x % 2 === 0);
|
|
1172
|
+
* console.log(evens.length); // 2;
|
|
1173
|
+
*/
|
|
1174
|
+
filter(predicate, thisArg) {
|
|
1175
|
+
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
1176
|
+
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
941
1177
|
let index = 0;
|
|
942
|
-
for (const
|
|
943
|
-
|
|
944
|
-
|
|
1178
|
+
for (const v of this) {
|
|
1179
|
+
if (predicate.call(thisArg, v, index, this)) out.push(v);
|
|
1180
|
+
index++;
|
|
945
1181
|
}
|
|
1182
|
+
return out;
|
|
946
1183
|
}
|
|
947
1184
|
/**
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1185
|
+
* Map each element to a new element in a possibly different-typed queue.
|
|
1186
|
+
* @remarks Time O(N), Space O(N)
|
|
1187
|
+
* @template EM
|
|
1188
|
+
* @template RM
|
|
1189
|
+
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
1190
|
+
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
1191
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1192
|
+
* @returns A new Queue with mapped elements.
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
* @example
|
|
1202
|
+
* // Transform elements
|
|
1203
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1204
|
+
* const doubled = q.map(x => x * 2);
|
|
1205
|
+
* console.log(doubled.toArray()); // [2, 4, 6];
|
|
1206
|
+
*/
|
|
1207
|
+
map(callback, options, thisArg) {
|
|
1208
|
+
var _a, _b;
|
|
1209
|
+
const out = new this.constructor([], {
|
|
1210
|
+
toElementFn: options == null ? void 0 : options.toElementFn,
|
|
1211
|
+
maxLen: (_a = options == null ? void 0 : options.maxLen) != null ? _a : this._maxLen,
|
|
1212
|
+
autoCompactRatio: (_b = options == null ? void 0 : options.autoCompactRatio) != null ? _b : this._autoCompactRatio
|
|
1213
|
+
});
|
|
955
1214
|
let index = 0;
|
|
956
|
-
for (const
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
}
|
|
960
|
-
return;
|
|
1215
|
+
for (const v of this)
|
|
1216
|
+
out.push(thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this));
|
|
1217
|
+
return out;
|
|
961
1218
|
}
|
|
962
1219
|
/**
|
|
963
|
-
*
|
|
964
|
-
* @
|
|
965
|
-
* @
|
|
966
|
-
* @
|
|
1220
|
+
* Map each element to a new value of the same type.
|
|
1221
|
+
* @remarks Time O(N), Space O(N)
|
|
1222
|
+
* @param callback - Mapping function (element, index, queue) → element.
|
|
1223
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1224
|
+
* @returns A new queue with mapped elements (same element type).
|
|
967
1225
|
*/
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1226
|
+
mapSame(callback, thisArg) {
|
|
1227
|
+
var _a;
|
|
1228
|
+
const Ctor = this.constructor;
|
|
1229
|
+
const out = new Ctor([], {
|
|
1230
|
+
toElementFn: this.toElementFn,
|
|
1231
|
+
maxLen: this._maxLen,
|
|
1232
|
+
autoCompactRatio: this._autoCompactRatio
|
|
1233
|
+
});
|
|
1234
|
+
(_a = out._setAutoCompactRatio) == null ? void 0 : _a.call(out, this._autoCompactRatio);
|
|
1235
|
+
let index = 0;
|
|
1236
|
+
for (const v of this) {
|
|
1237
|
+
const mv = thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
|
|
1238
|
+
out.push(mv);
|
|
972
1239
|
}
|
|
973
|
-
return
|
|
1240
|
+
return out;
|
|
974
1241
|
}
|
|
975
1242
|
/**
|
|
976
|
-
*
|
|
977
|
-
* @
|
|
978
|
-
* @
|
|
979
|
-
* @
|
|
1243
|
+
* (Protected) Set the internal auto-compaction ratio.
|
|
1244
|
+
* @remarks Time O(1), Space O(1)
|
|
1245
|
+
* @param value - New ratio to assign.
|
|
1246
|
+
* @returns void
|
|
980
1247
|
*/
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
if (elementValue === value) return true;
|
|
984
|
-
}
|
|
985
|
-
return false;
|
|
1248
|
+
_setAutoCompactRatio(value) {
|
|
1249
|
+
this._autoCompactRatio = value;
|
|
986
1250
|
}
|
|
987
1251
|
/**
|
|
988
|
-
*
|
|
989
|
-
* @
|
|
990
|
-
* @returns
|
|
991
|
-
* @remarks Time O(n) generic, Space O(1)
|
|
1252
|
+
* (Protected) Iterate elements from front to back.
|
|
1253
|
+
* @remarks Time O(N), Space O(1)
|
|
1254
|
+
* @returns Iterator of E.
|
|
992
1255
|
*/
|
|
993
|
-
|
|
994
|
-
for (
|
|
995
|
-
const [itemKey, value] = item;
|
|
996
|
-
if (itemKey === key) return value;
|
|
997
|
-
}
|
|
998
|
-
return;
|
|
1256
|
+
*_getIterator() {
|
|
1257
|
+
for (let i = this._offset; i < this.elements.length; i++) yield this.elements[i];
|
|
999
1258
|
}
|
|
1000
1259
|
/**
|
|
1001
|
-
*
|
|
1002
|
-
* @
|
|
1003
|
-
* @
|
|
1004
|
-
* @returns Final accumulator.
|
|
1005
|
-
* @remarks Time O(n), Space O(1)
|
|
1260
|
+
* (Protected) Iterate elements from back to front.
|
|
1261
|
+
* @remarks Time O(N), Space O(1)
|
|
1262
|
+
* @returns Iterator of E.
|
|
1006
1263
|
*/
|
|
1007
|
-
|
|
1008
|
-
let
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
const [key, value] = item;
|
|
1012
|
-
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
1264
|
+
*_getReverseIterator() {
|
|
1265
|
+
for (let i = this.length - 1; i >= 0; i--) {
|
|
1266
|
+
const cur = this.at(i);
|
|
1267
|
+
if (cur !== void 0) yield cur;
|
|
1013
1268
|
}
|
|
1014
|
-
return accumulator;
|
|
1015
|
-
}
|
|
1016
|
-
/**
|
|
1017
|
-
* Converts data structure to `[key, value]` pairs.
|
|
1018
|
-
* @returns Array of entries.
|
|
1019
|
-
* @remarks Time O(n), Space O(n)
|
|
1020
|
-
*/
|
|
1021
|
-
toArray() {
|
|
1022
|
-
return [...this];
|
|
1023
1269
|
}
|
|
1024
1270
|
/**
|
|
1025
|
-
*
|
|
1026
|
-
* @
|
|
1027
|
-
* @
|
|
1271
|
+
* (Protected) Create an empty instance of the same concrete class.
|
|
1272
|
+
* @remarks Time O(1), Space O(1)
|
|
1273
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1274
|
+
* @returns An empty like-kind queue instance.
|
|
1028
1275
|
*/
|
|
1029
|
-
|
|
1030
|
-
|
|
1276
|
+
_createInstance(options) {
|
|
1277
|
+
const Ctor = this.constructor;
|
|
1278
|
+
return new Ctor([], options);
|
|
1031
1279
|
}
|
|
1032
1280
|
/**
|
|
1033
|
-
*
|
|
1034
|
-
* @remarks Time O(
|
|
1281
|
+
* (Protected) Create a like-kind queue and seed it from an iterable.
|
|
1282
|
+
* @remarks Time O(N), Space O(N)
|
|
1283
|
+
* @template EM
|
|
1284
|
+
* @template RM
|
|
1285
|
+
* @param [elements] - Iterable used to seed the new queue.
|
|
1286
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1287
|
+
* @returns A like-kind Queue instance.
|
|
1035
1288
|
*/
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
};
|
|
1040
|
-
|
|
1041
|
-
// src/common/index.ts
|
|
1042
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
1043
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
1044
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
1045
|
-
return DFSOperation2;
|
|
1046
|
-
})(DFSOperation || {});
|
|
1047
|
-
var Range = class {
|
|
1048
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
1049
|
-
this.low = low;
|
|
1050
|
-
this.high = high;
|
|
1051
|
-
this.includeLow = includeLow;
|
|
1052
|
-
this.includeHigh = includeHigh;
|
|
1053
|
-
}
|
|
1054
|
-
// Determine whether a key is within the range
|
|
1055
|
-
isInRange(key, comparator) {
|
|
1056
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
1057
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
1058
|
-
return lowCheck && highCheck;
|
|
1289
|
+
_createLike(elements = [], options) {
|
|
1290
|
+
const Ctor = this.constructor;
|
|
1291
|
+
return new Ctor(elements, options);
|
|
1059
1292
|
}
|
|
1060
1293
|
};
|
|
1061
1294
|
|
|
@@ -1194,7 +1427,7 @@ var bstTyped = (() => {
|
|
|
1194
1427
|
return "MAL_NODE";
|
|
1195
1428
|
}
|
|
1196
1429
|
};
|
|
1197
|
-
var BinaryTree = class extends IterableEntryBase {
|
|
1430
|
+
var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
1198
1431
|
/**
|
|
1199
1432
|
* Creates an instance of BinaryTree.
|
|
1200
1433
|
* @remarks Time O(N * M), where N is the number of items in `keysNodesEntriesOrRaws` and M is the tree size at insertion time (due to O(M) `set` operation). Space O(N) for storing the nodes.
|
|
@@ -1229,7 +1462,7 @@ var bstTyped = (() => {
|
|
|
1229
1462
|
if (isMapMode !== void 0) this._isMapMode = isMapMode;
|
|
1230
1463
|
if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
|
|
1231
1464
|
if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
|
|
1232
|
-
else if (toEntryFn) throw TypeError("toEntryFn
|
|
1465
|
+
else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
|
|
1233
1466
|
}
|
|
1234
1467
|
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
1235
1468
|
}
|
|
@@ -1434,30 +1667,78 @@ var bstTyped = (() => {
|
|
|
1434
1667
|
return isComparable(key);
|
|
1435
1668
|
}
|
|
1436
1669
|
/**
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1670
|
+
* Adds a new node to the tree.
|
|
1671
|
+
* @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).
|
|
1672
|
+
*
|
|
1673
|
+
* @param keyNodeOrEntry - The key, node, or entry to add.
|
|
1674
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1675
|
+
|
|
1676
|
+
|
|
1677
|
+
|
|
1678
|
+
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
* @example
|
|
1682
|
+
* // Add a single node
|
|
1683
|
+
* const tree = new BinaryTree<number>();
|
|
1684
|
+
* tree.add(1);
|
|
1685
|
+
* tree.add(2);
|
|
1686
|
+
* tree.add(3);
|
|
1687
|
+
* console.log(tree.size); // 3;
|
|
1688
|
+
* console.log(tree.has(1)); // true;
|
|
1689
|
+
*/
|
|
1443
1690
|
add(keyNodeOrEntry) {
|
|
1444
1691
|
return this.set(keyNodeOrEntry);
|
|
1445
1692
|
}
|
|
1446
1693
|
/**
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1694
|
+
* Adds or updates a new node to the tree.
|
|
1695
|
+
* @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).
|
|
1696
|
+
*
|
|
1697
|
+
* @param keyNodeOrEntry - The key, node, or entry to set or update.
|
|
1698
|
+
* @param [value] - The value, if providing just a key.
|
|
1699
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1700
|
+
|
|
1701
|
+
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
|
|
1705
|
+
|
|
1706
|
+
|
|
1707
|
+
|
|
1708
|
+
|
|
1709
|
+
|
|
1710
|
+
|
|
1711
|
+
* @example
|
|
1712
|
+
* // basic BinaryTree creation and insertion
|
|
1713
|
+
* // Create a BinaryTree with entries
|
|
1714
|
+
* const entries: [number, string][] = [
|
|
1715
|
+
* [6, 'six'],
|
|
1716
|
+
* [1, 'one'],
|
|
1717
|
+
* [2, 'two'],
|
|
1718
|
+
* [7, 'seven'],
|
|
1719
|
+
* [5, 'five'],
|
|
1720
|
+
* [3, 'three'],
|
|
1721
|
+
* [4, 'four'],
|
|
1722
|
+
* [9, 'nine'],
|
|
1723
|
+
* [8, 'eight']
|
|
1724
|
+
* ];
|
|
1725
|
+
*
|
|
1726
|
+
* const tree = new BinaryTree(entries);
|
|
1727
|
+
*
|
|
1728
|
+
* // Verify size
|
|
1729
|
+
* console.log(tree.size); // 9;
|
|
1730
|
+
*
|
|
1731
|
+
* // Add new element
|
|
1732
|
+
* tree.set(10, 'ten');
|
|
1733
|
+
* console.log(tree.size); // 10;
|
|
1734
|
+
*/
|
|
1454
1735
|
set(keyNodeOrEntry, value) {
|
|
1455
1736
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
1456
1737
|
if (newNode === void 0) return false;
|
|
1457
1738
|
if (!this._root) {
|
|
1458
1739
|
this._setRoot(newNode);
|
|
1459
1740
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
1460
|
-
this._size = 1;
|
|
1741
|
+
if (newNode !== null) this._size = 1;
|
|
1461
1742
|
return true;
|
|
1462
1743
|
}
|
|
1463
1744
|
const queue = new Queue([this._root]);
|
|
@@ -1489,29 +1770,50 @@ var bstTyped = (() => {
|
|
|
1489
1770
|
potentialParent.right = newNode;
|
|
1490
1771
|
}
|
|
1491
1772
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
1492
|
-
this._size++;
|
|
1773
|
+
if (newNode !== null) this._size++;
|
|
1493
1774
|
return true;
|
|
1494
1775
|
}
|
|
1495
1776
|
return false;
|
|
1496
1777
|
}
|
|
1497
1778
|
/**
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1779
|
+
* Adds multiple items to the tree.
|
|
1780
|
+
* @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).
|
|
1781
|
+
*
|
|
1782
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
1783
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1784
|
+
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
|
|
1788
|
+
|
|
1789
|
+
|
|
1790
|
+
|
|
1791
|
+
|
|
1792
|
+
|
|
1793
|
+
* @example
|
|
1794
|
+
* // Bulk add
|
|
1795
|
+
* const tree = new BinaryTree<number>();
|
|
1796
|
+
* tree.addMany([1, 2, 3, 4, 5]);
|
|
1797
|
+
* console.log(tree.size); // 5;
|
|
1798
|
+
*/
|
|
1504
1799
|
addMany(keysNodesEntriesOrRaws) {
|
|
1505
1800
|
return this.setMany(keysNodesEntriesOrRaws);
|
|
1506
1801
|
}
|
|
1507
1802
|
/**
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1803
|
+
* Adds or updates multiple items to the tree.
|
|
1804
|
+
* @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).
|
|
1805
|
+
*
|
|
1806
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set or update.
|
|
1807
|
+
* @param [values] - An optional parallel iterable of values.
|
|
1808
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1809
|
+
|
|
1810
|
+
|
|
1811
|
+
* @example
|
|
1812
|
+
* // Set multiple entries
|
|
1813
|
+
* const tree = new BinaryTree<number, string>();
|
|
1814
|
+
* tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
1815
|
+
* console.log(tree.size); // 3;
|
|
1816
|
+
*/
|
|
1515
1817
|
setMany(keysNodesEntriesOrRaws, values) {
|
|
1516
1818
|
const inserted = [];
|
|
1517
1819
|
let valuesIterator;
|
|
@@ -1532,11 +1834,26 @@ var bstTyped = (() => {
|
|
|
1532
1834
|
return inserted;
|
|
1533
1835
|
}
|
|
1534
1836
|
/**
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1837
|
+
* Merges another tree into this one by seting all its nodes.
|
|
1838
|
+
* @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`).
|
|
1839
|
+
*
|
|
1840
|
+
* @param anotherTree - The tree to merge.
|
|
1841
|
+
|
|
1842
|
+
|
|
1843
|
+
|
|
1844
|
+
|
|
1845
|
+
|
|
1846
|
+
|
|
1847
|
+
|
|
1848
|
+
|
|
1849
|
+
|
|
1850
|
+
* @example
|
|
1851
|
+
* // Combine trees
|
|
1852
|
+
* const t1 = new BinaryTree<number>([1, 2]);
|
|
1853
|
+
* const t2 = new BinaryTree<number>([3, 4]);
|
|
1854
|
+
* t1.merge(t2);
|
|
1855
|
+
* console.log(t1.size); // 4;
|
|
1856
|
+
*/
|
|
1540
1857
|
merge(anotherTree) {
|
|
1541
1858
|
this.setMany(anotherTree, []);
|
|
1542
1859
|
}
|
|
@@ -1552,12 +1869,29 @@ var bstTyped = (() => {
|
|
|
1552
1869
|
this.setMany(keysNodesEntriesOrRaws, values);
|
|
1553
1870
|
}
|
|
1554
1871
|
/**
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1872
|
+
* Deletes a node from the tree.
|
|
1873
|
+
* @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).
|
|
1874
|
+
*
|
|
1875
|
+
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
1876
|
+
* @returns An array containing deletion results (for compatibility with self-balancing trees).
|
|
1877
|
+
|
|
1878
|
+
|
|
1879
|
+
|
|
1880
|
+
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
|
|
1885
|
+
|
|
1886
|
+
|
|
1887
|
+
|
|
1888
|
+
* @example
|
|
1889
|
+
* // Remove a node
|
|
1890
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
1891
|
+
* tree.delete(3);
|
|
1892
|
+
* console.log(tree.has(3)); // false;
|
|
1893
|
+
* console.log(tree.size); // 4;
|
|
1894
|
+
*/
|
|
1561
1895
|
delete(keyNodeEntryRawOrPredicate) {
|
|
1562
1896
|
const deletedResult = [];
|
|
1563
1897
|
if (!this._root) return deletedResult;
|
|
@@ -1651,14 +1985,27 @@ var bstTyped = (() => {
|
|
|
1651
1985
|
return this.search(keyNodeEntryOrPredicate, onlyOne, (node) => node, startNode, iterationType);
|
|
1652
1986
|
}
|
|
1653
1987
|
/**
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1988
|
+
* Gets the first node matching a predicate.
|
|
1989
|
+
* @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`).
|
|
1990
|
+
*
|
|
1991
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
1992
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
1993
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1994
|
+
* @returns The first matching node, or undefined if not found.
|
|
1995
|
+
|
|
1996
|
+
|
|
1997
|
+
|
|
1998
|
+
|
|
1999
|
+
|
|
2000
|
+
|
|
2001
|
+
|
|
2002
|
+
|
|
2003
|
+
|
|
2004
|
+
* @example
|
|
2005
|
+
* // Get node by key
|
|
2006
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
|
|
2007
|
+
* console.log(tree.getNode(2)?.value); // 'child';
|
|
2008
|
+
*/
|
|
1662
2009
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1663
2010
|
if (this._isMapMode && keyNodeEntryOrPredicate !== null && keyNodeEntryOrPredicate !== void 0) {
|
|
1664
2011
|
if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
@@ -1670,14 +2017,30 @@ var bstTyped = (() => {
|
|
|
1670
2017
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType)[0];
|
|
1671
2018
|
}
|
|
1672
2019
|
/**
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
2020
|
+
* Gets the value associated with a key.
|
|
2021
|
+
* @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.
|
|
2022
|
+
*
|
|
2023
|
+
* @param keyNodeEntryOrPredicate - The key, node, or entry to get the value for.
|
|
2024
|
+
* @param [startNode=this._root] - The node to start searching from (if not in Map mode).
|
|
2025
|
+
* @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
|
|
2026
|
+
* @returns The associated value, or undefined.
|
|
2027
|
+
|
|
2028
|
+
|
|
2029
|
+
|
|
2030
|
+
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
|
|
2034
|
+
|
|
2035
|
+
|
|
2036
|
+
|
|
2037
|
+
|
|
2038
|
+
* @example
|
|
2039
|
+
* // Retrieve value by key
|
|
2040
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
|
|
2041
|
+
* console.log(tree.get(2)); // 'left';
|
|
2042
|
+
* console.log(tree.get(99)); // undefined;
|
|
2043
|
+
*/
|
|
1681
2044
|
get(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1682
2045
|
var _a, _b;
|
|
1683
2046
|
if (this._isMapMode) {
|
|
@@ -1698,19 +2061,45 @@ var bstTyped = (() => {
|
|
|
1698
2061
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType).length > 0;
|
|
1699
2062
|
}
|
|
1700
2063
|
/**
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
2064
|
+
* Clears the tree of all nodes and values.
|
|
2065
|
+
* @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
|
|
2066
|
+
|
|
2067
|
+
|
|
2068
|
+
|
|
2069
|
+
|
|
2070
|
+
|
|
2071
|
+
|
|
2072
|
+
|
|
2073
|
+
|
|
2074
|
+
|
|
2075
|
+
* @example
|
|
2076
|
+
* // Remove all nodes
|
|
2077
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2078
|
+
* tree.clear();
|
|
2079
|
+
* console.log(tree.isEmpty()); // true;
|
|
2080
|
+
*/
|
|
1704
2081
|
clear() {
|
|
1705
2082
|
this._clearNodes();
|
|
1706
2083
|
if (this._isMapMode) this._clearValues();
|
|
1707
2084
|
}
|
|
1708
2085
|
/**
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
2086
|
+
* Checks if the tree is empty.
|
|
2087
|
+
* @remarks Time O(1), Space O(1)
|
|
2088
|
+
*
|
|
2089
|
+
* @returns True if the tree has no nodes, false otherwise.
|
|
2090
|
+
|
|
2091
|
+
|
|
2092
|
+
|
|
2093
|
+
|
|
2094
|
+
|
|
2095
|
+
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
|
|
2099
|
+
* @example
|
|
2100
|
+
* // Check empty
|
|
2101
|
+
* console.log(new BinaryTree().isEmpty()); // true;
|
|
2102
|
+
*/
|
|
1714
2103
|
isEmpty() {
|
|
1715
2104
|
return this._size === 0;
|
|
1716
2105
|
}
|
|
@@ -1725,13 +2114,27 @@ var bstTyped = (() => {
|
|
|
1725
2114
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
1726
2115
|
}
|
|
1727
2116
|
/**
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
2117
|
+
* Checks if the tree is a valid Binary Search Tree (BST).
|
|
2118
|
+
* @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).
|
|
2119
|
+
*
|
|
2120
|
+
* @param [startNode=this._root] - The node to start checking from.
|
|
2121
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2122
|
+
* @returns True if it's a valid BST, false otherwise.
|
|
2123
|
+
|
|
2124
|
+
|
|
2125
|
+
|
|
2126
|
+
|
|
2127
|
+
|
|
2128
|
+
|
|
2129
|
+
|
|
2130
|
+
|
|
2131
|
+
|
|
2132
|
+
* @example
|
|
2133
|
+
* // Check BST property
|
|
2134
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2135
|
+
* // BinaryTree doesn't guarantee BST order
|
|
2136
|
+
* console.log(typeof tree.isBST()); // 'boolean';
|
|
2137
|
+
*/
|
|
1735
2138
|
isBST(startNode = this._root, iterationType = this.iterationType) {
|
|
1736
2139
|
const startNodeSired = this.ensureNode(startNode);
|
|
1737
2140
|
if (!startNodeSired) return true;
|
|
@@ -1769,13 +2172,29 @@ var bstTyped = (() => {
|
|
|
1769
2172
|
}
|
|
1770
2173
|
}
|
|
1771
2174
|
/**
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
2175
|
+
* Gets the depth of a node (distance from `startNode`).
|
|
2176
|
+
* @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
|
|
2177
|
+
*
|
|
2178
|
+
* @param dist - The node to find the depth of.
|
|
2179
|
+
* @param [startNode=this._root] - The node to measure depth from (defaults to root).
|
|
2180
|
+
* @returns The depth (0 if `dist` is `startNode`).
|
|
2181
|
+
|
|
2182
|
+
|
|
2183
|
+
|
|
2184
|
+
|
|
2185
|
+
|
|
2186
|
+
|
|
2187
|
+
|
|
2188
|
+
|
|
2189
|
+
|
|
2190
|
+
|
|
2191
|
+
|
|
2192
|
+
* @example
|
|
2193
|
+
* // Get depth of a node
|
|
2194
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2195
|
+
* const node = tree.getNode(4);
|
|
2196
|
+
* console.log(tree.getDepth(node!)); // 2;
|
|
2197
|
+
*/
|
|
1779
2198
|
getDepth(dist, startNode = this._root) {
|
|
1780
2199
|
let distEnsured = this.ensureNode(dist);
|
|
1781
2200
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
@@ -1790,13 +2209,28 @@ var bstTyped = (() => {
|
|
|
1790
2209
|
return depth;
|
|
1791
2210
|
}
|
|
1792
2211
|
/**
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
2212
|
+
* Gets the maximum height of the tree (longest path from startNode to a leaf).
|
|
2213
|
+
* @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).
|
|
2214
|
+
*
|
|
2215
|
+
* @param [startNode=this._root] - The node to start measuring from.
|
|
2216
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2217
|
+
* @returns The height ( -1 for an empty tree, 0 for a single-node tree).
|
|
2218
|
+
|
|
2219
|
+
|
|
2220
|
+
|
|
2221
|
+
|
|
2222
|
+
|
|
2223
|
+
|
|
2224
|
+
|
|
2225
|
+
|
|
2226
|
+
|
|
2227
|
+
|
|
2228
|
+
|
|
2229
|
+
* @example
|
|
2230
|
+
* // Get tree height
|
|
2231
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2232
|
+
* console.log(tree.getHeight()); // 2;
|
|
2233
|
+
*/
|
|
1800
2234
|
getHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
1801
2235
|
startNode = this.ensureNode(startNode);
|
|
1802
2236
|
if (!this.isRealNode(startNode)) return -1;
|
|
@@ -2058,7 +2492,7 @@ var bstTyped = (() => {
|
|
|
2058
2492
|
}
|
|
2059
2493
|
/**
|
|
2060
2494
|
* Finds all leaf nodes in the tree.
|
|
2061
|
-
* @remarks Time O(N), visits every node. Space O(H) for recursive
|
|
2495
|
+
* @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
|
|
2062
2496
|
*
|
|
2063
2497
|
* @template C - The type of the callback function.
|
|
2064
2498
|
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
|
|
@@ -2081,15 +2515,15 @@ var bstTyped = (() => {
|
|
|
2081
2515
|
};
|
|
2082
2516
|
dfs(startNode);
|
|
2083
2517
|
} else {
|
|
2084
|
-
const
|
|
2085
|
-
while (
|
|
2086
|
-
const cur =
|
|
2518
|
+
const stack = [startNode];
|
|
2519
|
+
while (stack.length > 0) {
|
|
2520
|
+
const cur = stack.pop();
|
|
2087
2521
|
if (this.isRealNode(cur)) {
|
|
2088
2522
|
if (this.isLeaf(cur)) {
|
|
2089
2523
|
leaves.push(callback(cur));
|
|
2090
2524
|
}
|
|
2091
|
-
if (this.isRealNode(cur.
|
|
2092
|
-
if (this.isRealNode(cur.
|
|
2525
|
+
if (this.isRealNode(cur.right)) stack.push(cur.right);
|
|
2526
|
+
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
|
2093
2527
|
}
|
|
2094
2528
|
}
|
|
2095
2529
|
}
|
|
@@ -2232,24 +2666,53 @@ var bstTyped = (() => {
|
|
|
2232
2666
|
return ans;
|
|
2233
2667
|
}
|
|
2234
2668
|
/**
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2669
|
+
* Clones the tree.
|
|
2670
|
+
* @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.
|
|
2671
|
+
*
|
|
2672
|
+
* @returns A new, cloned instance of the tree.
|
|
2673
|
+
|
|
2674
|
+
|
|
2675
|
+
|
|
2676
|
+
|
|
2677
|
+
|
|
2678
|
+
|
|
2679
|
+
|
|
2680
|
+
|
|
2681
|
+
|
|
2682
|
+
* @example
|
|
2683
|
+
* // Deep copy
|
|
2684
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2685
|
+
* const copy = tree.clone();
|
|
2686
|
+
* copy.delete(1);
|
|
2687
|
+
* console.log(tree.has(1)); // true;
|
|
2688
|
+
*/
|
|
2240
2689
|
clone() {
|
|
2241
2690
|
const out = this._createInstance();
|
|
2242
2691
|
this._clone(out);
|
|
2243
2692
|
return out;
|
|
2244
2693
|
}
|
|
2245
2694
|
/**
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2695
|
+
* Creates a new tree containing only the entries that satisfy the predicate.
|
|
2696
|
+
* @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.
|
|
2697
|
+
*
|
|
2698
|
+
* @param predicate - A function to test each [key, value] pair.
|
|
2699
|
+
* @param [thisArg] - `this` context for the predicate.
|
|
2700
|
+
* @returns A new, filtered tree.
|
|
2701
|
+
|
|
2702
|
+
|
|
2703
|
+
|
|
2704
|
+
|
|
2705
|
+
|
|
2706
|
+
|
|
2707
|
+
|
|
2708
|
+
|
|
2709
|
+
|
|
2710
|
+
* @example
|
|
2711
|
+
* // Filter nodes by condition
|
|
2712
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4]);
|
|
2713
|
+
* const result = tree.filter((_, key) => key > 2);
|
|
2714
|
+
* console.log(result.size); // 2;
|
|
2715
|
+
*/
|
|
2253
2716
|
filter(predicate, thisArg) {
|
|
2254
2717
|
const out = this._createInstance();
|
|
2255
2718
|
let i = 0;
|
|
@@ -2257,17 +2720,31 @@ var bstTyped = (() => {
|
|
|
2257
2720
|
return out;
|
|
2258
2721
|
}
|
|
2259
2722
|
/**
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2723
|
+
* Creates a new tree by mapping each [key, value] pair to a new entry.
|
|
2724
|
+
* @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.
|
|
2725
|
+
*
|
|
2726
|
+
* @template MK - New key type.
|
|
2727
|
+
* @template MV - New value type.
|
|
2728
|
+
* @template MR - New raw type.
|
|
2729
|
+
* @param cb - A function to map each [key, value] pair.
|
|
2730
|
+
* @param [options] - Options for the new tree.
|
|
2731
|
+
* @param [thisArg] - `this` context for the callback.
|
|
2732
|
+
* @returns A new, mapped tree.
|
|
2733
|
+
|
|
2734
|
+
|
|
2735
|
+
|
|
2736
|
+
|
|
2737
|
+
|
|
2738
|
+
|
|
2739
|
+
|
|
2740
|
+
|
|
2741
|
+
|
|
2742
|
+
* @example
|
|
2743
|
+
* // Transform to new tree
|
|
2744
|
+
* const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
|
|
2745
|
+
* const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
|
|
2746
|
+
* console.log([...mapped.values()]); // contains 11;
|
|
2747
|
+
*/
|
|
2271
2748
|
map(cb, options, thisArg) {
|
|
2272
2749
|
const out = this._createLike([], options);
|
|
2273
2750
|
let i = 0;
|
|
@@ -2305,12 +2782,25 @@ var bstTyped = (() => {
|
|
|
2305
2782
|
return output;
|
|
2306
2783
|
}
|
|
2307
2784
|
/**
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2785
|
+
* Prints a visual representation of the tree to the console.
|
|
2786
|
+
* @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
|
|
2787
|
+
*
|
|
2788
|
+
* @param [options] - Options to control the output.
|
|
2789
|
+
* @param [startNode=this._root] - The node to start printing from.
|
|
2790
|
+
|
|
2791
|
+
|
|
2792
|
+
|
|
2793
|
+
|
|
2794
|
+
|
|
2795
|
+
|
|
2796
|
+
|
|
2797
|
+
|
|
2798
|
+
|
|
2799
|
+
* @example
|
|
2800
|
+
* // Display tree
|
|
2801
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2802
|
+
* expect(() => tree.print()).not.toThrow();
|
|
2803
|
+
*/
|
|
2314
2804
|
print(options, startNode = this._root) {
|
|
2315
2805
|
console.log(this.toVisual(startNode, options));
|
|
2316
2806
|
}
|
|
@@ -2543,44 +3033,99 @@ var bstTyped = (() => {
|
|
|
2543
3033
|
* @returns Layout information for this subtree.
|
|
2544
3034
|
*/
|
|
2545
3035
|
_displayAux(node, options) {
|
|
2546
|
-
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
2547
3036
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
const
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
3037
|
+
const newFrame = (n) => ({
|
|
3038
|
+
node: n,
|
|
3039
|
+
stage: 0,
|
|
3040
|
+
leftLayout: emptyDisplayLayout,
|
|
3041
|
+
rightLayout: emptyDisplayLayout
|
|
3042
|
+
});
|
|
3043
|
+
const stack = [newFrame(node)];
|
|
3044
|
+
let result = emptyDisplayLayout;
|
|
3045
|
+
const setChildResult = (layout) => {
|
|
3046
|
+
if (stack.length === 0) {
|
|
3047
|
+
result = layout;
|
|
3048
|
+
return;
|
|
3049
|
+
}
|
|
3050
|
+
const parent = stack[stack.length - 1];
|
|
3051
|
+
if (parent.stage === 1) parent.leftLayout = layout;
|
|
3052
|
+
else parent.rightLayout = layout;
|
|
3053
|
+
};
|
|
3054
|
+
while (stack.length > 0) {
|
|
3055
|
+
const frame = stack[stack.length - 1];
|
|
3056
|
+
const cur = frame.node;
|
|
3057
|
+
if (frame.stage === 0) {
|
|
3058
|
+
if (this._isDisplayLeaf(cur, options)) {
|
|
3059
|
+
stack.pop();
|
|
3060
|
+
const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
|
|
3061
|
+
setChildResult(layout);
|
|
3062
|
+
continue;
|
|
3063
|
+
}
|
|
3064
|
+
frame.stage = 1;
|
|
3065
|
+
stack.push(newFrame(cur.left));
|
|
3066
|
+
} else if (frame.stage === 1) {
|
|
3067
|
+
frame.stage = 2;
|
|
3068
|
+
stack.push(newFrame(cur.right));
|
|
3069
|
+
} else {
|
|
3070
|
+
stack.pop();
|
|
3071
|
+
const line = this.isNIL(cur) ? "S" : String(cur.key);
|
|
3072
|
+
const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
|
|
3073
|
+
setChildResult(layout);
|
|
2576
3074
|
}
|
|
2577
|
-
return [
|
|
2578
|
-
mergedLines,
|
|
2579
|
-
leftWidth + width + rightWidth,
|
|
2580
|
-
Math.max(leftHeight, rightHeight) + 2,
|
|
2581
|
-
leftWidth + Math.floor(width / 2)
|
|
2582
|
-
];
|
|
2583
3075
|
}
|
|
3076
|
+
return result;
|
|
3077
|
+
}
|
|
3078
|
+
static _buildNodeDisplay(line, width, left, right) {
|
|
3079
|
+
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
3080
|
+
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
3081
|
+
const firstLine = " ".repeat(Math.max(0, leftMiddle + 1)) + "_".repeat(Math.max(0, leftWidth - leftMiddle - 1)) + line + "_".repeat(Math.max(0, rightMiddle)) + " ".repeat(Math.max(0, rightWidth - rightMiddle));
|
|
3082
|
+
const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
|
|
3083
|
+
const mergedLines = [firstLine, secondLine];
|
|
3084
|
+
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
3085
|
+
const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
|
|
3086
|
+
const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
|
|
3087
|
+
mergedLines.push(leftLine + " ".repeat(width) + rightLine);
|
|
3088
|
+
}
|
|
3089
|
+
return [
|
|
3090
|
+
mergedLines,
|
|
3091
|
+
leftWidth + width + rightWidth,
|
|
3092
|
+
Math.max(leftHeight, rightHeight) + 2,
|
|
3093
|
+
leftWidth + Math.floor(width / 2)
|
|
3094
|
+
];
|
|
3095
|
+
}
|
|
3096
|
+
/**
|
|
3097
|
+
* Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
|
|
3098
|
+
*/
|
|
3099
|
+
_isDisplayLeaf(node, options) {
|
|
3100
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3101
|
+
if (node === null && !isShowNull) return true;
|
|
3102
|
+
if (node === void 0 && !isShowUndefined) return true;
|
|
3103
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return true;
|
|
3104
|
+
if (node === null || node === void 0) return true;
|
|
3105
|
+
const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
|
|
3106
|
+
const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
|
|
3107
|
+
return !hasDisplayableLeft && !hasDisplayableRight;
|
|
3108
|
+
}
|
|
3109
|
+
_hasDisplayableChild(child, options) {
|
|
3110
|
+
if (child === null) return !!options.isShowNull;
|
|
3111
|
+
if (child === void 0) return !!options.isShowUndefined;
|
|
3112
|
+
if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
|
|
3113
|
+
return true;
|
|
3114
|
+
}
|
|
3115
|
+
/**
|
|
3116
|
+
* Resolve a display leaf node to its layout.
|
|
3117
|
+
*/
|
|
3118
|
+
_resolveDisplayLeaf(node, options, emptyDisplayLayout) {
|
|
3119
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3120
|
+
if (node === null && !isShowNull) return emptyDisplayLayout;
|
|
3121
|
+
if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
|
|
3122
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
|
|
3123
|
+
if (node !== null && node !== void 0) {
|
|
3124
|
+
const line2 = this.isNIL(node) ? "S" : String(node.key);
|
|
3125
|
+
return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
|
|
3126
|
+
}
|
|
3127
|
+
const line = node === void 0 ? "U" : "N";
|
|
3128
|
+
return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
|
|
2584
3129
|
}
|
|
2585
3130
|
/**
|
|
2586
3131
|
* (Protected) Swaps the key/value properties of two nodes.
|
|
@@ -2782,6 +3327,7 @@ var bstTyped = (() => {
|
|
|
2782
3327
|
*
|
|
2783
3328
|
* @returns The height.
|
|
2784
3329
|
*/
|
|
3330
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
2785
3331
|
get height() {
|
|
2786
3332
|
return this._height;
|
|
2787
3333
|
}
|
|
@@ -2791,6 +3337,7 @@ var bstTyped = (() => {
|
|
|
2791
3337
|
*
|
|
2792
3338
|
* @param value - The new height.
|
|
2793
3339
|
*/
|
|
3340
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
2794
3341
|
set height(value) {
|
|
2795
3342
|
this._height = value;
|
|
2796
3343
|
}
|
|
@@ -2800,6 +3347,7 @@ var bstTyped = (() => {
|
|
|
2800
3347
|
*
|
|
2801
3348
|
* @returns The node's color.
|
|
2802
3349
|
*/
|
|
3350
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
2803
3351
|
get color() {
|
|
2804
3352
|
return this._color;
|
|
2805
3353
|
}
|
|
@@ -2809,6 +3357,7 @@ var bstTyped = (() => {
|
|
|
2809
3357
|
*
|
|
2810
3358
|
* @param value - The new color.
|
|
2811
3359
|
*/
|
|
3360
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
2812
3361
|
set color(value) {
|
|
2813
3362
|
this._color = value;
|
|
2814
3363
|
}
|
|
@@ -2818,6 +3367,7 @@ var bstTyped = (() => {
|
|
|
2818
3367
|
*
|
|
2819
3368
|
* @returns The subtree node count.
|
|
2820
3369
|
*/
|
|
3370
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
2821
3371
|
get count() {
|
|
2822
3372
|
return this._count;
|
|
2823
3373
|
}
|
|
@@ -2827,6 +3377,7 @@ var bstTyped = (() => {
|
|
|
2827
3377
|
*
|
|
2828
3378
|
* @param value - The new count.
|
|
2829
3379
|
*/
|
|
3380
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
2830
3381
|
set count(value) {
|
|
2831
3382
|
this._count = value;
|
|
2832
3383
|
}
|
|
@@ -2979,14 +3530,39 @@ var bstTyped = (() => {
|
|
|
2979
3530
|
return super.listLevels(callback, startNode, iterationType, false);
|
|
2980
3531
|
}
|
|
2981
3532
|
/**
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
3533
|
+
* Gets the first node matching a predicate.
|
|
3534
|
+
* @remarks Time O(log N) if searching by key, O(N) if searching by predicate. Space O(log N) or O(N).
|
|
3535
|
+
*
|
|
3536
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
3537
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
3538
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
3539
|
+
* @returns The first matching node, or undefined if not found.
|
|
3540
|
+
|
|
3541
|
+
|
|
3542
|
+
|
|
3543
|
+
|
|
3544
|
+
|
|
3545
|
+
|
|
3546
|
+
|
|
3547
|
+
|
|
3548
|
+
|
|
3549
|
+
|
|
3550
|
+
|
|
3551
|
+
|
|
3552
|
+
|
|
3553
|
+
|
|
3554
|
+
|
|
3555
|
+
|
|
3556
|
+
|
|
3557
|
+
|
|
3558
|
+
|
|
3559
|
+
* @example
|
|
3560
|
+
* // Get node object by key
|
|
3561
|
+
* const bst = new BST<number, string>([[5, 'root'], [3, 'left'], [7, 'right']]);
|
|
3562
|
+
* const node = bst.getNode(3);
|
|
3563
|
+
* console.log(node?.key); // 3;
|
|
3564
|
+
* console.log(node?.value); // 'left';
|
|
3565
|
+
*/
|
|
2990
3566
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
2991
3567
|
var _a, _b;
|
|
2992
3568
|
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === void 0) return void 0;
|
|
@@ -3136,13 +3712,44 @@ var bstTyped = (() => {
|
|
|
3136
3712
|
return this.search(searchRange, false, callback, startNode, iterationType);
|
|
3137
3713
|
}
|
|
3138
3714
|
/**
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3715
|
+
* Adds a new node to the BST based on key comparison.
|
|
3716
|
+
* @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
|
|
3717
|
+
*
|
|
3718
|
+
* @param keyNodeOrEntry - The key, node, or entry to set.
|
|
3719
|
+
* @param [value] - The value, if providing just a key.
|
|
3720
|
+
* @returns True if the addition was successful, false otherwise.
|
|
3721
|
+
|
|
3722
|
+
|
|
3723
|
+
|
|
3724
|
+
|
|
3725
|
+
|
|
3726
|
+
|
|
3727
|
+
|
|
3728
|
+
|
|
3729
|
+
|
|
3730
|
+
|
|
3731
|
+
|
|
3732
|
+
|
|
3733
|
+
|
|
3734
|
+
|
|
3735
|
+
|
|
3736
|
+
|
|
3737
|
+
|
|
3738
|
+
|
|
3739
|
+
|
|
3740
|
+
|
|
3741
|
+
|
|
3742
|
+
|
|
3743
|
+
|
|
3744
|
+
|
|
3745
|
+
|
|
3746
|
+
* @example
|
|
3747
|
+
* // Set a key-value pair
|
|
3748
|
+
* const bst = new BST<number, string>();
|
|
3749
|
+
* bst.set(1, 'one');
|
|
3750
|
+
* bst.set(2, 'two');
|
|
3751
|
+
* console.log(bst.get(1)); // 'one';
|
|
3752
|
+
*/
|
|
3146
3753
|
set(keyNodeOrEntry, value) {
|
|
3147
3754
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
3148
3755
|
if (newNode === void 0) return false;
|
|
@@ -3179,17 +3786,34 @@ var bstTyped = (() => {
|
|
|
3179
3786
|
return false;
|
|
3180
3787
|
}
|
|
3181
3788
|
/**
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3789
|
+
* Adds multiple items to the tree.
|
|
3790
|
+
* @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced set).
|
|
3791
|
+
* If false, adds items one by one. Time O(N * H), which is O(N^2) worst-case.
|
|
3792
|
+
* Space O(N) for sorting and recursion/iteration stack.
|
|
3793
|
+
*
|
|
3794
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
3795
|
+
* @param [values] - An optional parallel iterable of values.
|
|
3796
|
+
* @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
|
|
3797
|
+
* @param [iterationType=this.iterationType] - The traversal method for balanced set (recursive or iterative).
|
|
3798
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
3799
|
+
|
|
3800
|
+
|
|
3801
|
+
|
|
3802
|
+
|
|
3803
|
+
|
|
3804
|
+
|
|
3805
|
+
|
|
3806
|
+
|
|
3807
|
+
|
|
3808
|
+
|
|
3809
|
+
|
|
3810
|
+
* @example
|
|
3811
|
+
* // Set multiple key-value pairs
|
|
3812
|
+
* const bst = new BST<number, string>();
|
|
3813
|
+
* bst.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3814
|
+
* console.log(bst.size); // 3;
|
|
3815
|
+
* console.log(bst.get(2)); // 'b';
|
|
3816
|
+
*/
|
|
3193
3817
|
setMany(keysNodesEntriesOrRaws, values, isBalanceAdd = true, iterationType = this.iterationType) {
|
|
3194
3818
|
const inserted = [];
|
|
3195
3819
|
const valuesIterator = values == null ? void 0 : values[Symbol.iterator]();
|
|
@@ -3432,12 +4056,29 @@ var bstTyped = (() => {
|
|
|
3432
4056
|
}
|
|
3433
4057
|
}
|
|
3434
4058
|
/**
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
4059
|
+
* Rebuilds the tree to be perfectly balanced.
|
|
4060
|
+
* @remarks Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
|
|
4061
|
+
*
|
|
4062
|
+
* @param [iterationType=this.iterationType] - The traversal method for the initial node export.
|
|
4063
|
+
* @returns True if successful, false if the tree was empty.
|
|
4064
|
+
|
|
4065
|
+
|
|
4066
|
+
|
|
4067
|
+
|
|
4068
|
+
|
|
4069
|
+
|
|
4070
|
+
|
|
4071
|
+
|
|
4072
|
+
|
|
4073
|
+
* @example
|
|
4074
|
+
* // Rebalance the tree
|
|
4075
|
+
* const bst = new BST<number>();
|
|
4076
|
+
* // Insert in sorted order (worst case for BST)
|
|
4077
|
+
* for (let i = 1; i <= 7; i++) bst.add(i);
|
|
4078
|
+
* console.log(bst.isAVLBalanced()); // false;
|
|
4079
|
+
* bst.perfectlyBalance();
|
|
4080
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
4081
|
+
*/
|
|
3441
4082
|
perfectlyBalance(iterationType = this.iterationType) {
|
|
3442
4083
|
const nodes = this.dfs((node) => node, "IN", false, this._root, iterationType);
|
|
3443
4084
|
const n = nodes.length;
|
|
@@ -3460,12 +4101,25 @@ var bstTyped = (() => {
|
|
|
3460
4101
|
return true;
|
|
3461
4102
|
}
|
|
3462
4103
|
/**
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
4104
|
+
* Checks if the tree meets the AVL balance condition (height difference <= 1).
|
|
4105
|
+
* @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.
|
|
4106
|
+
*
|
|
4107
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
4108
|
+
* @returns True if the tree is AVL balanced, false otherwise.
|
|
4109
|
+
|
|
4110
|
+
|
|
4111
|
+
|
|
4112
|
+
|
|
4113
|
+
|
|
4114
|
+
|
|
4115
|
+
|
|
4116
|
+
|
|
4117
|
+
|
|
4118
|
+
* @example
|
|
4119
|
+
* // Check if tree is height-balanced
|
|
4120
|
+
* const bst = new BST<number>([3, 1, 5, 2, 4]);
|
|
4121
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
4122
|
+
*/
|
|
3469
4123
|
isAVLBalanced(iterationType = this.iterationType) {
|
|
3470
4124
|
if (!this._root) return true;
|
|
3471
4125
|
let balanced = true;
|
|
@@ -3505,18 +4159,42 @@ var bstTyped = (() => {
|
|
|
3505
4159
|
return balanced;
|
|
3506
4160
|
}
|
|
3507
4161
|
/**
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
4162
|
+
* Creates a new BST by mapping each [key, value] pair to a new entry.
|
|
4163
|
+
* @remarks Time O(N * H), where N is nodes in this tree, and H is height of the new tree during insertion.
|
|
4164
|
+
* Space O(N) for the new tree.
|
|
4165
|
+
*
|
|
4166
|
+
* @template MK - New key type.
|
|
4167
|
+
* @template MV - New value type.
|
|
4168
|
+
* @template MR - New raw type.
|
|
4169
|
+
* @param callback - A function to map each [key, value] pair.
|
|
4170
|
+
* @param [options] - Options for the new BST.
|
|
4171
|
+
* @param [thisArg] - `this` context for the callback.
|
|
4172
|
+
* @returns A new, mapped BST.
|
|
4173
|
+
|
|
4174
|
+
|
|
4175
|
+
|
|
4176
|
+
|
|
4177
|
+
|
|
4178
|
+
|
|
4179
|
+
|
|
4180
|
+
|
|
4181
|
+
|
|
4182
|
+
|
|
4183
|
+
|
|
4184
|
+
|
|
4185
|
+
|
|
4186
|
+
|
|
4187
|
+
|
|
4188
|
+
|
|
4189
|
+
|
|
4190
|
+
|
|
4191
|
+
|
|
4192
|
+
* @example
|
|
4193
|
+
* // Transform to new tree
|
|
4194
|
+
* const bst = new BST<number, number>([[1, 10], [2, 20], [3, 30]]);
|
|
4195
|
+
* const doubled = bst.map((value, key) => [key, (value ?? 0) * 2] as [number, number]);
|
|
4196
|
+
* console.log([...doubled.values()]); // [20, 40, 60];
|
|
4197
|
+
*/
|
|
3520
4198
|
map(callback, options, thisArg) {
|
|
3521
4199
|
const out = this._createLike([], options);
|
|
3522
4200
|
let index = 0;
|
|
@@ -3582,9 +4260,15 @@ var bstTyped = (() => {
|
|
|
3582
4260
|
if (a < b) return -1;
|
|
3583
4261
|
return 0;
|
|
3584
4262
|
}
|
|
4263
|
+
if (a instanceof Date && b instanceof Date) {
|
|
4264
|
+
const ta = a.getTime();
|
|
4265
|
+
const tb = b.getTime();
|
|
4266
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
|
|
4267
|
+
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
4268
|
+
}
|
|
3585
4269
|
if (typeof a === "object" || typeof b === "object") {
|
|
3586
|
-
throw TypeError(
|
|
3587
|
-
|
|
4270
|
+
throw new TypeError(
|
|
4271
|
+
ERR.comparatorRequired("BST")
|
|
3588
4272
|
);
|
|
3589
4273
|
}
|
|
3590
4274
|
return 0;
|