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
package/dist/cjs/index.cjs
CHANGED
|
@@ -475,6 +475,237 @@ var LinearBase = class _LinearBase extends IterableElementBase {
|
|
|
475
475
|
}
|
|
476
476
|
};
|
|
477
477
|
|
|
478
|
+
// src/common/error.ts
|
|
479
|
+
var ERR = {
|
|
480
|
+
// Range / index
|
|
481
|
+
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
482
|
+
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
483
|
+
// Type / argument
|
|
484
|
+
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
485
|
+
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
486
|
+
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
487
|
+
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
488
|
+
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
489
|
+
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
490
|
+
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
491
|
+
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
492
|
+
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
493
|
+
// State / operation
|
|
494
|
+
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
495
|
+
// Matrix
|
|
496
|
+
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
497
|
+
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
498
|
+
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
499
|
+
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
500
|
+
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
// src/common/index.ts
|
|
504
|
+
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
505
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
506
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
507
|
+
return DFSOperation2;
|
|
508
|
+
})(DFSOperation || {});
|
|
509
|
+
var Range = class {
|
|
510
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
511
|
+
this.low = low;
|
|
512
|
+
this.high = high;
|
|
513
|
+
this.includeLow = includeLow;
|
|
514
|
+
this.includeHigh = includeHigh;
|
|
515
|
+
}
|
|
516
|
+
static {
|
|
517
|
+
__name(this, "Range");
|
|
518
|
+
}
|
|
519
|
+
// Determine whether a key is within the range
|
|
520
|
+
isInRange(key, comparator) {
|
|
521
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
522
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
523
|
+
return lowCheck && highCheck;
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
528
|
+
var IterableEntryBase = class {
|
|
529
|
+
static {
|
|
530
|
+
__name(this, "IterableEntryBase");
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Default iterator yielding `[key, value]` entries.
|
|
534
|
+
* @returns Iterator of `[K, V]`.
|
|
535
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
536
|
+
*/
|
|
537
|
+
*[Symbol.iterator](...args) {
|
|
538
|
+
yield* this._getIterator(...args);
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
542
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
543
|
+
* @remarks Time O(n), Space O(1)
|
|
544
|
+
*/
|
|
545
|
+
*entries() {
|
|
546
|
+
for (const item of this) {
|
|
547
|
+
yield item;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Iterate over keys only.
|
|
552
|
+
* @returns Iterator of keys.
|
|
553
|
+
* @remarks Time O(n), Space O(1)
|
|
554
|
+
*/
|
|
555
|
+
*keys() {
|
|
556
|
+
for (const item of this) {
|
|
557
|
+
yield item[0];
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Iterate over values only.
|
|
562
|
+
* @returns Iterator of values.
|
|
563
|
+
* @remarks Time O(n), Space O(1)
|
|
564
|
+
*/
|
|
565
|
+
*values() {
|
|
566
|
+
for (const item of this) {
|
|
567
|
+
yield item[1];
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Test whether all entries satisfy the predicate.
|
|
572
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
573
|
+
* @param thisArg - Optional `this` for callback.
|
|
574
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
575
|
+
* @remarks Time O(n), Space O(1)
|
|
576
|
+
*/
|
|
577
|
+
every(predicate, thisArg) {
|
|
578
|
+
let index = 0;
|
|
579
|
+
for (const item of this) {
|
|
580
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Test whether any entry satisfies the predicate.
|
|
588
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
589
|
+
* @param thisArg - Optional `this` for callback.
|
|
590
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
591
|
+
* @remarks Time O(n), Space O(1)
|
|
592
|
+
*/
|
|
593
|
+
some(predicate, thisArg) {
|
|
594
|
+
let index = 0;
|
|
595
|
+
for (const item of this) {
|
|
596
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
597
|
+
return true;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Visit each entry, left-to-right.
|
|
604
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
605
|
+
* @param thisArg - Optional `this` for callback.
|
|
606
|
+
* @remarks Time O(n), Space O(1)
|
|
607
|
+
*/
|
|
608
|
+
forEach(callbackfn, thisArg) {
|
|
609
|
+
let index = 0;
|
|
610
|
+
for (const item of this) {
|
|
611
|
+
const [key, value] = item;
|
|
612
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Find the first entry that matches a predicate.
|
|
617
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
618
|
+
* @param thisArg - Optional `this` for callback.
|
|
619
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
620
|
+
* @remarks Time O(n), Space O(1)
|
|
621
|
+
*/
|
|
622
|
+
find(callbackfn, thisArg) {
|
|
623
|
+
let index = 0;
|
|
624
|
+
for (const item of this) {
|
|
625
|
+
const [key, value] = item;
|
|
626
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
627
|
+
}
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Whether the given key exists.
|
|
632
|
+
* @param key - Key to test.
|
|
633
|
+
* @returns `true` if found; otherwise `false`.
|
|
634
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
635
|
+
*/
|
|
636
|
+
has(key) {
|
|
637
|
+
for (const item of this) {
|
|
638
|
+
const [itemKey] = item;
|
|
639
|
+
if (itemKey === key) return true;
|
|
640
|
+
}
|
|
641
|
+
return false;
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Whether there exists an entry with the given value.
|
|
645
|
+
* @param value - Value to test.
|
|
646
|
+
* @returns `true` if found; otherwise `false`.
|
|
647
|
+
* @remarks Time O(n), Space O(1)
|
|
648
|
+
*/
|
|
649
|
+
hasValue(value) {
|
|
650
|
+
for (const [, elementValue] of this) {
|
|
651
|
+
if (elementValue === value) return true;
|
|
652
|
+
}
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Get the value under a key.
|
|
657
|
+
* @param key - Key to look up.
|
|
658
|
+
* @returns Value or `undefined`.
|
|
659
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
660
|
+
*/
|
|
661
|
+
get(key) {
|
|
662
|
+
for (const item of this) {
|
|
663
|
+
const [itemKey, value] = item;
|
|
664
|
+
if (itemKey === key) return value;
|
|
665
|
+
}
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Reduce entries into a single accumulator.
|
|
670
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
671
|
+
* @param initialValue - Initial accumulator.
|
|
672
|
+
* @returns Final accumulator.
|
|
673
|
+
* @remarks Time O(n), Space O(1)
|
|
674
|
+
*/
|
|
675
|
+
reduce(callbackfn, initialValue) {
|
|
676
|
+
let accumulator = initialValue;
|
|
677
|
+
let index = 0;
|
|
678
|
+
for (const item of this) {
|
|
679
|
+
const [key, value] = item;
|
|
680
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
681
|
+
}
|
|
682
|
+
return accumulator;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Converts data structure to `[key, value]` pairs.
|
|
686
|
+
* @returns Array of entries.
|
|
687
|
+
* @remarks Time O(n), Space O(n)
|
|
688
|
+
*/
|
|
689
|
+
toArray() {
|
|
690
|
+
return [...this];
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
694
|
+
* @returns Array of entries (default) or a string.
|
|
695
|
+
* @remarks Time O(n), Space O(n)
|
|
696
|
+
*/
|
|
697
|
+
toVisual() {
|
|
698
|
+
return [...this];
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Print a human-friendly representation to the console.
|
|
702
|
+
* @remarks Time O(n), Space O(n)
|
|
703
|
+
*/
|
|
704
|
+
print() {
|
|
705
|
+
console.log(this.toVisual());
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
|
|
478
709
|
// src/data-structures/queue/queue.ts
|
|
479
710
|
var Queue = class _Queue extends LinearBase {
|
|
480
711
|
static {
|
|
@@ -532,18 +763,52 @@ var Queue = class _Queue extends LinearBase {
|
|
|
532
763
|
this._autoCompactRatio = value;
|
|
533
764
|
}
|
|
534
765
|
/**
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
766
|
+
* Get the number of elements currently in the queue.
|
|
767
|
+
* @remarks Time O(1), Space O(1)
|
|
768
|
+
* @returns Current length.
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
* @example
|
|
781
|
+
* // Track queue length
|
|
782
|
+
* const q = new Queue<number>();
|
|
783
|
+
* console.log(q.length); // 0;
|
|
784
|
+
* q.push(1);
|
|
785
|
+
* q.push(2);
|
|
786
|
+
* console.log(q.length); // 2;
|
|
787
|
+
*/
|
|
539
788
|
get length() {
|
|
540
789
|
return this.elements.length - this._offset;
|
|
541
790
|
}
|
|
542
791
|
/**
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
792
|
+
* Get the first element (front) without removing it.
|
|
793
|
+
* @remarks Time O(1), Space O(1)
|
|
794
|
+
* @returns Front element or undefined.
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
* @example
|
|
807
|
+
* // View the front element
|
|
808
|
+
* const q = new Queue<string>(['first', 'second', 'third']);
|
|
809
|
+
* console.log(q.first); // 'first';
|
|
810
|
+
* console.log(q.length); // 3;
|
|
811
|
+
*/
|
|
547
812
|
get first() {
|
|
548
813
|
return this.length > 0 ? this.elements[this._offset] : void 0;
|
|
549
814
|
}
|
|
@@ -566,19 +831,69 @@ var Queue = class _Queue extends LinearBase {
|
|
|
566
831
|
return new _Queue(elements);
|
|
567
832
|
}
|
|
568
833
|
/**
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
834
|
+
* Check whether the queue is empty.
|
|
835
|
+
* @remarks Time O(1), Space O(1)
|
|
836
|
+
* @returns True if length is 0.
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
* @example
|
|
849
|
+
* // Queue for...of iteration and isEmpty check
|
|
850
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
851
|
+
*
|
|
852
|
+
* const elements: string[] = [];
|
|
853
|
+
* for (const item of queue) {
|
|
854
|
+
* elements.push(item);
|
|
855
|
+
* }
|
|
856
|
+
*
|
|
857
|
+
* // Verify all elements are iterated in order
|
|
858
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
859
|
+
*
|
|
860
|
+
* // Process all elements
|
|
861
|
+
* while (queue.length > 0) {
|
|
862
|
+
* queue.shift();
|
|
863
|
+
* }
|
|
864
|
+
*
|
|
865
|
+
* console.log(queue.length); // 0;
|
|
866
|
+
*/
|
|
573
867
|
isEmpty() {
|
|
574
868
|
return this.length === 0;
|
|
575
869
|
}
|
|
576
870
|
/**
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
871
|
+
* Enqueue one element at the back.
|
|
872
|
+
* @remarks Time O(1), Space O(1)
|
|
873
|
+
* @param element - Element to enqueue.
|
|
874
|
+
* @returns True on success.
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
* @example
|
|
887
|
+
* // basic Queue creation and push operation
|
|
888
|
+
* // Create a simple Queue with initial values
|
|
889
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
890
|
+
*
|
|
891
|
+
* // Verify the queue maintains insertion order
|
|
892
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
893
|
+
*
|
|
894
|
+
* // Check length
|
|
895
|
+
* console.log(queue.length); // 5;
|
|
896
|
+
*/
|
|
582
897
|
push(element) {
|
|
583
898
|
this.elements.push(element);
|
|
584
899
|
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
@@ -599,10 +914,35 @@ var Queue = class _Queue extends LinearBase {
|
|
|
599
914
|
return ans;
|
|
600
915
|
}
|
|
601
916
|
/**
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
917
|
+
* Dequeue one element from the front (amortized via offset).
|
|
918
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
919
|
+
* @returns Removed element or undefined.
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
* @example
|
|
932
|
+
* // Queue shift and peek operations
|
|
933
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
934
|
+
*
|
|
935
|
+
* // Peek at the front element without removing it
|
|
936
|
+
* console.log(queue.first); // 10;
|
|
937
|
+
*
|
|
938
|
+
* // Remove and get the first element (FIFO)
|
|
939
|
+
* const first = queue.shift();
|
|
940
|
+
* console.log(first); // 10;
|
|
941
|
+
*
|
|
942
|
+
* // Verify remaining elements and length decreased
|
|
943
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
944
|
+
* console.log(queue.length); // 3;
|
|
945
|
+
*/
|
|
606
946
|
shift() {
|
|
607
947
|
if (this.length === 0) return void 0;
|
|
608
948
|
const first = this.first;
|
|
@@ -611,11 +951,24 @@ var Queue = class _Queue extends LinearBase {
|
|
|
611
951
|
return first;
|
|
612
952
|
}
|
|
613
953
|
/**
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
954
|
+
* Delete the first occurrence of a specific element.
|
|
955
|
+
* @remarks Time O(N), Space O(1)
|
|
956
|
+
* @param element - Element to remove (strict equality via Object.is).
|
|
957
|
+
* @returns True if an element was removed.
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
* @example
|
|
967
|
+
* // Remove specific element
|
|
968
|
+
* const q = new Queue<number>([1, 2, 3, 2]);
|
|
969
|
+
* q.delete(2);
|
|
970
|
+
* console.log(q.length); // 3;
|
|
971
|
+
*/
|
|
619
972
|
delete(element) {
|
|
620
973
|
for (let i = this._offset; i < this.elements.length; i++) {
|
|
621
974
|
if (Object.is(this.elements[i], element)) {
|
|
@@ -626,11 +979,24 @@ var Queue = class _Queue extends LinearBase {
|
|
|
626
979
|
return false;
|
|
627
980
|
}
|
|
628
981
|
/**
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
982
|
+
* Get the element at a given logical index.
|
|
983
|
+
* @remarks Time O(1), Space O(1)
|
|
984
|
+
* @param index - Zero-based index from the front.
|
|
985
|
+
* @returns Element or undefined.
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
* @example
|
|
995
|
+
* // Access element by index
|
|
996
|
+
* const q = new Queue<string>(['a', 'b', 'c']);
|
|
997
|
+
* console.log(q.at(0)); // 'a';
|
|
998
|
+
* console.log(q.at(2)); // 'c';
|
|
999
|
+
*/
|
|
634
1000
|
at(index) {
|
|
635
1001
|
if (index < 0 || index >= this.length) return void 0;
|
|
636
1002
|
return this._elements[this._offset + index];
|
|
@@ -682,19 +1048,48 @@ var Queue = class _Queue extends LinearBase {
|
|
|
682
1048
|
return this;
|
|
683
1049
|
}
|
|
684
1050
|
/**
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
1051
|
+
* Remove all elements and reset offset.
|
|
1052
|
+
* @remarks Time O(1), Space O(1)
|
|
1053
|
+
* @returns void
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
* @example
|
|
1064
|
+
* // Remove all elements
|
|
1065
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1066
|
+
* q.clear();
|
|
1067
|
+
* console.log(q.length); // 0;
|
|
1068
|
+
*/
|
|
689
1069
|
clear() {
|
|
690
1070
|
this._elements = [];
|
|
691
1071
|
this._offset = 0;
|
|
692
1072
|
}
|
|
693
1073
|
/**
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
1074
|
+
* Compact storage by discarding consumed head elements.
|
|
1075
|
+
* @remarks Time O(N), Space O(N)
|
|
1076
|
+
* @returns True when compaction performed.
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
|
|
1085
|
+
* @example
|
|
1086
|
+
* // Reclaim unused memory
|
|
1087
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1088
|
+
* q.shift();
|
|
1089
|
+
* q.shift();
|
|
1090
|
+
* q.compact();
|
|
1091
|
+
* console.log(q.length); // 3;
|
|
1092
|
+
*/
|
|
698
1093
|
compact() {
|
|
699
1094
|
this._elements = this.elements.slice(this._offset);
|
|
700
1095
|
this._offset = 0;
|
|
@@ -720,10 +1115,26 @@ var Queue = class _Queue extends LinearBase {
|
|
|
720
1115
|
return removed;
|
|
721
1116
|
}
|
|
722
1117
|
/**
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
1118
|
+
* Deep clone this queue and its parameters.
|
|
1119
|
+
* @remarks Time O(N), Space O(N)
|
|
1120
|
+
* @returns A new queue with the same content and options.
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
* @example
|
|
1131
|
+
* // Create independent copy
|
|
1132
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1133
|
+
* const copy = q.clone();
|
|
1134
|
+
* copy.shift();
|
|
1135
|
+
* console.log(q.length); // 3;
|
|
1136
|
+
* console.log(copy.length); // 2;
|
|
1137
|
+
*/
|
|
727
1138
|
clone() {
|
|
728
1139
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
729
1140
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -731,12 +1142,26 @@ var Queue = class _Queue extends LinearBase {
|
|
|
731
1142
|
return out;
|
|
732
1143
|
}
|
|
733
1144
|
/**
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
1145
|
+
* Filter elements into a new queue of the same class.
|
|
1146
|
+
* @remarks Time O(N), Space O(N)
|
|
1147
|
+
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
1148
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1149
|
+
* @returns A new queue with kept elements.
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
* @example
|
|
1160
|
+
* // Filter elements
|
|
1161
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1162
|
+
* const evens = q.filter(x => x % 2 === 0);
|
|
1163
|
+
* console.log(evens.length); // 2;
|
|
1164
|
+
*/
|
|
740
1165
|
filter(predicate, thisArg) {
|
|
741
1166
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
742
1167
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -748,15 +1173,28 @@ var Queue = class _Queue extends LinearBase {
|
|
|
748
1173
|
return out;
|
|
749
1174
|
}
|
|
750
1175
|
/**
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
1176
|
+
* Map each element to a new element in a possibly different-typed queue.
|
|
1177
|
+
* @remarks Time O(N), Space O(N)
|
|
1178
|
+
* @template EM
|
|
1179
|
+
* @template RM
|
|
1180
|
+
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
1181
|
+
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
1182
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1183
|
+
* @returns A new Queue with mapped elements.
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
* @example
|
|
1193
|
+
* // Transform elements
|
|
1194
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1195
|
+
* const doubled = q.map(x => x * 2);
|
|
1196
|
+
* console.log(doubled.toArray()); // [2, 4, 6];
|
|
1197
|
+
*/
|
|
760
1198
|
map(callback, options, thisArg) {
|
|
761
1199
|
const out = new this.constructor([], {
|
|
762
1200
|
toElementFn: options?.toElementFn,
|
|
@@ -843,212 +1281,6 @@ var Queue = class _Queue extends LinearBase {
|
|
|
843
1281
|
}
|
|
844
1282
|
};
|
|
845
1283
|
|
|
846
|
-
// src/data-structures/base/iterable-entry-base.ts
|
|
847
|
-
var IterableEntryBase = class {
|
|
848
|
-
static {
|
|
849
|
-
__name(this, "IterableEntryBase");
|
|
850
|
-
}
|
|
851
|
-
/**
|
|
852
|
-
* Default iterator yielding `[key, value]` entries.
|
|
853
|
-
* @returns Iterator of `[K, V]`.
|
|
854
|
-
* @remarks Time O(n) to iterate, Space O(1)
|
|
855
|
-
*/
|
|
856
|
-
*[Symbol.iterator](...args) {
|
|
857
|
-
yield* this._getIterator(...args);
|
|
858
|
-
}
|
|
859
|
-
/**
|
|
860
|
-
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
861
|
-
* @returns Iterator of `[K, V | undefined]`.
|
|
862
|
-
* @remarks Time O(n), Space O(1)
|
|
863
|
-
*/
|
|
864
|
-
*entries() {
|
|
865
|
-
for (const item of this) {
|
|
866
|
-
yield item;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
/**
|
|
870
|
-
* Iterate over keys only.
|
|
871
|
-
* @returns Iterator of keys.
|
|
872
|
-
* @remarks Time O(n), Space O(1)
|
|
873
|
-
*/
|
|
874
|
-
*keys() {
|
|
875
|
-
for (const item of this) {
|
|
876
|
-
yield item[0];
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
/**
|
|
880
|
-
* Iterate over values only.
|
|
881
|
-
* @returns Iterator of values.
|
|
882
|
-
* @remarks Time O(n), Space O(1)
|
|
883
|
-
*/
|
|
884
|
-
*values() {
|
|
885
|
-
for (const item of this) {
|
|
886
|
-
yield item[1];
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
/**
|
|
890
|
-
* Test whether all entries satisfy the predicate.
|
|
891
|
-
* @param predicate - `(key, value, index, self) => boolean`.
|
|
892
|
-
* @param thisArg - Optional `this` for callback.
|
|
893
|
-
* @returns `true` if all pass; otherwise `false`.
|
|
894
|
-
* @remarks Time O(n), Space O(1)
|
|
895
|
-
*/
|
|
896
|
-
every(predicate, thisArg) {
|
|
897
|
-
let index = 0;
|
|
898
|
-
for (const item of this) {
|
|
899
|
-
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
900
|
-
return false;
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
return true;
|
|
904
|
-
}
|
|
905
|
-
/**
|
|
906
|
-
* Test whether any entry satisfies the predicate.
|
|
907
|
-
* @param predicate - `(key, value, index, self) => boolean`.
|
|
908
|
-
* @param thisArg - Optional `this` for callback.
|
|
909
|
-
* @returns `true` if any passes; otherwise `false`.
|
|
910
|
-
* @remarks Time O(n), Space O(1)
|
|
911
|
-
*/
|
|
912
|
-
some(predicate, thisArg) {
|
|
913
|
-
let index = 0;
|
|
914
|
-
for (const item of this) {
|
|
915
|
-
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
916
|
-
return true;
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
return false;
|
|
920
|
-
}
|
|
921
|
-
/**
|
|
922
|
-
* Visit each entry, left-to-right.
|
|
923
|
-
* @param callbackfn - `(key, value, index, self) => void`.
|
|
924
|
-
* @param thisArg - Optional `this` for callback.
|
|
925
|
-
* @remarks Time O(n), Space O(1)
|
|
926
|
-
*/
|
|
927
|
-
forEach(callbackfn, thisArg) {
|
|
928
|
-
let index = 0;
|
|
929
|
-
for (const item of this) {
|
|
930
|
-
const [key, value] = item;
|
|
931
|
-
callbackfn.call(thisArg, value, key, index++, this);
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
/**
|
|
935
|
-
* Find the first entry that matches a predicate.
|
|
936
|
-
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
937
|
-
* @param thisArg - Optional `this` for callback.
|
|
938
|
-
* @returns Matching `[key, value]` or `undefined`.
|
|
939
|
-
* @remarks Time O(n), Space O(1)
|
|
940
|
-
*/
|
|
941
|
-
find(callbackfn, thisArg) {
|
|
942
|
-
let index = 0;
|
|
943
|
-
for (const item of this) {
|
|
944
|
-
const [key, value] = item;
|
|
945
|
-
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
946
|
-
}
|
|
947
|
-
return;
|
|
948
|
-
}
|
|
949
|
-
/**
|
|
950
|
-
* Whether the given key exists.
|
|
951
|
-
* @param key - Key to test.
|
|
952
|
-
* @returns `true` if found; otherwise `false`.
|
|
953
|
-
* @remarks Time O(n) generic, Space O(1)
|
|
954
|
-
*/
|
|
955
|
-
has(key) {
|
|
956
|
-
for (const item of this) {
|
|
957
|
-
const [itemKey] = item;
|
|
958
|
-
if (itemKey === key) return true;
|
|
959
|
-
}
|
|
960
|
-
return false;
|
|
961
|
-
}
|
|
962
|
-
/**
|
|
963
|
-
* Whether there exists an entry with the given value.
|
|
964
|
-
* @param value - Value to test.
|
|
965
|
-
* @returns `true` if found; otherwise `false`.
|
|
966
|
-
* @remarks Time O(n), Space O(1)
|
|
967
|
-
*/
|
|
968
|
-
hasValue(value) {
|
|
969
|
-
for (const [, elementValue] of this) {
|
|
970
|
-
if (elementValue === value) return true;
|
|
971
|
-
}
|
|
972
|
-
return false;
|
|
973
|
-
}
|
|
974
|
-
/**
|
|
975
|
-
* Get the value under a key.
|
|
976
|
-
* @param key - Key to look up.
|
|
977
|
-
* @returns Value or `undefined`.
|
|
978
|
-
* @remarks Time O(n) generic, Space O(1)
|
|
979
|
-
*/
|
|
980
|
-
get(key) {
|
|
981
|
-
for (const item of this) {
|
|
982
|
-
const [itemKey, value] = item;
|
|
983
|
-
if (itemKey === key) return value;
|
|
984
|
-
}
|
|
985
|
-
return;
|
|
986
|
-
}
|
|
987
|
-
/**
|
|
988
|
-
* Reduce entries into a single accumulator.
|
|
989
|
-
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
990
|
-
* @param initialValue - Initial accumulator.
|
|
991
|
-
* @returns Final accumulator.
|
|
992
|
-
* @remarks Time O(n), Space O(1)
|
|
993
|
-
*/
|
|
994
|
-
reduce(callbackfn, initialValue) {
|
|
995
|
-
let accumulator = initialValue;
|
|
996
|
-
let index = 0;
|
|
997
|
-
for (const item of this) {
|
|
998
|
-
const [key, value] = item;
|
|
999
|
-
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
1000
|
-
}
|
|
1001
|
-
return accumulator;
|
|
1002
|
-
}
|
|
1003
|
-
/**
|
|
1004
|
-
* Converts data structure to `[key, value]` pairs.
|
|
1005
|
-
* @returns Array of entries.
|
|
1006
|
-
* @remarks Time O(n), Space O(n)
|
|
1007
|
-
*/
|
|
1008
|
-
toArray() {
|
|
1009
|
-
return [...this];
|
|
1010
|
-
}
|
|
1011
|
-
/**
|
|
1012
|
-
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
1013
|
-
* @returns Array of entries (default) or a string.
|
|
1014
|
-
* @remarks Time O(n), Space O(n)
|
|
1015
|
-
*/
|
|
1016
|
-
toVisual() {
|
|
1017
|
-
return [...this];
|
|
1018
|
-
}
|
|
1019
|
-
/**
|
|
1020
|
-
* Print a human-friendly representation to the console.
|
|
1021
|
-
* @remarks Time O(n), Space O(n)
|
|
1022
|
-
*/
|
|
1023
|
-
print() {
|
|
1024
|
-
console.log(this.toVisual());
|
|
1025
|
-
}
|
|
1026
|
-
};
|
|
1027
|
-
|
|
1028
|
-
// src/common/index.ts
|
|
1029
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
1030
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
1031
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
1032
|
-
return DFSOperation2;
|
|
1033
|
-
})(DFSOperation || {});
|
|
1034
|
-
var Range = class {
|
|
1035
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
1036
|
-
this.low = low;
|
|
1037
|
-
this.high = high;
|
|
1038
|
-
this.includeLow = includeLow;
|
|
1039
|
-
this.includeHigh = includeHigh;
|
|
1040
|
-
}
|
|
1041
|
-
static {
|
|
1042
|
-
__name(this, "Range");
|
|
1043
|
-
}
|
|
1044
|
-
// Determine whether a key is within the range
|
|
1045
|
-
isInRange(key, comparator) {
|
|
1046
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
1047
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
1048
|
-
return lowCheck && highCheck;
|
|
1049
|
-
}
|
|
1050
|
-
};
|
|
1051
|
-
|
|
1052
1284
|
// src/data-structures/binary-tree/binary-tree.ts
|
|
1053
1285
|
var BinaryTreeNode = class {
|
|
1054
1286
|
static {
|
|
@@ -1187,7 +1419,7 @@ var BinaryTreeNode = class {
|
|
|
1187
1419
|
return "MAL_NODE";
|
|
1188
1420
|
}
|
|
1189
1421
|
};
|
|
1190
|
-
var BinaryTree = class extends IterableEntryBase {
|
|
1422
|
+
var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
1191
1423
|
static {
|
|
1192
1424
|
__name(this, "BinaryTree");
|
|
1193
1425
|
}
|
|
@@ -1207,7 +1439,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1207
1439
|
if (isMapMode !== void 0) this._isMapMode = isMapMode;
|
|
1208
1440
|
if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
|
|
1209
1441
|
if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
|
|
1210
|
-
else if (toEntryFn) throw TypeError("toEntryFn
|
|
1442
|
+
else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
|
|
1211
1443
|
}
|
|
1212
1444
|
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
1213
1445
|
}
|
|
@@ -1422,30 +1654,78 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1422
1654
|
return isComparable(key);
|
|
1423
1655
|
}
|
|
1424
1656
|
/**
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1657
|
+
* Adds a new node to the tree.
|
|
1658
|
+
* @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).
|
|
1659
|
+
*
|
|
1660
|
+
* @param keyNodeOrEntry - The key, node, or entry to add.
|
|
1661
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
|
|
1668
|
+
* @example
|
|
1669
|
+
* // Add a single node
|
|
1670
|
+
* const tree = new BinaryTree<number>();
|
|
1671
|
+
* tree.add(1);
|
|
1672
|
+
* tree.add(2);
|
|
1673
|
+
* tree.add(3);
|
|
1674
|
+
* console.log(tree.size); // 3;
|
|
1675
|
+
* console.log(tree.has(1)); // true;
|
|
1676
|
+
*/
|
|
1431
1677
|
add(keyNodeOrEntry) {
|
|
1432
1678
|
return this.set(keyNodeOrEntry);
|
|
1433
1679
|
}
|
|
1434
1680
|
/**
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1681
|
+
* Adds or updates a new node to the tree.
|
|
1682
|
+
* @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).
|
|
1683
|
+
*
|
|
1684
|
+
* @param keyNodeOrEntry - The key, node, or entry to set or update.
|
|
1685
|
+
* @param [value] - The value, if providing just a key.
|
|
1686
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1687
|
+
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
* @example
|
|
1699
|
+
* // basic BinaryTree creation and insertion
|
|
1700
|
+
* // Create a BinaryTree with entries
|
|
1701
|
+
* const entries: [number, string][] = [
|
|
1702
|
+
* [6, 'six'],
|
|
1703
|
+
* [1, 'one'],
|
|
1704
|
+
* [2, 'two'],
|
|
1705
|
+
* [7, 'seven'],
|
|
1706
|
+
* [5, 'five'],
|
|
1707
|
+
* [3, 'three'],
|
|
1708
|
+
* [4, 'four'],
|
|
1709
|
+
* [9, 'nine'],
|
|
1710
|
+
* [8, 'eight']
|
|
1711
|
+
* ];
|
|
1712
|
+
*
|
|
1713
|
+
* const tree = new BinaryTree(entries);
|
|
1714
|
+
*
|
|
1715
|
+
* // Verify size
|
|
1716
|
+
* console.log(tree.size); // 9;
|
|
1717
|
+
*
|
|
1718
|
+
* // Add new element
|
|
1719
|
+
* tree.set(10, 'ten');
|
|
1720
|
+
* console.log(tree.size); // 10;
|
|
1721
|
+
*/
|
|
1442
1722
|
set(keyNodeOrEntry, value) {
|
|
1443
1723
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
1444
1724
|
if (newNode === void 0) return false;
|
|
1445
1725
|
if (!this._root) {
|
|
1446
1726
|
this._setRoot(newNode);
|
|
1447
1727
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
1448
|
-
this._size = 1;
|
|
1728
|
+
if (newNode !== null) this._size = 1;
|
|
1449
1729
|
return true;
|
|
1450
1730
|
}
|
|
1451
1731
|
const queue = new Queue([this._root]);
|
|
@@ -1477,29 +1757,50 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1477
1757
|
potentialParent.right = newNode;
|
|
1478
1758
|
}
|
|
1479
1759
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
1480
|
-
this._size++;
|
|
1760
|
+
if (newNode !== null) this._size++;
|
|
1481
1761
|
return true;
|
|
1482
1762
|
}
|
|
1483
1763
|
return false;
|
|
1484
1764
|
}
|
|
1485
1765
|
/**
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1766
|
+
* Adds multiple items to the tree.
|
|
1767
|
+
* @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).
|
|
1768
|
+
*
|
|
1769
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
1770
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1771
|
+
|
|
1772
|
+
|
|
1773
|
+
|
|
1774
|
+
|
|
1775
|
+
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
|
|
1779
|
+
|
|
1780
|
+
* @example
|
|
1781
|
+
* // Bulk add
|
|
1782
|
+
* const tree = new BinaryTree<number>();
|
|
1783
|
+
* tree.addMany([1, 2, 3, 4, 5]);
|
|
1784
|
+
* console.log(tree.size); // 5;
|
|
1785
|
+
*/
|
|
1492
1786
|
addMany(keysNodesEntriesOrRaws) {
|
|
1493
1787
|
return this.setMany(keysNodesEntriesOrRaws);
|
|
1494
1788
|
}
|
|
1495
1789
|
/**
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1790
|
+
* Adds or updates multiple items to the tree.
|
|
1791
|
+
* @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).
|
|
1792
|
+
*
|
|
1793
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set or update.
|
|
1794
|
+
* @param [values] - An optional parallel iterable of values.
|
|
1795
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1796
|
+
|
|
1797
|
+
|
|
1798
|
+
* @example
|
|
1799
|
+
* // Set multiple entries
|
|
1800
|
+
* const tree = new BinaryTree<number, string>();
|
|
1801
|
+
* tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
1802
|
+
* console.log(tree.size); // 3;
|
|
1803
|
+
*/
|
|
1503
1804
|
setMany(keysNodesEntriesOrRaws, values) {
|
|
1504
1805
|
const inserted = [];
|
|
1505
1806
|
let valuesIterator;
|
|
@@ -1520,11 +1821,26 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1520
1821
|
return inserted;
|
|
1521
1822
|
}
|
|
1522
1823
|
/**
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1824
|
+
* Merges another tree into this one by seting all its nodes.
|
|
1825
|
+
* @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`).
|
|
1826
|
+
*
|
|
1827
|
+
* @param anotherTree - The tree to merge.
|
|
1828
|
+
|
|
1829
|
+
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
|
|
1833
|
+
|
|
1834
|
+
|
|
1835
|
+
|
|
1836
|
+
|
|
1837
|
+
* @example
|
|
1838
|
+
* // Combine trees
|
|
1839
|
+
* const t1 = new BinaryTree<number>([1, 2]);
|
|
1840
|
+
* const t2 = new BinaryTree<number>([3, 4]);
|
|
1841
|
+
* t1.merge(t2);
|
|
1842
|
+
* console.log(t1.size); // 4;
|
|
1843
|
+
*/
|
|
1528
1844
|
merge(anotherTree) {
|
|
1529
1845
|
this.setMany(anotherTree, []);
|
|
1530
1846
|
}
|
|
@@ -1540,12 +1856,29 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1540
1856
|
this.setMany(keysNodesEntriesOrRaws, values);
|
|
1541
1857
|
}
|
|
1542
1858
|
/**
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1859
|
+
* Deletes a node from the tree.
|
|
1860
|
+
* @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).
|
|
1861
|
+
*
|
|
1862
|
+
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
1863
|
+
* @returns An array containing deletion results (for compatibility with self-balancing trees).
|
|
1864
|
+
|
|
1865
|
+
|
|
1866
|
+
|
|
1867
|
+
|
|
1868
|
+
|
|
1869
|
+
|
|
1870
|
+
|
|
1871
|
+
|
|
1872
|
+
|
|
1873
|
+
|
|
1874
|
+
|
|
1875
|
+
* @example
|
|
1876
|
+
* // Remove a node
|
|
1877
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
1878
|
+
* tree.delete(3);
|
|
1879
|
+
* console.log(tree.has(3)); // false;
|
|
1880
|
+
* console.log(tree.size); // 4;
|
|
1881
|
+
*/
|
|
1549
1882
|
delete(keyNodeEntryRawOrPredicate) {
|
|
1550
1883
|
const deletedResult = [];
|
|
1551
1884
|
if (!this._root) return deletedResult;
|
|
@@ -1639,14 +1972,27 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1639
1972
|
return this.search(keyNodeEntryOrPredicate, onlyOne, (node) => node, startNode, iterationType);
|
|
1640
1973
|
}
|
|
1641
1974
|
/**
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1975
|
+
* Gets the first node matching a predicate.
|
|
1976
|
+
* @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`).
|
|
1977
|
+
*
|
|
1978
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
1979
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
1980
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1981
|
+
* @returns The first matching node, or undefined if not found.
|
|
1982
|
+
|
|
1983
|
+
|
|
1984
|
+
|
|
1985
|
+
|
|
1986
|
+
|
|
1987
|
+
|
|
1988
|
+
|
|
1989
|
+
|
|
1990
|
+
|
|
1991
|
+
* @example
|
|
1992
|
+
* // Get node by key
|
|
1993
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
|
|
1994
|
+
* console.log(tree.getNode(2)?.value); // 'child';
|
|
1995
|
+
*/
|
|
1650
1996
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1651
1997
|
if (this._isMapMode && keyNodeEntryOrPredicate !== null && keyNodeEntryOrPredicate !== void 0) {
|
|
1652
1998
|
if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
@@ -1658,14 +2004,30 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1658
2004
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType)[0];
|
|
1659
2005
|
}
|
|
1660
2006
|
/**
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
2007
|
+
* Gets the value associated with a key.
|
|
2008
|
+
* @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.
|
|
2009
|
+
*
|
|
2010
|
+
* @param keyNodeEntryOrPredicate - The key, node, or entry to get the value for.
|
|
2011
|
+
* @param [startNode=this._root] - The node to start searching from (if not in Map mode).
|
|
2012
|
+
* @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
|
|
2013
|
+
* @returns The associated value, or undefined.
|
|
2014
|
+
|
|
2015
|
+
|
|
2016
|
+
|
|
2017
|
+
|
|
2018
|
+
|
|
2019
|
+
|
|
2020
|
+
|
|
2021
|
+
|
|
2022
|
+
|
|
2023
|
+
|
|
2024
|
+
|
|
2025
|
+
* @example
|
|
2026
|
+
* // Retrieve value by key
|
|
2027
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
|
|
2028
|
+
* console.log(tree.get(2)); // 'left';
|
|
2029
|
+
* console.log(tree.get(99)); // undefined;
|
|
2030
|
+
*/
|
|
1669
2031
|
get(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1670
2032
|
if (this._isMapMode) {
|
|
1671
2033
|
const key = this._extractKey(keyNodeEntryOrPredicate);
|
|
@@ -1685,19 +2047,45 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1685
2047
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType).length > 0;
|
|
1686
2048
|
}
|
|
1687
2049
|
/**
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
2050
|
+
* Clears the tree of all nodes and values.
|
|
2051
|
+
* @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
|
|
2052
|
+
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
|
|
2056
|
+
|
|
2057
|
+
|
|
2058
|
+
|
|
2059
|
+
|
|
2060
|
+
|
|
2061
|
+
* @example
|
|
2062
|
+
* // Remove all nodes
|
|
2063
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2064
|
+
* tree.clear();
|
|
2065
|
+
* console.log(tree.isEmpty()); // true;
|
|
2066
|
+
*/
|
|
1691
2067
|
clear() {
|
|
1692
2068
|
this._clearNodes();
|
|
1693
2069
|
if (this._isMapMode) this._clearValues();
|
|
1694
2070
|
}
|
|
1695
2071
|
/**
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
2072
|
+
* Checks if the tree is empty.
|
|
2073
|
+
* @remarks Time O(1), Space O(1)
|
|
2074
|
+
*
|
|
2075
|
+
* @returns True if the tree has no nodes, false otherwise.
|
|
2076
|
+
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
* @example
|
|
2086
|
+
* // Check empty
|
|
2087
|
+
* console.log(new BinaryTree().isEmpty()); // true;
|
|
2088
|
+
*/
|
|
1701
2089
|
isEmpty() {
|
|
1702
2090
|
return this._size === 0;
|
|
1703
2091
|
}
|
|
@@ -1712,13 +2100,27 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1712
2100
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
1713
2101
|
}
|
|
1714
2102
|
/**
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
2103
|
+
* Checks if the tree is a valid Binary Search Tree (BST).
|
|
2104
|
+
* @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).
|
|
2105
|
+
*
|
|
2106
|
+
* @param [startNode=this._root] - The node to start checking from.
|
|
2107
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2108
|
+
* @returns True if it's a valid BST, false otherwise.
|
|
2109
|
+
|
|
2110
|
+
|
|
2111
|
+
|
|
2112
|
+
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
|
|
2116
|
+
|
|
2117
|
+
|
|
2118
|
+
* @example
|
|
2119
|
+
* // Check BST property
|
|
2120
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2121
|
+
* // BinaryTree doesn't guarantee BST order
|
|
2122
|
+
* console.log(typeof tree.isBST()); // 'boolean';
|
|
2123
|
+
*/
|
|
1722
2124
|
isBST(startNode = this._root, iterationType = this.iterationType) {
|
|
1723
2125
|
const startNodeSired = this.ensureNode(startNode);
|
|
1724
2126
|
if (!startNodeSired) return true;
|
|
@@ -1756,13 +2158,29 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1756
2158
|
}
|
|
1757
2159
|
}
|
|
1758
2160
|
/**
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
2161
|
+
* Gets the depth of a node (distance from `startNode`).
|
|
2162
|
+
* @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
|
|
2163
|
+
*
|
|
2164
|
+
* @param dist - The node to find the depth of.
|
|
2165
|
+
* @param [startNode=this._root] - The node to measure depth from (defaults to root).
|
|
2166
|
+
* @returns The depth (0 if `dist` is `startNode`).
|
|
2167
|
+
|
|
2168
|
+
|
|
2169
|
+
|
|
2170
|
+
|
|
2171
|
+
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
|
|
2177
|
+
|
|
2178
|
+
* @example
|
|
2179
|
+
* // Get depth of a node
|
|
2180
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2181
|
+
* const node = tree.getNode(4);
|
|
2182
|
+
* console.log(tree.getDepth(node!)); // 2;
|
|
2183
|
+
*/
|
|
1766
2184
|
getDepth(dist, startNode = this._root) {
|
|
1767
2185
|
let distEnsured = this.ensureNode(dist);
|
|
1768
2186
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
@@ -1777,13 +2195,28 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1777
2195
|
return depth;
|
|
1778
2196
|
}
|
|
1779
2197
|
/**
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
2198
|
+
* Gets the maximum height of the tree (longest path from startNode to a leaf).
|
|
2199
|
+
* @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).
|
|
2200
|
+
*
|
|
2201
|
+
* @param [startNode=this._root] - The node to start measuring from.
|
|
2202
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2203
|
+
* @returns The height ( -1 for an empty tree, 0 for a single-node tree).
|
|
2204
|
+
|
|
2205
|
+
|
|
2206
|
+
|
|
2207
|
+
|
|
2208
|
+
|
|
2209
|
+
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
|
|
2213
|
+
|
|
2214
|
+
|
|
2215
|
+
* @example
|
|
2216
|
+
* // Get tree height
|
|
2217
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2218
|
+
* console.log(tree.getHeight()); // 2;
|
|
2219
|
+
*/
|
|
1787
2220
|
getHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
1788
2221
|
startNode = this.ensureNode(startNode);
|
|
1789
2222
|
if (!this.isRealNode(startNode)) return -1;
|
|
@@ -2045,7 +2478,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2045
2478
|
}
|
|
2046
2479
|
/**
|
|
2047
2480
|
* Finds all leaf nodes in the tree.
|
|
2048
|
-
* @remarks Time O(N), visits every node. Space O(H) for recursive
|
|
2481
|
+
* @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
|
|
2049
2482
|
*
|
|
2050
2483
|
* @template C - The type of the callback function.
|
|
2051
2484
|
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
|
|
@@ -2068,15 +2501,15 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2068
2501
|
}, "dfs");
|
|
2069
2502
|
dfs(startNode);
|
|
2070
2503
|
} else {
|
|
2071
|
-
const
|
|
2072
|
-
while (
|
|
2073
|
-
const cur =
|
|
2504
|
+
const stack = [startNode];
|
|
2505
|
+
while (stack.length > 0) {
|
|
2506
|
+
const cur = stack.pop();
|
|
2074
2507
|
if (this.isRealNode(cur)) {
|
|
2075
2508
|
if (this.isLeaf(cur)) {
|
|
2076
2509
|
leaves.push(callback(cur));
|
|
2077
2510
|
}
|
|
2078
|
-
if (this.isRealNode(cur.
|
|
2079
|
-
if (this.isRealNode(cur.
|
|
2511
|
+
if (this.isRealNode(cur.right)) stack.push(cur.right);
|
|
2512
|
+
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
|
2080
2513
|
}
|
|
2081
2514
|
}
|
|
2082
2515
|
}
|
|
@@ -2219,24 +2652,53 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2219
2652
|
return ans;
|
|
2220
2653
|
}
|
|
2221
2654
|
/**
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2655
|
+
* Clones the tree.
|
|
2656
|
+
* @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.
|
|
2657
|
+
*
|
|
2658
|
+
* @returns A new, cloned instance of the tree.
|
|
2659
|
+
|
|
2660
|
+
|
|
2661
|
+
|
|
2662
|
+
|
|
2663
|
+
|
|
2664
|
+
|
|
2665
|
+
|
|
2666
|
+
|
|
2667
|
+
|
|
2668
|
+
* @example
|
|
2669
|
+
* // Deep copy
|
|
2670
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2671
|
+
* const copy = tree.clone();
|
|
2672
|
+
* copy.delete(1);
|
|
2673
|
+
* console.log(tree.has(1)); // true;
|
|
2674
|
+
*/
|
|
2227
2675
|
clone() {
|
|
2228
2676
|
const out = this._createInstance();
|
|
2229
2677
|
this._clone(out);
|
|
2230
2678
|
return out;
|
|
2231
2679
|
}
|
|
2232
2680
|
/**
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2681
|
+
* Creates a new tree containing only the entries that satisfy the predicate.
|
|
2682
|
+
* @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.
|
|
2683
|
+
*
|
|
2684
|
+
* @param predicate - A function to test each [key, value] pair.
|
|
2685
|
+
* @param [thisArg] - `this` context for the predicate.
|
|
2686
|
+
* @returns A new, filtered tree.
|
|
2687
|
+
|
|
2688
|
+
|
|
2689
|
+
|
|
2690
|
+
|
|
2691
|
+
|
|
2692
|
+
|
|
2693
|
+
|
|
2694
|
+
|
|
2695
|
+
|
|
2696
|
+
* @example
|
|
2697
|
+
* // Filter nodes by condition
|
|
2698
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4]);
|
|
2699
|
+
* const result = tree.filter((_, key) => key > 2);
|
|
2700
|
+
* console.log(result.size); // 2;
|
|
2701
|
+
*/
|
|
2240
2702
|
filter(predicate, thisArg) {
|
|
2241
2703
|
const out = this._createInstance();
|
|
2242
2704
|
let i = 0;
|
|
@@ -2244,17 +2706,31 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2244
2706
|
return out;
|
|
2245
2707
|
}
|
|
2246
2708
|
/**
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2709
|
+
* Creates a new tree by mapping each [key, value] pair to a new entry.
|
|
2710
|
+
* @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.
|
|
2711
|
+
*
|
|
2712
|
+
* @template MK - New key type.
|
|
2713
|
+
* @template MV - New value type.
|
|
2714
|
+
* @template MR - New raw type.
|
|
2715
|
+
* @param cb - A function to map each [key, value] pair.
|
|
2716
|
+
* @param [options] - Options for the new tree.
|
|
2717
|
+
* @param [thisArg] - `this` context for the callback.
|
|
2718
|
+
* @returns A new, mapped tree.
|
|
2719
|
+
|
|
2720
|
+
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
|
|
2728
|
+
* @example
|
|
2729
|
+
* // Transform to new tree
|
|
2730
|
+
* const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
|
|
2731
|
+
* const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
|
|
2732
|
+
* console.log([...mapped.values()]); // contains 11;
|
|
2733
|
+
*/
|
|
2258
2734
|
map(cb, options, thisArg) {
|
|
2259
2735
|
const out = this._createLike([], options);
|
|
2260
2736
|
let i = 0;
|
|
@@ -2292,12 +2768,25 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2292
2768
|
return output;
|
|
2293
2769
|
}
|
|
2294
2770
|
/**
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2771
|
+
* Prints a visual representation of the tree to the console.
|
|
2772
|
+
* @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
|
|
2773
|
+
*
|
|
2774
|
+
* @param [options] - Options to control the output.
|
|
2775
|
+
* @param [startNode=this._root] - The node to start printing from.
|
|
2776
|
+
|
|
2777
|
+
|
|
2778
|
+
|
|
2779
|
+
|
|
2780
|
+
|
|
2781
|
+
|
|
2782
|
+
|
|
2783
|
+
|
|
2784
|
+
|
|
2785
|
+
* @example
|
|
2786
|
+
* // Display tree
|
|
2787
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2788
|
+
* expect(() => tree.print()).not.toThrow();
|
|
2789
|
+
*/
|
|
2301
2790
|
print(options, startNode = this._root) {
|
|
2302
2791
|
console.log(this.toVisual(startNode, options));
|
|
2303
2792
|
}
|
|
@@ -2536,44 +3025,99 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2536
3025
|
* @returns Layout information for this subtree.
|
|
2537
3026
|
*/
|
|
2538
3027
|
_displayAux(node, options) {
|
|
2539
|
-
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
2540
3028
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
const
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
3029
|
+
const newFrame = /* @__PURE__ */ __name((n) => ({
|
|
3030
|
+
node: n,
|
|
3031
|
+
stage: 0,
|
|
3032
|
+
leftLayout: emptyDisplayLayout,
|
|
3033
|
+
rightLayout: emptyDisplayLayout
|
|
3034
|
+
}), "newFrame");
|
|
3035
|
+
const stack = [newFrame(node)];
|
|
3036
|
+
let result = emptyDisplayLayout;
|
|
3037
|
+
const setChildResult = /* @__PURE__ */ __name((layout) => {
|
|
3038
|
+
if (stack.length === 0) {
|
|
3039
|
+
result = layout;
|
|
3040
|
+
return;
|
|
3041
|
+
}
|
|
3042
|
+
const parent = stack[stack.length - 1];
|
|
3043
|
+
if (parent.stage === 1) parent.leftLayout = layout;
|
|
3044
|
+
else parent.rightLayout = layout;
|
|
3045
|
+
}, "setChildResult");
|
|
3046
|
+
while (stack.length > 0) {
|
|
3047
|
+
const frame = stack[stack.length - 1];
|
|
3048
|
+
const cur = frame.node;
|
|
3049
|
+
if (frame.stage === 0) {
|
|
3050
|
+
if (this._isDisplayLeaf(cur, options)) {
|
|
3051
|
+
stack.pop();
|
|
3052
|
+
const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
|
|
3053
|
+
setChildResult(layout);
|
|
3054
|
+
continue;
|
|
3055
|
+
}
|
|
3056
|
+
frame.stage = 1;
|
|
3057
|
+
stack.push(newFrame(cur.left));
|
|
3058
|
+
} else if (frame.stage === 1) {
|
|
3059
|
+
frame.stage = 2;
|
|
3060
|
+
stack.push(newFrame(cur.right));
|
|
3061
|
+
} else {
|
|
3062
|
+
stack.pop();
|
|
3063
|
+
const line = this.isNIL(cur) ? "S" : String(cur.key);
|
|
3064
|
+
const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
|
|
3065
|
+
setChildResult(layout);
|
|
2569
3066
|
}
|
|
2570
|
-
return [
|
|
2571
|
-
mergedLines,
|
|
2572
|
-
leftWidth + width + rightWidth,
|
|
2573
|
-
Math.max(leftHeight, rightHeight) + 2,
|
|
2574
|
-
leftWidth + Math.floor(width / 2)
|
|
2575
|
-
];
|
|
2576
3067
|
}
|
|
3068
|
+
return result;
|
|
3069
|
+
}
|
|
3070
|
+
static _buildNodeDisplay(line, width, left, right) {
|
|
3071
|
+
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
3072
|
+
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
3073
|
+
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));
|
|
3074
|
+
const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
|
|
3075
|
+
const mergedLines = [firstLine, secondLine];
|
|
3076
|
+
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
3077
|
+
const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
|
|
3078
|
+
const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
|
|
3079
|
+
mergedLines.push(leftLine + " ".repeat(width) + rightLine);
|
|
3080
|
+
}
|
|
3081
|
+
return [
|
|
3082
|
+
mergedLines,
|
|
3083
|
+
leftWidth + width + rightWidth,
|
|
3084
|
+
Math.max(leftHeight, rightHeight) + 2,
|
|
3085
|
+
leftWidth + Math.floor(width / 2)
|
|
3086
|
+
];
|
|
3087
|
+
}
|
|
3088
|
+
/**
|
|
3089
|
+
* Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
|
|
3090
|
+
*/
|
|
3091
|
+
_isDisplayLeaf(node, options) {
|
|
3092
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3093
|
+
if (node === null && !isShowNull) return true;
|
|
3094
|
+
if (node === void 0 && !isShowUndefined) return true;
|
|
3095
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return true;
|
|
3096
|
+
if (node === null || node === void 0) return true;
|
|
3097
|
+
const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
|
|
3098
|
+
const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
|
|
3099
|
+
return !hasDisplayableLeft && !hasDisplayableRight;
|
|
3100
|
+
}
|
|
3101
|
+
_hasDisplayableChild(child, options) {
|
|
3102
|
+
if (child === null) return !!options.isShowNull;
|
|
3103
|
+
if (child === void 0) return !!options.isShowUndefined;
|
|
3104
|
+
if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
|
|
3105
|
+
return true;
|
|
3106
|
+
}
|
|
3107
|
+
/**
|
|
3108
|
+
* Resolve a display leaf node to its layout.
|
|
3109
|
+
*/
|
|
3110
|
+
_resolveDisplayLeaf(node, options, emptyDisplayLayout) {
|
|
3111
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3112
|
+
if (node === null && !isShowNull) return emptyDisplayLayout;
|
|
3113
|
+
if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
|
|
3114
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
|
|
3115
|
+
if (node !== null && node !== void 0) {
|
|
3116
|
+
const line2 = this.isNIL(node) ? "S" : String(node.key);
|
|
3117
|
+
return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
|
|
3118
|
+
}
|
|
3119
|
+
const line = node === void 0 ? "U" : "N";
|
|
3120
|
+
return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
|
|
2577
3121
|
}
|
|
2578
3122
|
/**
|
|
2579
3123
|
* (Protected) Swaps the key/value properties of two nodes.
|
|
@@ -2720,6 +3264,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2720
3264
|
exports.BinaryTree = BinaryTree;
|
|
2721
3265
|
exports.BinaryTreeNode = BinaryTreeNode;
|
|
2722
3266
|
exports.DFSOperation = DFSOperation;
|
|
3267
|
+
exports.ERR = ERR;
|
|
2723
3268
|
exports.Range = Range;
|
|
2724
3269
|
//# sourceMappingURL=index.cjs.map
|
|
2725
3270
|
//# sourceMappingURL=index.cjs.map
|