binary-tree-typed 2.4.4 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -84
- package/dist/cjs/index.cjs +965 -420
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +962 -417
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +965 -421
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +962 -418
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/common/error.d.ts +23 -0
- package/dist/types/common/index.d.ts +1 -0
- package/dist/types/data-structures/base/iterable-element-base.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +128 -51
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +210 -164
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +439 -78
- package/dist/types/data-structures/binary-tree/bst.d.ts +311 -28
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +217 -31
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +218 -152
- package/dist/types/data-structures/binary-tree/tree-map.d.ts +1281 -5
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +1087 -201
- package/dist/types/data-structures/binary-tree/tree-multi-set.d.ts +858 -65
- package/dist/types/data-structures/binary-tree/tree-set.d.ts +1133 -5
- package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +220 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +218 -59
- package/dist/types/data-structures/hash/hash-map.d.ts +230 -77
- package/dist/types/data-structures/heap/heap.d.ts +287 -99
- package/dist/types/data-structures/heap/max-heap.d.ts +46 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +59 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +286 -44
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +278 -65
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +415 -12
- package/dist/types/data-structures/matrix/matrix.d.ts +331 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +57 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +60 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +60 -0
- package/dist/types/data-structures/queue/deque.d.ts +313 -66
- package/dist/types/data-structures/queue/queue.d.ts +211 -42
- package/dist/types/data-structures/stack/stack.d.ts +174 -32
- package/dist/types/data-structures/trie/trie.d.ts +213 -43
- package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -1
- package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +1 -4
- package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
- package/dist/umd/binary-tree-typed.js +959 -414
- package/dist/umd/binary-tree-typed.js.map +1 -1
- package/dist/umd/binary-tree-typed.min.js +3 -3
- package/dist/umd/binary-tree-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
- package/src/data-structures/binary-tree/binary-tree.ts +542 -121
- package/src/data-structures/binary-tree/bst.ts +346 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1292 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
- package/src/data-structures/binary-tree/tree-set.ts +1143 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +223 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +299 -59
- package/src/data-structures/hash/hash-map.ts +243 -79
- package/src/data-structures/heap/heap.ts +291 -102
- package/src/data-structures/heap/max-heap.ts +48 -3
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
- package/src/data-structures/matrix/matrix.ts +425 -22
- package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +343 -68
- package/src/data-structures/queue/queue.ts +211 -42
- package/src/data-structures/stack/stack.ts +174 -32
- package/src/data-structures/trie/trie.ts +215 -44
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
|
@@ -26,6 +26,7 @@ var binaryTreeTyped = (() => {
|
|
|
26
26
|
BinaryTree: () => BinaryTree,
|
|
27
27
|
BinaryTreeNode: () => BinaryTreeNode,
|
|
28
28
|
DFSOperation: () => DFSOperation,
|
|
29
|
+
ERR: () => ERR,
|
|
29
30
|
Range: () => Range
|
|
30
31
|
});
|
|
31
32
|
|
|
@@ -490,6 +491,231 @@ var binaryTreeTyped = (() => {
|
|
|
490
491
|
}
|
|
491
492
|
};
|
|
492
493
|
|
|
494
|
+
// src/common/error.ts
|
|
495
|
+
var ERR = {
|
|
496
|
+
// Range / index
|
|
497
|
+
indexOutOfRange: (index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`,
|
|
498
|
+
invalidIndex: (ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`,
|
|
499
|
+
// Type / argument
|
|
500
|
+
invalidArgument: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
501
|
+
comparatorRequired: (ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`,
|
|
502
|
+
invalidKey: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
503
|
+
notAFunction: (name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`,
|
|
504
|
+
invalidEntry: (ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`,
|
|
505
|
+
invalidNaN: (ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`,
|
|
506
|
+
invalidDate: (ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`,
|
|
507
|
+
reduceEmpty: (ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`,
|
|
508
|
+
callbackReturnType: (expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`,
|
|
509
|
+
// State / operation
|
|
510
|
+
invalidOperation: (reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`,
|
|
511
|
+
// Matrix
|
|
512
|
+
matrixDimensionMismatch: (op) => `Matrix: Dimensions must be compatible for ${op}.`,
|
|
513
|
+
matrixSingular: () => "Matrix: Singular matrix, inverse does not exist.",
|
|
514
|
+
matrixNotSquare: () => "Matrix: Must be square for inversion.",
|
|
515
|
+
matrixNotRectangular: () => "Matrix: Must be rectangular for transposition.",
|
|
516
|
+
matrixRowMismatch: (expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
// src/common/index.ts
|
|
520
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
521
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
522
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
523
|
+
return DFSOperation2;
|
|
524
|
+
})(DFSOperation || {});
|
|
525
|
+
var Range = class {
|
|
526
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
527
|
+
this.low = low;
|
|
528
|
+
this.high = high;
|
|
529
|
+
this.includeLow = includeLow;
|
|
530
|
+
this.includeHigh = includeHigh;
|
|
531
|
+
}
|
|
532
|
+
// Determine whether a key is within the range
|
|
533
|
+
isInRange(key, comparator) {
|
|
534
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
535
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
536
|
+
return lowCheck && highCheck;
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
541
|
+
var IterableEntryBase = class {
|
|
542
|
+
/**
|
|
543
|
+
* Default iterator yielding `[key, value]` entries.
|
|
544
|
+
* @returns Iterator of `[K, V]`.
|
|
545
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
546
|
+
*/
|
|
547
|
+
*[Symbol.iterator](...args) {
|
|
548
|
+
yield* this._getIterator(...args);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
552
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
553
|
+
* @remarks Time O(n), Space O(1)
|
|
554
|
+
*/
|
|
555
|
+
*entries() {
|
|
556
|
+
for (const item of this) {
|
|
557
|
+
yield item;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Iterate over keys only.
|
|
562
|
+
* @returns Iterator of keys.
|
|
563
|
+
* @remarks Time O(n), Space O(1)
|
|
564
|
+
*/
|
|
565
|
+
*keys() {
|
|
566
|
+
for (const item of this) {
|
|
567
|
+
yield item[0];
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Iterate over values only.
|
|
572
|
+
* @returns Iterator of values.
|
|
573
|
+
* @remarks Time O(n), Space O(1)
|
|
574
|
+
*/
|
|
575
|
+
*values() {
|
|
576
|
+
for (const item of this) {
|
|
577
|
+
yield item[1];
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Test whether all entries satisfy the predicate.
|
|
582
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
583
|
+
* @param thisArg - Optional `this` for callback.
|
|
584
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
585
|
+
* @remarks Time O(n), Space O(1)
|
|
586
|
+
*/
|
|
587
|
+
every(predicate, thisArg) {
|
|
588
|
+
let index = 0;
|
|
589
|
+
for (const item of this) {
|
|
590
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
591
|
+
return false;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return true;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Test whether any entry satisfies the predicate.
|
|
598
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
599
|
+
* @param thisArg - Optional `this` for callback.
|
|
600
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
601
|
+
* @remarks Time O(n), Space O(1)
|
|
602
|
+
*/
|
|
603
|
+
some(predicate, thisArg) {
|
|
604
|
+
let index = 0;
|
|
605
|
+
for (const item of this) {
|
|
606
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
607
|
+
return true;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Visit each entry, left-to-right.
|
|
614
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
615
|
+
* @param thisArg - Optional `this` for callback.
|
|
616
|
+
* @remarks Time O(n), Space O(1)
|
|
617
|
+
*/
|
|
618
|
+
forEach(callbackfn, thisArg) {
|
|
619
|
+
let index = 0;
|
|
620
|
+
for (const item of this) {
|
|
621
|
+
const [key, value] = item;
|
|
622
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Find the first entry that matches a predicate.
|
|
627
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
628
|
+
* @param thisArg - Optional `this` for callback.
|
|
629
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
630
|
+
* @remarks Time O(n), Space O(1)
|
|
631
|
+
*/
|
|
632
|
+
find(callbackfn, thisArg) {
|
|
633
|
+
let index = 0;
|
|
634
|
+
for (const item of this) {
|
|
635
|
+
const [key, value] = item;
|
|
636
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
637
|
+
}
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Whether the given key exists.
|
|
642
|
+
* @param key - Key to test.
|
|
643
|
+
* @returns `true` if found; otherwise `false`.
|
|
644
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
645
|
+
*/
|
|
646
|
+
has(key) {
|
|
647
|
+
for (const item of this) {
|
|
648
|
+
const [itemKey] = item;
|
|
649
|
+
if (itemKey === key) return true;
|
|
650
|
+
}
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Whether there exists an entry with the given value.
|
|
655
|
+
* @param value - Value to test.
|
|
656
|
+
* @returns `true` if found; otherwise `false`.
|
|
657
|
+
* @remarks Time O(n), Space O(1)
|
|
658
|
+
*/
|
|
659
|
+
hasValue(value) {
|
|
660
|
+
for (const [, elementValue] of this) {
|
|
661
|
+
if (elementValue === value) return true;
|
|
662
|
+
}
|
|
663
|
+
return false;
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Get the value under a key.
|
|
667
|
+
* @param key - Key to look up.
|
|
668
|
+
* @returns Value or `undefined`.
|
|
669
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
670
|
+
*/
|
|
671
|
+
get(key) {
|
|
672
|
+
for (const item of this) {
|
|
673
|
+
const [itemKey, value] = item;
|
|
674
|
+
if (itemKey === key) return value;
|
|
675
|
+
}
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Reduce entries into a single accumulator.
|
|
680
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
681
|
+
* @param initialValue - Initial accumulator.
|
|
682
|
+
* @returns Final accumulator.
|
|
683
|
+
* @remarks Time O(n), Space O(1)
|
|
684
|
+
*/
|
|
685
|
+
reduce(callbackfn, initialValue) {
|
|
686
|
+
let accumulator = initialValue;
|
|
687
|
+
let index = 0;
|
|
688
|
+
for (const item of this) {
|
|
689
|
+
const [key, value] = item;
|
|
690
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
691
|
+
}
|
|
692
|
+
return accumulator;
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Converts data structure to `[key, value]` pairs.
|
|
696
|
+
* @returns Array of entries.
|
|
697
|
+
* @remarks Time O(n), Space O(n)
|
|
698
|
+
*/
|
|
699
|
+
toArray() {
|
|
700
|
+
return [...this];
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
704
|
+
* @returns Array of entries (default) or a string.
|
|
705
|
+
* @remarks Time O(n), Space O(n)
|
|
706
|
+
*/
|
|
707
|
+
toVisual() {
|
|
708
|
+
return [...this];
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Print a human-friendly representation to the console.
|
|
712
|
+
* @remarks Time O(n), Space O(n)
|
|
713
|
+
*/
|
|
714
|
+
print() {
|
|
715
|
+
console.log(this.toVisual());
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
|
|
493
719
|
// src/data-structures/queue/queue.ts
|
|
494
720
|
var Queue = class _Queue extends LinearBase {
|
|
495
721
|
/**
|
|
@@ -544,18 +770,52 @@ var binaryTreeTyped = (() => {
|
|
|
544
770
|
this._autoCompactRatio = value;
|
|
545
771
|
}
|
|
546
772
|
/**
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
773
|
+
* Get the number of elements currently in the queue.
|
|
774
|
+
* @remarks Time O(1), Space O(1)
|
|
775
|
+
* @returns Current length.
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
* @example
|
|
788
|
+
* // Track queue length
|
|
789
|
+
* const q = new Queue<number>();
|
|
790
|
+
* console.log(q.length); // 0;
|
|
791
|
+
* q.push(1);
|
|
792
|
+
* q.push(2);
|
|
793
|
+
* console.log(q.length); // 2;
|
|
794
|
+
*/
|
|
551
795
|
get length() {
|
|
552
796
|
return this.elements.length - this._offset;
|
|
553
797
|
}
|
|
554
798
|
/**
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
799
|
+
* Get the first element (front) without removing it.
|
|
800
|
+
* @remarks Time O(1), Space O(1)
|
|
801
|
+
* @returns Front element or undefined.
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
* @example
|
|
814
|
+
* // View the front element
|
|
815
|
+
* const q = new Queue<string>(['first', 'second', 'third']);
|
|
816
|
+
* console.log(q.first); // 'first';
|
|
817
|
+
* console.log(q.length); // 3;
|
|
818
|
+
*/
|
|
559
819
|
get first() {
|
|
560
820
|
return this.length > 0 ? this.elements[this._offset] : void 0;
|
|
561
821
|
}
|
|
@@ -578,19 +838,69 @@ var binaryTreeTyped = (() => {
|
|
|
578
838
|
return new _Queue(elements);
|
|
579
839
|
}
|
|
580
840
|
/**
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
841
|
+
* Check whether the queue is empty.
|
|
842
|
+
* @remarks Time O(1), Space O(1)
|
|
843
|
+
* @returns True if length is 0.
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
* @example
|
|
856
|
+
* // Queue for...of iteration and isEmpty check
|
|
857
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
858
|
+
*
|
|
859
|
+
* const elements: string[] = [];
|
|
860
|
+
* for (const item of queue) {
|
|
861
|
+
* elements.push(item);
|
|
862
|
+
* }
|
|
863
|
+
*
|
|
864
|
+
* // Verify all elements are iterated in order
|
|
865
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
866
|
+
*
|
|
867
|
+
* // Process all elements
|
|
868
|
+
* while (queue.length > 0) {
|
|
869
|
+
* queue.shift();
|
|
870
|
+
* }
|
|
871
|
+
*
|
|
872
|
+
* console.log(queue.length); // 0;
|
|
873
|
+
*/
|
|
585
874
|
isEmpty() {
|
|
586
875
|
return this.length === 0;
|
|
587
876
|
}
|
|
588
877
|
/**
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
878
|
+
* Enqueue one element at the back.
|
|
879
|
+
* @remarks Time O(1), Space O(1)
|
|
880
|
+
* @param element - Element to enqueue.
|
|
881
|
+
* @returns True on success.
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
* @example
|
|
894
|
+
* // basic Queue creation and push operation
|
|
895
|
+
* // Create a simple Queue with initial values
|
|
896
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
897
|
+
*
|
|
898
|
+
* // Verify the queue maintains insertion order
|
|
899
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
900
|
+
*
|
|
901
|
+
* // Check length
|
|
902
|
+
* console.log(queue.length); // 5;
|
|
903
|
+
*/
|
|
594
904
|
push(element) {
|
|
595
905
|
this.elements.push(element);
|
|
596
906
|
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
@@ -611,10 +921,35 @@ var binaryTreeTyped = (() => {
|
|
|
611
921
|
return ans;
|
|
612
922
|
}
|
|
613
923
|
/**
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
924
|
+
* Dequeue one element from the front (amortized via offset).
|
|
925
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
926
|
+
* @returns Removed element or undefined.
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
* @example
|
|
939
|
+
* // Queue shift and peek operations
|
|
940
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
941
|
+
*
|
|
942
|
+
* // Peek at the front element without removing it
|
|
943
|
+
* console.log(queue.first); // 10;
|
|
944
|
+
*
|
|
945
|
+
* // Remove and get the first element (FIFO)
|
|
946
|
+
* const first = queue.shift();
|
|
947
|
+
* console.log(first); // 10;
|
|
948
|
+
*
|
|
949
|
+
* // Verify remaining elements and length decreased
|
|
950
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
951
|
+
* console.log(queue.length); // 3;
|
|
952
|
+
*/
|
|
618
953
|
shift() {
|
|
619
954
|
if (this.length === 0) return void 0;
|
|
620
955
|
const first = this.first;
|
|
@@ -623,11 +958,24 @@ var binaryTreeTyped = (() => {
|
|
|
623
958
|
return first;
|
|
624
959
|
}
|
|
625
960
|
/**
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
961
|
+
* Delete the first occurrence of a specific element.
|
|
962
|
+
* @remarks Time O(N), Space O(1)
|
|
963
|
+
* @param element - Element to remove (strict equality via Object.is).
|
|
964
|
+
* @returns True if an element was removed.
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
* @example
|
|
974
|
+
* // Remove specific element
|
|
975
|
+
* const q = new Queue<number>([1, 2, 3, 2]);
|
|
976
|
+
* q.delete(2);
|
|
977
|
+
* console.log(q.length); // 3;
|
|
978
|
+
*/
|
|
631
979
|
delete(element) {
|
|
632
980
|
for (let i = this._offset; i < this.elements.length; i++) {
|
|
633
981
|
if (Object.is(this.elements[i], element)) {
|
|
@@ -638,11 +986,24 @@ var binaryTreeTyped = (() => {
|
|
|
638
986
|
return false;
|
|
639
987
|
}
|
|
640
988
|
/**
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
989
|
+
* Get the element at a given logical index.
|
|
990
|
+
* @remarks Time O(1), Space O(1)
|
|
991
|
+
* @param index - Zero-based index from the front.
|
|
992
|
+
* @returns Element or undefined.
|
|
993
|
+
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
* @example
|
|
1002
|
+
* // Access element by index
|
|
1003
|
+
* const q = new Queue<string>(['a', 'b', 'c']);
|
|
1004
|
+
* console.log(q.at(0)); // 'a';
|
|
1005
|
+
* console.log(q.at(2)); // 'c';
|
|
1006
|
+
*/
|
|
646
1007
|
at(index) {
|
|
647
1008
|
if (index < 0 || index >= this.length) return void 0;
|
|
648
1009
|
return this._elements[this._offset + index];
|
|
@@ -694,19 +1055,48 @@ var binaryTreeTyped = (() => {
|
|
|
694
1055
|
return this;
|
|
695
1056
|
}
|
|
696
1057
|
/**
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
1058
|
+
* Remove all elements and reset offset.
|
|
1059
|
+
* @remarks Time O(1), Space O(1)
|
|
1060
|
+
* @returns void
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
* @example
|
|
1071
|
+
* // Remove all elements
|
|
1072
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1073
|
+
* q.clear();
|
|
1074
|
+
* console.log(q.length); // 0;
|
|
1075
|
+
*/
|
|
701
1076
|
clear() {
|
|
702
1077
|
this._elements = [];
|
|
703
1078
|
this._offset = 0;
|
|
704
1079
|
}
|
|
705
1080
|
/**
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
1081
|
+
* Compact storage by discarding consumed head elements.
|
|
1082
|
+
* @remarks Time O(N), Space O(N)
|
|
1083
|
+
* @returns True when compaction performed.
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
* @example
|
|
1093
|
+
* // Reclaim unused memory
|
|
1094
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1095
|
+
* q.shift();
|
|
1096
|
+
* q.shift();
|
|
1097
|
+
* q.compact();
|
|
1098
|
+
* console.log(q.length); // 3;
|
|
1099
|
+
*/
|
|
710
1100
|
compact() {
|
|
711
1101
|
this._elements = this.elements.slice(this._offset);
|
|
712
1102
|
this._offset = 0;
|
|
@@ -732,10 +1122,26 @@ var binaryTreeTyped = (() => {
|
|
|
732
1122
|
return removed;
|
|
733
1123
|
}
|
|
734
1124
|
/**
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
1125
|
+
* Deep clone this queue and its parameters.
|
|
1126
|
+
* @remarks Time O(N), Space O(N)
|
|
1127
|
+
* @returns A new queue with the same content and options.
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
* @example
|
|
1138
|
+
* // Create independent copy
|
|
1139
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1140
|
+
* const copy = q.clone();
|
|
1141
|
+
* copy.shift();
|
|
1142
|
+
* console.log(q.length); // 3;
|
|
1143
|
+
* console.log(copy.length); // 2;
|
|
1144
|
+
*/
|
|
739
1145
|
clone() {
|
|
740
1146
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
741
1147
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -743,12 +1149,26 @@ var binaryTreeTyped = (() => {
|
|
|
743
1149
|
return out;
|
|
744
1150
|
}
|
|
745
1151
|
/**
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1152
|
+
* Filter elements into a new queue of the same class.
|
|
1153
|
+
* @remarks Time O(N), Space O(N)
|
|
1154
|
+
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
1155
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1156
|
+
* @returns A new queue with kept elements.
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
* @example
|
|
1167
|
+
* // Filter elements
|
|
1168
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1169
|
+
* const evens = q.filter(x => x % 2 === 0);
|
|
1170
|
+
* console.log(evens.length); // 2;
|
|
1171
|
+
*/
|
|
752
1172
|
filter(predicate, thisArg) {
|
|
753
1173
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
754
1174
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -760,15 +1180,28 @@ var binaryTreeTyped = (() => {
|
|
|
760
1180
|
return out;
|
|
761
1181
|
}
|
|
762
1182
|
/**
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
1183
|
+
* Map each element to a new element in a possibly different-typed queue.
|
|
1184
|
+
* @remarks Time O(N), Space O(N)
|
|
1185
|
+
* @template EM
|
|
1186
|
+
* @template RM
|
|
1187
|
+
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
1188
|
+
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
1189
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1190
|
+
* @returns A new Queue with mapped elements.
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
|
|
1199
|
+
* @example
|
|
1200
|
+
* // Transform elements
|
|
1201
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1202
|
+
* const doubled = q.map(x => x * 2);
|
|
1203
|
+
* console.log(doubled.toArray()); // [2, 4, 6];
|
|
1204
|
+
*/
|
|
772
1205
|
map(callback, options, thisArg) {
|
|
773
1206
|
var _a, _b;
|
|
774
1207
|
const out = new this.constructor([], {
|
|
@@ -857,206 +1290,6 @@ var binaryTreeTyped = (() => {
|
|
|
857
1290
|
}
|
|
858
1291
|
};
|
|
859
1292
|
|
|
860
|
-
// src/data-structures/base/iterable-entry-base.ts
|
|
861
|
-
var IterableEntryBase = class {
|
|
862
|
-
/**
|
|
863
|
-
* Default iterator yielding `[key, value]` entries.
|
|
864
|
-
* @returns Iterator of `[K, V]`.
|
|
865
|
-
* @remarks Time O(n) to iterate, Space O(1)
|
|
866
|
-
*/
|
|
867
|
-
*[Symbol.iterator](...args) {
|
|
868
|
-
yield* this._getIterator(...args);
|
|
869
|
-
}
|
|
870
|
-
/**
|
|
871
|
-
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
872
|
-
* @returns Iterator of `[K, V | undefined]`.
|
|
873
|
-
* @remarks Time O(n), Space O(1)
|
|
874
|
-
*/
|
|
875
|
-
*entries() {
|
|
876
|
-
for (const item of this) {
|
|
877
|
-
yield item;
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
/**
|
|
881
|
-
* Iterate over keys only.
|
|
882
|
-
* @returns Iterator of keys.
|
|
883
|
-
* @remarks Time O(n), Space O(1)
|
|
884
|
-
*/
|
|
885
|
-
*keys() {
|
|
886
|
-
for (const item of this) {
|
|
887
|
-
yield item[0];
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
/**
|
|
891
|
-
* Iterate over values only.
|
|
892
|
-
* @returns Iterator of values.
|
|
893
|
-
* @remarks Time O(n), Space O(1)
|
|
894
|
-
*/
|
|
895
|
-
*values() {
|
|
896
|
-
for (const item of this) {
|
|
897
|
-
yield item[1];
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
/**
|
|
901
|
-
* Test whether all entries satisfy the predicate.
|
|
902
|
-
* @param predicate - `(key, value, index, self) => boolean`.
|
|
903
|
-
* @param thisArg - Optional `this` for callback.
|
|
904
|
-
* @returns `true` if all pass; otherwise `false`.
|
|
905
|
-
* @remarks Time O(n), Space O(1)
|
|
906
|
-
*/
|
|
907
|
-
every(predicate, thisArg) {
|
|
908
|
-
let index = 0;
|
|
909
|
-
for (const item of this) {
|
|
910
|
-
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
911
|
-
return false;
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
return true;
|
|
915
|
-
}
|
|
916
|
-
/**
|
|
917
|
-
* Test whether any entry satisfies the predicate.
|
|
918
|
-
* @param predicate - `(key, value, index, self) => boolean`.
|
|
919
|
-
* @param thisArg - Optional `this` for callback.
|
|
920
|
-
* @returns `true` if any passes; otherwise `false`.
|
|
921
|
-
* @remarks Time O(n), Space O(1)
|
|
922
|
-
*/
|
|
923
|
-
some(predicate, thisArg) {
|
|
924
|
-
let index = 0;
|
|
925
|
-
for (const item of this) {
|
|
926
|
-
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
927
|
-
return true;
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
return false;
|
|
931
|
-
}
|
|
932
|
-
/**
|
|
933
|
-
* Visit each entry, left-to-right.
|
|
934
|
-
* @param callbackfn - `(key, value, index, self) => void`.
|
|
935
|
-
* @param thisArg - Optional `this` for callback.
|
|
936
|
-
* @remarks Time O(n), Space O(1)
|
|
937
|
-
*/
|
|
938
|
-
forEach(callbackfn, thisArg) {
|
|
939
|
-
let index = 0;
|
|
940
|
-
for (const item of this) {
|
|
941
|
-
const [key, value] = item;
|
|
942
|
-
callbackfn.call(thisArg, value, key, index++, this);
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
/**
|
|
946
|
-
* Find the first entry that matches a predicate.
|
|
947
|
-
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
948
|
-
* @param thisArg - Optional `this` for callback.
|
|
949
|
-
* @returns Matching `[key, value]` or `undefined`.
|
|
950
|
-
* @remarks Time O(n), Space O(1)
|
|
951
|
-
*/
|
|
952
|
-
find(callbackfn, thisArg) {
|
|
953
|
-
let index = 0;
|
|
954
|
-
for (const item of this) {
|
|
955
|
-
const [key, value] = item;
|
|
956
|
-
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
957
|
-
}
|
|
958
|
-
return;
|
|
959
|
-
}
|
|
960
|
-
/**
|
|
961
|
-
* Whether the given key exists.
|
|
962
|
-
* @param key - Key to test.
|
|
963
|
-
* @returns `true` if found; otherwise `false`.
|
|
964
|
-
* @remarks Time O(n) generic, Space O(1)
|
|
965
|
-
*/
|
|
966
|
-
has(key) {
|
|
967
|
-
for (const item of this) {
|
|
968
|
-
const [itemKey] = item;
|
|
969
|
-
if (itemKey === key) return true;
|
|
970
|
-
}
|
|
971
|
-
return false;
|
|
972
|
-
}
|
|
973
|
-
/**
|
|
974
|
-
* Whether there exists an entry with the given value.
|
|
975
|
-
* @param value - Value to test.
|
|
976
|
-
* @returns `true` if found; otherwise `false`.
|
|
977
|
-
* @remarks Time O(n), Space O(1)
|
|
978
|
-
*/
|
|
979
|
-
hasValue(value) {
|
|
980
|
-
for (const [, elementValue] of this) {
|
|
981
|
-
if (elementValue === value) return true;
|
|
982
|
-
}
|
|
983
|
-
return false;
|
|
984
|
-
}
|
|
985
|
-
/**
|
|
986
|
-
* Get the value under a key.
|
|
987
|
-
* @param key - Key to look up.
|
|
988
|
-
* @returns Value or `undefined`.
|
|
989
|
-
* @remarks Time O(n) generic, Space O(1)
|
|
990
|
-
*/
|
|
991
|
-
get(key) {
|
|
992
|
-
for (const item of this) {
|
|
993
|
-
const [itemKey, value] = item;
|
|
994
|
-
if (itemKey === key) return value;
|
|
995
|
-
}
|
|
996
|
-
return;
|
|
997
|
-
}
|
|
998
|
-
/**
|
|
999
|
-
* Reduce entries into a single accumulator.
|
|
1000
|
-
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
1001
|
-
* @param initialValue - Initial accumulator.
|
|
1002
|
-
* @returns Final accumulator.
|
|
1003
|
-
* @remarks Time O(n), Space O(1)
|
|
1004
|
-
*/
|
|
1005
|
-
reduce(callbackfn, initialValue) {
|
|
1006
|
-
let accumulator = initialValue;
|
|
1007
|
-
let index = 0;
|
|
1008
|
-
for (const item of this) {
|
|
1009
|
-
const [key, value] = item;
|
|
1010
|
-
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
1011
|
-
}
|
|
1012
|
-
return accumulator;
|
|
1013
|
-
}
|
|
1014
|
-
/**
|
|
1015
|
-
* Converts data structure to `[key, value]` pairs.
|
|
1016
|
-
* @returns Array of entries.
|
|
1017
|
-
* @remarks Time O(n), Space O(n)
|
|
1018
|
-
*/
|
|
1019
|
-
toArray() {
|
|
1020
|
-
return [...this];
|
|
1021
|
-
}
|
|
1022
|
-
/**
|
|
1023
|
-
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
1024
|
-
* @returns Array of entries (default) or a string.
|
|
1025
|
-
* @remarks Time O(n), Space O(n)
|
|
1026
|
-
*/
|
|
1027
|
-
toVisual() {
|
|
1028
|
-
return [...this];
|
|
1029
|
-
}
|
|
1030
|
-
/**
|
|
1031
|
-
* Print a human-friendly representation to the console.
|
|
1032
|
-
* @remarks Time O(n), Space O(n)
|
|
1033
|
-
*/
|
|
1034
|
-
print() {
|
|
1035
|
-
console.log(this.toVisual());
|
|
1036
|
-
}
|
|
1037
|
-
};
|
|
1038
|
-
|
|
1039
|
-
// src/common/index.ts
|
|
1040
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
1041
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
1042
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
1043
|
-
return DFSOperation2;
|
|
1044
|
-
})(DFSOperation || {});
|
|
1045
|
-
var Range = class {
|
|
1046
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
1047
|
-
this.low = low;
|
|
1048
|
-
this.high = high;
|
|
1049
|
-
this.includeLow = includeLow;
|
|
1050
|
-
this.includeHigh = includeHigh;
|
|
1051
|
-
}
|
|
1052
|
-
// Determine whether a key is within the range
|
|
1053
|
-
isInRange(key, comparator) {
|
|
1054
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
1055
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
1056
|
-
return lowCheck && highCheck;
|
|
1057
|
-
}
|
|
1058
|
-
};
|
|
1059
|
-
|
|
1060
1293
|
// src/data-structures/binary-tree/binary-tree.ts
|
|
1061
1294
|
var BinaryTreeNode = class {
|
|
1062
1295
|
/**
|
|
@@ -1192,7 +1425,7 @@ var binaryTreeTyped = (() => {
|
|
|
1192
1425
|
return "MAL_NODE";
|
|
1193
1426
|
}
|
|
1194
1427
|
};
|
|
1195
|
-
var BinaryTree = class extends IterableEntryBase {
|
|
1428
|
+
var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
1196
1429
|
/**
|
|
1197
1430
|
* Creates an instance of BinaryTree.
|
|
1198
1431
|
* @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.
|
|
@@ -1227,7 +1460,7 @@ var binaryTreeTyped = (() => {
|
|
|
1227
1460
|
if (isMapMode !== void 0) this._isMapMode = isMapMode;
|
|
1228
1461
|
if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
|
|
1229
1462
|
if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
|
|
1230
|
-
else if (toEntryFn) throw TypeError("toEntryFn
|
|
1463
|
+
else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
|
|
1231
1464
|
}
|
|
1232
1465
|
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
1233
1466
|
}
|
|
@@ -1432,30 +1665,78 @@ var binaryTreeTyped = (() => {
|
|
|
1432
1665
|
return isComparable(key);
|
|
1433
1666
|
}
|
|
1434
1667
|
/**
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1668
|
+
* Adds a new node to the tree.
|
|
1669
|
+
* @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).
|
|
1670
|
+
*
|
|
1671
|
+
* @param keyNodeOrEntry - The key, node, or entry to add.
|
|
1672
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1673
|
+
|
|
1674
|
+
|
|
1675
|
+
|
|
1676
|
+
|
|
1677
|
+
|
|
1678
|
+
|
|
1679
|
+
* @example
|
|
1680
|
+
* // Add a single node
|
|
1681
|
+
* const tree = new BinaryTree<number>();
|
|
1682
|
+
* tree.add(1);
|
|
1683
|
+
* tree.add(2);
|
|
1684
|
+
* tree.add(3);
|
|
1685
|
+
* console.log(tree.size); // 3;
|
|
1686
|
+
* console.log(tree.has(1)); // true;
|
|
1687
|
+
*/
|
|
1441
1688
|
add(keyNodeOrEntry) {
|
|
1442
1689
|
return this.set(keyNodeOrEntry);
|
|
1443
1690
|
}
|
|
1444
1691
|
/**
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1692
|
+
* Adds or updates a new node to the tree.
|
|
1693
|
+
* @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).
|
|
1694
|
+
*
|
|
1695
|
+
* @param keyNodeOrEntry - The key, node, or entry to set or update.
|
|
1696
|
+
* @param [value] - The value, if providing just a key.
|
|
1697
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1698
|
+
|
|
1699
|
+
|
|
1700
|
+
|
|
1701
|
+
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
|
|
1705
|
+
|
|
1706
|
+
|
|
1707
|
+
|
|
1708
|
+
|
|
1709
|
+
* @example
|
|
1710
|
+
* // basic BinaryTree creation and insertion
|
|
1711
|
+
* // Create a BinaryTree with entries
|
|
1712
|
+
* const entries: [number, string][] = [
|
|
1713
|
+
* [6, 'six'],
|
|
1714
|
+
* [1, 'one'],
|
|
1715
|
+
* [2, 'two'],
|
|
1716
|
+
* [7, 'seven'],
|
|
1717
|
+
* [5, 'five'],
|
|
1718
|
+
* [3, 'three'],
|
|
1719
|
+
* [4, 'four'],
|
|
1720
|
+
* [9, 'nine'],
|
|
1721
|
+
* [8, 'eight']
|
|
1722
|
+
* ];
|
|
1723
|
+
*
|
|
1724
|
+
* const tree = new BinaryTree(entries);
|
|
1725
|
+
*
|
|
1726
|
+
* // Verify size
|
|
1727
|
+
* console.log(tree.size); // 9;
|
|
1728
|
+
*
|
|
1729
|
+
* // Add new element
|
|
1730
|
+
* tree.set(10, 'ten');
|
|
1731
|
+
* console.log(tree.size); // 10;
|
|
1732
|
+
*/
|
|
1452
1733
|
set(keyNodeOrEntry, value) {
|
|
1453
1734
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
1454
1735
|
if (newNode === void 0) return false;
|
|
1455
1736
|
if (!this._root) {
|
|
1456
1737
|
this._setRoot(newNode);
|
|
1457
1738
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
1458
|
-
this._size = 1;
|
|
1739
|
+
if (newNode !== null) this._size = 1;
|
|
1459
1740
|
return true;
|
|
1460
1741
|
}
|
|
1461
1742
|
const queue = new Queue([this._root]);
|
|
@@ -1487,29 +1768,50 @@ var binaryTreeTyped = (() => {
|
|
|
1487
1768
|
potentialParent.right = newNode;
|
|
1488
1769
|
}
|
|
1489
1770
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
1490
|
-
this._size++;
|
|
1771
|
+
if (newNode !== null) this._size++;
|
|
1491
1772
|
return true;
|
|
1492
1773
|
}
|
|
1493
1774
|
return false;
|
|
1494
1775
|
}
|
|
1495
1776
|
/**
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1777
|
+
* Adds multiple items to the tree.
|
|
1778
|
+
* @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).
|
|
1779
|
+
*
|
|
1780
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
1781
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1782
|
+
|
|
1783
|
+
|
|
1784
|
+
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
|
|
1788
|
+
|
|
1789
|
+
|
|
1790
|
+
|
|
1791
|
+
* @example
|
|
1792
|
+
* // Bulk add
|
|
1793
|
+
* const tree = new BinaryTree<number>();
|
|
1794
|
+
* tree.addMany([1, 2, 3, 4, 5]);
|
|
1795
|
+
* console.log(tree.size); // 5;
|
|
1796
|
+
*/
|
|
1502
1797
|
addMany(keysNodesEntriesOrRaws) {
|
|
1503
1798
|
return this.setMany(keysNodesEntriesOrRaws);
|
|
1504
1799
|
}
|
|
1505
1800
|
/**
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1801
|
+
* Adds or updates multiple items to the tree.
|
|
1802
|
+
* @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).
|
|
1803
|
+
*
|
|
1804
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set or update.
|
|
1805
|
+
* @param [values] - An optional parallel iterable of values.
|
|
1806
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1807
|
+
|
|
1808
|
+
|
|
1809
|
+
* @example
|
|
1810
|
+
* // Set multiple entries
|
|
1811
|
+
* const tree = new BinaryTree<number, string>();
|
|
1812
|
+
* tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
1813
|
+
* console.log(tree.size); // 3;
|
|
1814
|
+
*/
|
|
1513
1815
|
setMany(keysNodesEntriesOrRaws, values) {
|
|
1514
1816
|
const inserted = [];
|
|
1515
1817
|
let valuesIterator;
|
|
@@ -1530,11 +1832,26 @@ var binaryTreeTyped = (() => {
|
|
|
1530
1832
|
return inserted;
|
|
1531
1833
|
}
|
|
1532
1834
|
/**
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1835
|
+
* Merges another tree into this one by seting all its nodes.
|
|
1836
|
+
* @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`).
|
|
1837
|
+
*
|
|
1838
|
+
* @param anotherTree - The tree to merge.
|
|
1839
|
+
|
|
1840
|
+
|
|
1841
|
+
|
|
1842
|
+
|
|
1843
|
+
|
|
1844
|
+
|
|
1845
|
+
|
|
1846
|
+
|
|
1847
|
+
|
|
1848
|
+
* @example
|
|
1849
|
+
* // Combine trees
|
|
1850
|
+
* const t1 = new BinaryTree<number>([1, 2]);
|
|
1851
|
+
* const t2 = new BinaryTree<number>([3, 4]);
|
|
1852
|
+
* t1.merge(t2);
|
|
1853
|
+
* console.log(t1.size); // 4;
|
|
1854
|
+
*/
|
|
1538
1855
|
merge(anotherTree) {
|
|
1539
1856
|
this.setMany(anotherTree, []);
|
|
1540
1857
|
}
|
|
@@ -1550,12 +1867,29 @@ var binaryTreeTyped = (() => {
|
|
|
1550
1867
|
this.setMany(keysNodesEntriesOrRaws, values);
|
|
1551
1868
|
}
|
|
1552
1869
|
/**
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1870
|
+
* Deletes a node from the tree.
|
|
1871
|
+
* @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).
|
|
1872
|
+
*
|
|
1873
|
+
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
1874
|
+
* @returns An array containing deletion results (for compatibility with self-balancing trees).
|
|
1875
|
+
|
|
1876
|
+
|
|
1877
|
+
|
|
1878
|
+
|
|
1879
|
+
|
|
1880
|
+
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
|
|
1885
|
+
|
|
1886
|
+
* @example
|
|
1887
|
+
* // Remove a node
|
|
1888
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
1889
|
+
* tree.delete(3);
|
|
1890
|
+
* console.log(tree.has(3)); // false;
|
|
1891
|
+
* console.log(tree.size); // 4;
|
|
1892
|
+
*/
|
|
1559
1893
|
delete(keyNodeEntryRawOrPredicate) {
|
|
1560
1894
|
const deletedResult = [];
|
|
1561
1895
|
if (!this._root) return deletedResult;
|
|
@@ -1649,14 +1983,27 @@ var binaryTreeTyped = (() => {
|
|
|
1649
1983
|
return this.search(keyNodeEntryOrPredicate, onlyOne, (node) => node, startNode, iterationType);
|
|
1650
1984
|
}
|
|
1651
1985
|
/**
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1986
|
+
* Gets the first node matching a predicate.
|
|
1987
|
+
* @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`).
|
|
1988
|
+
*
|
|
1989
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
1990
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
1991
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1992
|
+
* @returns The first matching node, or undefined if not found.
|
|
1993
|
+
|
|
1994
|
+
|
|
1995
|
+
|
|
1996
|
+
|
|
1997
|
+
|
|
1998
|
+
|
|
1999
|
+
|
|
2000
|
+
|
|
2001
|
+
|
|
2002
|
+
* @example
|
|
2003
|
+
* // Get node by key
|
|
2004
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
|
|
2005
|
+
* console.log(tree.getNode(2)?.value); // 'child';
|
|
2006
|
+
*/
|
|
1660
2007
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1661
2008
|
if (this._isMapMode && keyNodeEntryOrPredicate !== null && keyNodeEntryOrPredicate !== void 0) {
|
|
1662
2009
|
if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
@@ -1668,14 +2015,30 @@ var binaryTreeTyped = (() => {
|
|
|
1668
2015
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType)[0];
|
|
1669
2016
|
}
|
|
1670
2017
|
/**
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
2018
|
+
* Gets the value associated with a key.
|
|
2019
|
+
* @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.
|
|
2020
|
+
*
|
|
2021
|
+
* @param keyNodeEntryOrPredicate - The key, node, or entry to get the value for.
|
|
2022
|
+
* @param [startNode=this._root] - The node to start searching from (if not in Map mode).
|
|
2023
|
+
* @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
|
|
2024
|
+
* @returns The associated value, or undefined.
|
|
2025
|
+
|
|
2026
|
+
|
|
2027
|
+
|
|
2028
|
+
|
|
2029
|
+
|
|
2030
|
+
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
|
|
2034
|
+
|
|
2035
|
+
|
|
2036
|
+
* @example
|
|
2037
|
+
* // Retrieve value by key
|
|
2038
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
|
|
2039
|
+
* console.log(tree.get(2)); // 'left';
|
|
2040
|
+
* console.log(tree.get(99)); // undefined;
|
|
2041
|
+
*/
|
|
1679
2042
|
get(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1680
2043
|
var _a, _b;
|
|
1681
2044
|
if (this._isMapMode) {
|
|
@@ -1696,19 +2059,45 @@ var binaryTreeTyped = (() => {
|
|
|
1696
2059
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType).length > 0;
|
|
1697
2060
|
}
|
|
1698
2061
|
/**
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
2062
|
+
* Clears the tree of all nodes and values.
|
|
2063
|
+
* @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
|
|
2064
|
+
|
|
2065
|
+
|
|
2066
|
+
|
|
2067
|
+
|
|
2068
|
+
|
|
2069
|
+
|
|
2070
|
+
|
|
2071
|
+
|
|
2072
|
+
|
|
2073
|
+
* @example
|
|
2074
|
+
* // Remove all nodes
|
|
2075
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2076
|
+
* tree.clear();
|
|
2077
|
+
* console.log(tree.isEmpty()); // true;
|
|
2078
|
+
*/
|
|
1702
2079
|
clear() {
|
|
1703
2080
|
this._clearNodes();
|
|
1704
2081
|
if (this._isMapMode) this._clearValues();
|
|
1705
2082
|
}
|
|
1706
2083
|
/**
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
2084
|
+
* Checks if the tree is empty.
|
|
2085
|
+
* @remarks Time O(1), Space O(1)
|
|
2086
|
+
*
|
|
2087
|
+
* @returns True if the tree has no nodes, false otherwise.
|
|
2088
|
+
|
|
2089
|
+
|
|
2090
|
+
|
|
2091
|
+
|
|
2092
|
+
|
|
2093
|
+
|
|
2094
|
+
|
|
2095
|
+
|
|
2096
|
+
|
|
2097
|
+
* @example
|
|
2098
|
+
* // Check empty
|
|
2099
|
+
* console.log(new BinaryTree().isEmpty()); // true;
|
|
2100
|
+
*/
|
|
1712
2101
|
isEmpty() {
|
|
1713
2102
|
return this._size === 0;
|
|
1714
2103
|
}
|
|
@@ -1723,13 +2112,27 @@ var binaryTreeTyped = (() => {
|
|
|
1723
2112
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
1724
2113
|
}
|
|
1725
2114
|
/**
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
2115
|
+
* Checks if the tree is a valid Binary Search Tree (BST).
|
|
2116
|
+
* @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).
|
|
2117
|
+
*
|
|
2118
|
+
* @param [startNode=this._root] - The node to start checking from.
|
|
2119
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2120
|
+
* @returns True if it's a valid BST, false otherwise.
|
|
2121
|
+
|
|
2122
|
+
|
|
2123
|
+
|
|
2124
|
+
|
|
2125
|
+
|
|
2126
|
+
|
|
2127
|
+
|
|
2128
|
+
|
|
2129
|
+
|
|
2130
|
+
* @example
|
|
2131
|
+
* // Check BST property
|
|
2132
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2133
|
+
* // BinaryTree doesn't guarantee BST order
|
|
2134
|
+
* console.log(typeof tree.isBST()); // 'boolean';
|
|
2135
|
+
*/
|
|
1733
2136
|
isBST(startNode = this._root, iterationType = this.iterationType) {
|
|
1734
2137
|
const startNodeSired = this.ensureNode(startNode);
|
|
1735
2138
|
if (!startNodeSired) return true;
|
|
@@ -1767,13 +2170,29 @@ var binaryTreeTyped = (() => {
|
|
|
1767
2170
|
}
|
|
1768
2171
|
}
|
|
1769
2172
|
/**
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
2173
|
+
* Gets the depth of a node (distance from `startNode`).
|
|
2174
|
+
* @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
|
|
2175
|
+
*
|
|
2176
|
+
* @param dist - The node to find the depth of.
|
|
2177
|
+
* @param [startNode=this._root] - The node to measure depth from (defaults to root).
|
|
2178
|
+
* @returns The depth (0 if `dist` is `startNode`).
|
|
2179
|
+
|
|
2180
|
+
|
|
2181
|
+
|
|
2182
|
+
|
|
2183
|
+
|
|
2184
|
+
|
|
2185
|
+
|
|
2186
|
+
|
|
2187
|
+
|
|
2188
|
+
|
|
2189
|
+
|
|
2190
|
+
* @example
|
|
2191
|
+
* // Get depth of a node
|
|
2192
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2193
|
+
* const node = tree.getNode(4);
|
|
2194
|
+
* console.log(tree.getDepth(node!)); // 2;
|
|
2195
|
+
*/
|
|
1777
2196
|
getDepth(dist, startNode = this._root) {
|
|
1778
2197
|
let distEnsured = this.ensureNode(dist);
|
|
1779
2198
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
@@ -1788,13 +2207,28 @@ var binaryTreeTyped = (() => {
|
|
|
1788
2207
|
return depth;
|
|
1789
2208
|
}
|
|
1790
2209
|
/**
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
2210
|
+
* Gets the maximum height of the tree (longest path from startNode to a leaf).
|
|
2211
|
+
* @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).
|
|
2212
|
+
*
|
|
2213
|
+
* @param [startNode=this._root] - The node to start measuring from.
|
|
2214
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2215
|
+
* @returns The height ( -1 for an empty tree, 0 for a single-node tree).
|
|
2216
|
+
|
|
2217
|
+
|
|
2218
|
+
|
|
2219
|
+
|
|
2220
|
+
|
|
2221
|
+
|
|
2222
|
+
|
|
2223
|
+
|
|
2224
|
+
|
|
2225
|
+
|
|
2226
|
+
|
|
2227
|
+
* @example
|
|
2228
|
+
* // Get tree height
|
|
2229
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2230
|
+
* console.log(tree.getHeight()); // 2;
|
|
2231
|
+
*/
|
|
1798
2232
|
getHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
1799
2233
|
startNode = this.ensureNode(startNode);
|
|
1800
2234
|
if (!this.isRealNode(startNode)) return -1;
|
|
@@ -2056,7 +2490,7 @@ var binaryTreeTyped = (() => {
|
|
|
2056
2490
|
}
|
|
2057
2491
|
/**
|
|
2058
2492
|
* Finds all leaf nodes in the tree.
|
|
2059
|
-
* @remarks Time O(N), visits every node. Space O(H) for recursive
|
|
2493
|
+
* @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
|
|
2060
2494
|
*
|
|
2061
2495
|
* @template C - The type of the callback function.
|
|
2062
2496
|
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
|
|
@@ -2079,15 +2513,15 @@ var binaryTreeTyped = (() => {
|
|
|
2079
2513
|
};
|
|
2080
2514
|
dfs(startNode);
|
|
2081
2515
|
} else {
|
|
2082
|
-
const
|
|
2083
|
-
while (
|
|
2084
|
-
const cur =
|
|
2516
|
+
const stack = [startNode];
|
|
2517
|
+
while (stack.length > 0) {
|
|
2518
|
+
const cur = stack.pop();
|
|
2085
2519
|
if (this.isRealNode(cur)) {
|
|
2086
2520
|
if (this.isLeaf(cur)) {
|
|
2087
2521
|
leaves.push(callback(cur));
|
|
2088
2522
|
}
|
|
2089
|
-
if (this.isRealNode(cur.
|
|
2090
|
-
if (this.isRealNode(cur.
|
|
2523
|
+
if (this.isRealNode(cur.right)) stack.push(cur.right);
|
|
2524
|
+
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
|
2091
2525
|
}
|
|
2092
2526
|
}
|
|
2093
2527
|
}
|
|
@@ -2230,24 +2664,53 @@ var binaryTreeTyped = (() => {
|
|
|
2230
2664
|
return ans;
|
|
2231
2665
|
}
|
|
2232
2666
|
/**
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2667
|
+
* Clones the tree.
|
|
2668
|
+
* @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.
|
|
2669
|
+
*
|
|
2670
|
+
* @returns A new, cloned instance of the tree.
|
|
2671
|
+
|
|
2672
|
+
|
|
2673
|
+
|
|
2674
|
+
|
|
2675
|
+
|
|
2676
|
+
|
|
2677
|
+
|
|
2678
|
+
|
|
2679
|
+
|
|
2680
|
+
* @example
|
|
2681
|
+
* // Deep copy
|
|
2682
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2683
|
+
* const copy = tree.clone();
|
|
2684
|
+
* copy.delete(1);
|
|
2685
|
+
* console.log(tree.has(1)); // true;
|
|
2686
|
+
*/
|
|
2238
2687
|
clone() {
|
|
2239
2688
|
const out = this._createInstance();
|
|
2240
2689
|
this._clone(out);
|
|
2241
2690
|
return out;
|
|
2242
2691
|
}
|
|
2243
2692
|
/**
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2693
|
+
* Creates a new tree containing only the entries that satisfy the predicate.
|
|
2694
|
+
* @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.
|
|
2695
|
+
*
|
|
2696
|
+
* @param predicate - A function to test each [key, value] pair.
|
|
2697
|
+
* @param [thisArg] - `this` context for the predicate.
|
|
2698
|
+
* @returns A new, filtered tree.
|
|
2699
|
+
|
|
2700
|
+
|
|
2701
|
+
|
|
2702
|
+
|
|
2703
|
+
|
|
2704
|
+
|
|
2705
|
+
|
|
2706
|
+
|
|
2707
|
+
|
|
2708
|
+
* @example
|
|
2709
|
+
* // Filter nodes by condition
|
|
2710
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4]);
|
|
2711
|
+
* const result = tree.filter((_, key) => key > 2);
|
|
2712
|
+
* console.log(result.size); // 2;
|
|
2713
|
+
*/
|
|
2251
2714
|
filter(predicate, thisArg) {
|
|
2252
2715
|
const out = this._createInstance();
|
|
2253
2716
|
let i = 0;
|
|
@@ -2255,17 +2718,31 @@ var binaryTreeTyped = (() => {
|
|
|
2255
2718
|
return out;
|
|
2256
2719
|
}
|
|
2257
2720
|
/**
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2721
|
+
* Creates a new tree by mapping each [key, value] pair to a new entry.
|
|
2722
|
+
* @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.
|
|
2723
|
+
*
|
|
2724
|
+
* @template MK - New key type.
|
|
2725
|
+
* @template MV - New value type.
|
|
2726
|
+
* @template MR - New raw type.
|
|
2727
|
+
* @param cb - A function to map each [key, value] pair.
|
|
2728
|
+
* @param [options] - Options for the new tree.
|
|
2729
|
+
* @param [thisArg] - `this` context for the callback.
|
|
2730
|
+
* @returns A new, mapped tree.
|
|
2731
|
+
|
|
2732
|
+
|
|
2733
|
+
|
|
2734
|
+
|
|
2735
|
+
|
|
2736
|
+
|
|
2737
|
+
|
|
2738
|
+
|
|
2739
|
+
|
|
2740
|
+
* @example
|
|
2741
|
+
* // Transform to new tree
|
|
2742
|
+
* const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
|
|
2743
|
+
* const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
|
|
2744
|
+
* console.log([...mapped.values()]); // contains 11;
|
|
2745
|
+
*/
|
|
2269
2746
|
map(cb, options, thisArg) {
|
|
2270
2747
|
const out = this._createLike([], options);
|
|
2271
2748
|
let i = 0;
|
|
@@ -2303,12 +2780,25 @@ var binaryTreeTyped = (() => {
|
|
|
2303
2780
|
return output;
|
|
2304
2781
|
}
|
|
2305
2782
|
/**
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2783
|
+
* Prints a visual representation of the tree to the console.
|
|
2784
|
+
* @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
|
|
2785
|
+
*
|
|
2786
|
+
* @param [options] - Options to control the output.
|
|
2787
|
+
* @param [startNode=this._root] - The node to start printing from.
|
|
2788
|
+
|
|
2789
|
+
|
|
2790
|
+
|
|
2791
|
+
|
|
2792
|
+
|
|
2793
|
+
|
|
2794
|
+
|
|
2795
|
+
|
|
2796
|
+
|
|
2797
|
+
* @example
|
|
2798
|
+
* // Display tree
|
|
2799
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2800
|
+
* expect(() => tree.print()).not.toThrow();
|
|
2801
|
+
*/
|
|
2312
2802
|
print(options, startNode = this._root) {
|
|
2313
2803
|
console.log(this.toVisual(startNode, options));
|
|
2314
2804
|
}
|
|
@@ -2541,44 +3031,99 @@ var binaryTreeTyped = (() => {
|
|
|
2541
3031
|
* @returns Layout information for this subtree.
|
|
2542
3032
|
*/
|
|
2543
3033
|
_displayAux(node, options) {
|
|
2544
|
-
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
2545
3034
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
const
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
3035
|
+
const newFrame = (n) => ({
|
|
3036
|
+
node: n,
|
|
3037
|
+
stage: 0,
|
|
3038
|
+
leftLayout: emptyDisplayLayout,
|
|
3039
|
+
rightLayout: emptyDisplayLayout
|
|
3040
|
+
});
|
|
3041
|
+
const stack = [newFrame(node)];
|
|
3042
|
+
let result = emptyDisplayLayout;
|
|
3043
|
+
const setChildResult = (layout) => {
|
|
3044
|
+
if (stack.length === 0) {
|
|
3045
|
+
result = layout;
|
|
3046
|
+
return;
|
|
3047
|
+
}
|
|
3048
|
+
const parent = stack[stack.length - 1];
|
|
3049
|
+
if (parent.stage === 1) parent.leftLayout = layout;
|
|
3050
|
+
else parent.rightLayout = layout;
|
|
3051
|
+
};
|
|
3052
|
+
while (stack.length > 0) {
|
|
3053
|
+
const frame = stack[stack.length - 1];
|
|
3054
|
+
const cur = frame.node;
|
|
3055
|
+
if (frame.stage === 0) {
|
|
3056
|
+
if (this._isDisplayLeaf(cur, options)) {
|
|
3057
|
+
stack.pop();
|
|
3058
|
+
const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
|
|
3059
|
+
setChildResult(layout);
|
|
3060
|
+
continue;
|
|
3061
|
+
}
|
|
3062
|
+
frame.stage = 1;
|
|
3063
|
+
stack.push(newFrame(cur.left));
|
|
3064
|
+
} else if (frame.stage === 1) {
|
|
3065
|
+
frame.stage = 2;
|
|
3066
|
+
stack.push(newFrame(cur.right));
|
|
3067
|
+
} else {
|
|
3068
|
+
stack.pop();
|
|
3069
|
+
const line = this.isNIL(cur) ? "S" : String(cur.key);
|
|
3070
|
+
const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
|
|
3071
|
+
setChildResult(layout);
|
|
2574
3072
|
}
|
|
2575
|
-
return [
|
|
2576
|
-
mergedLines,
|
|
2577
|
-
leftWidth + width + rightWidth,
|
|
2578
|
-
Math.max(leftHeight, rightHeight) + 2,
|
|
2579
|
-
leftWidth + Math.floor(width / 2)
|
|
2580
|
-
];
|
|
2581
3073
|
}
|
|
3074
|
+
return result;
|
|
3075
|
+
}
|
|
3076
|
+
static _buildNodeDisplay(line, width, left, right) {
|
|
3077
|
+
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
3078
|
+
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
3079
|
+
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));
|
|
3080
|
+
const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
|
|
3081
|
+
const mergedLines = [firstLine, secondLine];
|
|
3082
|
+
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
3083
|
+
const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
|
|
3084
|
+
const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
|
|
3085
|
+
mergedLines.push(leftLine + " ".repeat(width) + rightLine);
|
|
3086
|
+
}
|
|
3087
|
+
return [
|
|
3088
|
+
mergedLines,
|
|
3089
|
+
leftWidth + width + rightWidth,
|
|
3090
|
+
Math.max(leftHeight, rightHeight) + 2,
|
|
3091
|
+
leftWidth + Math.floor(width / 2)
|
|
3092
|
+
];
|
|
3093
|
+
}
|
|
3094
|
+
/**
|
|
3095
|
+
* Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
|
|
3096
|
+
*/
|
|
3097
|
+
_isDisplayLeaf(node, options) {
|
|
3098
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3099
|
+
if (node === null && !isShowNull) return true;
|
|
3100
|
+
if (node === void 0 && !isShowUndefined) return true;
|
|
3101
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return true;
|
|
3102
|
+
if (node === null || node === void 0) return true;
|
|
3103
|
+
const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
|
|
3104
|
+
const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
|
|
3105
|
+
return !hasDisplayableLeft && !hasDisplayableRight;
|
|
3106
|
+
}
|
|
3107
|
+
_hasDisplayableChild(child, options) {
|
|
3108
|
+
if (child === null) return !!options.isShowNull;
|
|
3109
|
+
if (child === void 0) return !!options.isShowUndefined;
|
|
3110
|
+
if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
|
|
3111
|
+
return true;
|
|
3112
|
+
}
|
|
3113
|
+
/**
|
|
3114
|
+
* Resolve a display leaf node to its layout.
|
|
3115
|
+
*/
|
|
3116
|
+
_resolveDisplayLeaf(node, options, emptyDisplayLayout) {
|
|
3117
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3118
|
+
if (node === null && !isShowNull) return emptyDisplayLayout;
|
|
3119
|
+
if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
|
|
3120
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
|
|
3121
|
+
if (node !== null && node !== void 0) {
|
|
3122
|
+
const line2 = this.isNIL(node) ? "S" : String(node.key);
|
|
3123
|
+
return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
|
|
3124
|
+
}
|
|
3125
|
+
const line = node === void 0 ? "U" : "N";
|
|
3126
|
+
return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
|
|
2582
3127
|
}
|
|
2583
3128
|
/**
|
|
2584
3129
|
* (Protected) Swaps the key/value properties of two nodes.
|