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