avl-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/dist/cjs/index.cjs +1381 -577
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +1333 -529
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1381 -577
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +1333 -529
- 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/avl-tree-typed.js +1331 -527
- package/dist/umd/avl-tree-typed.js.map +1 -1
- package/dist/umd/avl-tree-typed.min.js +3 -3
- package/dist/umd/avl-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,230 @@ 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 _Range = class _Range {
|
|
505
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
506
|
+
this.low = low;
|
|
507
|
+
this.high = high;
|
|
508
|
+
this.includeLow = includeLow;
|
|
509
|
+
this.includeHigh = includeHigh;
|
|
510
|
+
}
|
|
511
|
+
// Determine whether a key is within the range
|
|
512
|
+
isInRange(key, comparator) {
|
|
513
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
514
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
515
|
+
return lowCheck && highCheck;
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
__name(_Range, "Range");
|
|
519
|
+
var Range = _Range;
|
|
520
|
+
|
|
521
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
522
|
+
var _IterableEntryBase = class _IterableEntryBase {
|
|
523
|
+
/**
|
|
524
|
+
* Default iterator yielding `[key, value]` entries.
|
|
525
|
+
* @returns Iterator of `[K, V]`.
|
|
526
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
527
|
+
*/
|
|
528
|
+
*[Symbol.iterator](...args) {
|
|
529
|
+
yield* this._getIterator(...args);
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
533
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
534
|
+
* @remarks Time O(n), Space O(1)
|
|
535
|
+
*/
|
|
536
|
+
*entries() {
|
|
537
|
+
for (const item of this) {
|
|
538
|
+
yield item;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Iterate over keys only.
|
|
543
|
+
* @returns Iterator of keys.
|
|
544
|
+
* @remarks Time O(n), Space O(1)
|
|
545
|
+
*/
|
|
546
|
+
*keys() {
|
|
547
|
+
for (const item of this) {
|
|
548
|
+
yield item[0];
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Iterate over values only.
|
|
553
|
+
* @returns Iterator of values.
|
|
554
|
+
* @remarks Time O(n), Space O(1)
|
|
555
|
+
*/
|
|
556
|
+
*values() {
|
|
557
|
+
for (const item of this) {
|
|
558
|
+
yield item[1];
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Test whether all entries satisfy the predicate.
|
|
563
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
564
|
+
* @param thisArg - Optional `this` for callback.
|
|
565
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
566
|
+
* @remarks Time O(n), Space O(1)
|
|
567
|
+
*/
|
|
568
|
+
every(predicate, thisArg) {
|
|
569
|
+
let index = 0;
|
|
570
|
+
for (const item of this) {
|
|
571
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Test whether any entry satisfies the predicate.
|
|
579
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
580
|
+
* @param thisArg - Optional `this` for callback.
|
|
581
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
582
|
+
* @remarks Time O(n), Space O(1)
|
|
583
|
+
*/
|
|
584
|
+
some(predicate, thisArg) {
|
|
585
|
+
let index = 0;
|
|
586
|
+
for (const item of this) {
|
|
587
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return false;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Visit each entry, left-to-right.
|
|
595
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
596
|
+
* @param thisArg - Optional `this` for callback.
|
|
597
|
+
* @remarks Time O(n), Space O(1)
|
|
598
|
+
*/
|
|
599
|
+
forEach(callbackfn, thisArg) {
|
|
600
|
+
let index = 0;
|
|
601
|
+
for (const item of this) {
|
|
602
|
+
const [key, value] = item;
|
|
603
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Find the first entry that matches a predicate.
|
|
608
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
609
|
+
* @param thisArg - Optional `this` for callback.
|
|
610
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
611
|
+
* @remarks Time O(n), Space O(1)
|
|
612
|
+
*/
|
|
613
|
+
find(callbackfn, thisArg) {
|
|
614
|
+
let index = 0;
|
|
615
|
+
for (const item of this) {
|
|
616
|
+
const [key, value] = item;
|
|
617
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
618
|
+
}
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Whether the given key exists.
|
|
623
|
+
* @param key - Key to test.
|
|
624
|
+
* @returns `true` if found; otherwise `false`.
|
|
625
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
626
|
+
*/
|
|
627
|
+
has(key) {
|
|
628
|
+
for (const item of this) {
|
|
629
|
+
const [itemKey] = item;
|
|
630
|
+
if (itemKey === key) return true;
|
|
631
|
+
}
|
|
632
|
+
return false;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Whether there exists an entry with the given value.
|
|
636
|
+
* @param value - Value to test.
|
|
637
|
+
* @returns `true` if found; otherwise `false`.
|
|
638
|
+
* @remarks Time O(n), Space O(1)
|
|
639
|
+
*/
|
|
640
|
+
hasValue(value) {
|
|
641
|
+
for (const [, elementValue] of this) {
|
|
642
|
+
if (elementValue === value) return true;
|
|
643
|
+
}
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Get the value under a key.
|
|
648
|
+
* @param key - Key to look up.
|
|
649
|
+
* @returns Value or `undefined`.
|
|
650
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
651
|
+
*/
|
|
652
|
+
get(key) {
|
|
653
|
+
for (const item of this) {
|
|
654
|
+
const [itemKey, value] = item;
|
|
655
|
+
if (itemKey === key) return value;
|
|
656
|
+
}
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Reduce entries into a single accumulator.
|
|
661
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
662
|
+
* @param initialValue - Initial accumulator.
|
|
663
|
+
* @returns Final accumulator.
|
|
664
|
+
* @remarks Time O(n), Space O(1)
|
|
665
|
+
*/
|
|
666
|
+
reduce(callbackfn, initialValue) {
|
|
667
|
+
let accumulator = initialValue;
|
|
668
|
+
let index = 0;
|
|
669
|
+
for (const item of this) {
|
|
670
|
+
const [key, value] = item;
|
|
671
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
672
|
+
}
|
|
673
|
+
return accumulator;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Converts data structure to `[key, value]` pairs.
|
|
677
|
+
* @returns Array of entries.
|
|
678
|
+
* @remarks Time O(n), Space O(n)
|
|
679
|
+
*/
|
|
680
|
+
toArray() {
|
|
681
|
+
return [...this];
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
685
|
+
* @returns Array of entries (default) or a string.
|
|
686
|
+
* @remarks Time O(n), Space O(n)
|
|
687
|
+
*/
|
|
688
|
+
toVisual() {
|
|
689
|
+
return [...this];
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Print a human-friendly representation to the console.
|
|
693
|
+
* @remarks Time O(n), Space O(n)
|
|
694
|
+
*/
|
|
695
|
+
print() {
|
|
696
|
+
console.log(this.toVisual());
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
__name(_IterableEntryBase, "IterableEntryBase");
|
|
700
|
+
var IterableEntryBase = _IterableEntryBase;
|
|
701
|
+
|
|
478
702
|
// src/data-structures/queue/queue.ts
|
|
479
703
|
var _Queue = class _Queue extends LinearBase {
|
|
480
704
|
/**
|
|
@@ -529,18 +753,52 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
529
753
|
this._autoCompactRatio = value;
|
|
530
754
|
}
|
|
531
755
|
/**
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
756
|
+
* Get the number of elements currently in the queue.
|
|
757
|
+
* @remarks Time O(1), Space O(1)
|
|
758
|
+
* @returns Current length.
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
* @example
|
|
771
|
+
* // Track queue length
|
|
772
|
+
* const q = new Queue<number>();
|
|
773
|
+
* console.log(q.length); // 0;
|
|
774
|
+
* q.push(1);
|
|
775
|
+
* q.push(2);
|
|
776
|
+
* console.log(q.length); // 2;
|
|
777
|
+
*/
|
|
536
778
|
get length() {
|
|
537
779
|
return this.elements.length - this._offset;
|
|
538
780
|
}
|
|
539
781
|
/**
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
782
|
+
* Get the first element (front) without removing it.
|
|
783
|
+
* @remarks Time O(1), Space O(1)
|
|
784
|
+
* @returns Front element or undefined.
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
* @example
|
|
797
|
+
* // View the front element
|
|
798
|
+
* const q = new Queue<string>(['first', 'second', 'third']);
|
|
799
|
+
* console.log(q.first); // 'first';
|
|
800
|
+
* console.log(q.length); // 3;
|
|
801
|
+
*/
|
|
544
802
|
get first() {
|
|
545
803
|
return this.length > 0 ? this.elements[this._offset] : void 0;
|
|
546
804
|
}
|
|
@@ -563,19 +821,69 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
563
821
|
return new _Queue(elements);
|
|
564
822
|
}
|
|
565
823
|
/**
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
824
|
+
* Check whether the queue is empty.
|
|
825
|
+
* @remarks Time O(1), Space O(1)
|
|
826
|
+
* @returns True if length is 0.
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
* @example
|
|
839
|
+
* // Queue for...of iteration and isEmpty check
|
|
840
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
841
|
+
*
|
|
842
|
+
* const elements: string[] = [];
|
|
843
|
+
* for (const item of queue) {
|
|
844
|
+
* elements.push(item);
|
|
845
|
+
* }
|
|
846
|
+
*
|
|
847
|
+
* // Verify all elements are iterated in order
|
|
848
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
849
|
+
*
|
|
850
|
+
* // Process all elements
|
|
851
|
+
* while (queue.length > 0) {
|
|
852
|
+
* queue.shift();
|
|
853
|
+
* }
|
|
854
|
+
*
|
|
855
|
+
* console.log(queue.length); // 0;
|
|
856
|
+
*/
|
|
570
857
|
isEmpty() {
|
|
571
858
|
return this.length === 0;
|
|
572
859
|
}
|
|
573
860
|
/**
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
861
|
+
* Enqueue one element at the back.
|
|
862
|
+
* @remarks Time O(1), Space O(1)
|
|
863
|
+
* @param element - Element to enqueue.
|
|
864
|
+
* @returns True on success.
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
* @example
|
|
877
|
+
* // basic Queue creation and push operation
|
|
878
|
+
* // Create a simple Queue with initial values
|
|
879
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
880
|
+
*
|
|
881
|
+
* // Verify the queue maintains insertion order
|
|
882
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
883
|
+
*
|
|
884
|
+
* // Check length
|
|
885
|
+
* console.log(queue.length); // 5;
|
|
886
|
+
*/
|
|
579
887
|
push(element) {
|
|
580
888
|
this.elements.push(element);
|
|
581
889
|
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
@@ -596,10 +904,35 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
596
904
|
return ans;
|
|
597
905
|
}
|
|
598
906
|
/**
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
907
|
+
* Dequeue one element from the front (amortized via offset).
|
|
908
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
909
|
+
* @returns Removed element or undefined.
|
|
910
|
+
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
* @example
|
|
922
|
+
* // Queue shift and peek operations
|
|
923
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
924
|
+
*
|
|
925
|
+
* // Peek at the front element without removing it
|
|
926
|
+
* console.log(queue.first); // 10;
|
|
927
|
+
*
|
|
928
|
+
* // Remove and get the first element (FIFO)
|
|
929
|
+
* const first = queue.shift();
|
|
930
|
+
* console.log(first); // 10;
|
|
931
|
+
*
|
|
932
|
+
* // Verify remaining elements and length decreased
|
|
933
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
934
|
+
* console.log(queue.length); // 3;
|
|
935
|
+
*/
|
|
603
936
|
shift() {
|
|
604
937
|
if (this.length === 0) return void 0;
|
|
605
938
|
const first = this.first;
|
|
@@ -608,11 +941,24 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
608
941
|
return first;
|
|
609
942
|
}
|
|
610
943
|
/**
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
944
|
+
* Delete the first occurrence of a specific element.
|
|
945
|
+
* @remarks Time O(N), Space O(1)
|
|
946
|
+
* @param element - Element to remove (strict equality via Object.is).
|
|
947
|
+
* @returns True if an element was removed.
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
* @example
|
|
957
|
+
* // Remove specific element
|
|
958
|
+
* const q = new Queue<number>([1, 2, 3, 2]);
|
|
959
|
+
* q.delete(2);
|
|
960
|
+
* console.log(q.length); // 3;
|
|
961
|
+
*/
|
|
616
962
|
delete(element) {
|
|
617
963
|
for (let i = this._offset; i < this.elements.length; i++) {
|
|
618
964
|
if (Object.is(this.elements[i], element)) {
|
|
@@ -623,11 +969,24 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
623
969
|
return false;
|
|
624
970
|
}
|
|
625
971
|
/**
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
972
|
+
* Get the element at a given logical index.
|
|
973
|
+
* @remarks Time O(1), Space O(1)
|
|
974
|
+
* @param index - Zero-based index from the front.
|
|
975
|
+
* @returns Element or undefined.
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
* @example
|
|
985
|
+
* // Access element by index
|
|
986
|
+
* const q = new Queue<string>(['a', 'b', 'c']);
|
|
987
|
+
* console.log(q.at(0)); // 'a';
|
|
988
|
+
* console.log(q.at(2)); // 'c';
|
|
989
|
+
*/
|
|
631
990
|
at(index) {
|
|
632
991
|
if (index < 0 || index >= this.length) return void 0;
|
|
633
992
|
return this._elements[this._offset + index];
|
|
@@ -679,19 +1038,48 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
679
1038
|
return this;
|
|
680
1039
|
}
|
|
681
1040
|
/**
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
1041
|
+
* Remove all elements and reset offset.
|
|
1042
|
+
* @remarks Time O(1), Space O(1)
|
|
1043
|
+
* @returns void
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
* @example
|
|
1054
|
+
* // Remove all elements
|
|
1055
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1056
|
+
* q.clear();
|
|
1057
|
+
* console.log(q.length); // 0;
|
|
1058
|
+
*/
|
|
686
1059
|
clear() {
|
|
687
1060
|
this._elements = [];
|
|
688
1061
|
this._offset = 0;
|
|
689
1062
|
}
|
|
690
1063
|
/**
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
1064
|
+
* Compact storage by discarding consumed head elements.
|
|
1065
|
+
* @remarks Time O(N), Space O(N)
|
|
1066
|
+
* @returns True when compaction performed.
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
* @example
|
|
1076
|
+
* // Reclaim unused memory
|
|
1077
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1078
|
+
* q.shift();
|
|
1079
|
+
* q.shift();
|
|
1080
|
+
* q.compact();
|
|
1081
|
+
* console.log(q.length); // 3;
|
|
1082
|
+
*/
|
|
695
1083
|
compact() {
|
|
696
1084
|
this._elements = this.elements.slice(this._offset);
|
|
697
1085
|
this._offset = 0;
|
|
@@ -717,10 +1105,26 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
717
1105
|
return removed;
|
|
718
1106
|
}
|
|
719
1107
|
/**
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
1108
|
+
* Deep clone this queue and its parameters.
|
|
1109
|
+
* @remarks Time O(N), Space O(N)
|
|
1110
|
+
* @returns A new queue with the same content and options.
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
* @example
|
|
1121
|
+
* // Create independent copy
|
|
1122
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1123
|
+
* const copy = q.clone();
|
|
1124
|
+
* copy.shift();
|
|
1125
|
+
* console.log(q.length); // 3;
|
|
1126
|
+
* console.log(copy.length); // 2;
|
|
1127
|
+
*/
|
|
724
1128
|
clone() {
|
|
725
1129
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
726
1130
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -728,12 +1132,26 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
728
1132
|
return out;
|
|
729
1133
|
}
|
|
730
1134
|
/**
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
1135
|
+
* Filter elements into a new queue of the same class.
|
|
1136
|
+
* @remarks Time O(N), Space O(N)
|
|
1137
|
+
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
1138
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1139
|
+
* @returns A new queue with kept elements.
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
* @example
|
|
1150
|
+
* // Filter elements
|
|
1151
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1152
|
+
* const evens = q.filter(x => x % 2 === 0);
|
|
1153
|
+
* console.log(evens.length); // 2;
|
|
1154
|
+
*/
|
|
737
1155
|
filter(predicate, thisArg) {
|
|
738
1156
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
739
1157
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -745,15 +1163,28 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
745
1163
|
return out;
|
|
746
1164
|
}
|
|
747
1165
|
/**
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
1166
|
+
* Map each element to a new element in a possibly different-typed queue.
|
|
1167
|
+
* @remarks Time O(N), Space O(N)
|
|
1168
|
+
* @template EM
|
|
1169
|
+
* @template RM
|
|
1170
|
+
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
1171
|
+
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
1172
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1173
|
+
* @returns A new Queue with mapped elements.
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
* @example
|
|
1183
|
+
* // Transform elements
|
|
1184
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1185
|
+
* const doubled = q.map(x => x * 2);
|
|
1186
|
+
* console.log(doubled.toArray()); // [2, 4, 6];
|
|
1187
|
+
*/
|
|
757
1188
|
map(callback, options, thisArg) {
|
|
758
1189
|
var _a, _b;
|
|
759
1190
|
const out = new this.constructor([], {
|
|
@@ -813,235 +1244,36 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
813
1244
|
*/
|
|
814
1245
|
*_getReverseIterator() {
|
|
815
1246
|
for (let i = this.length - 1; i >= 0; i--) {
|
|
816
|
-
const cur = this.at(i);
|
|
817
|
-
if (cur !== void 0) yield cur;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
/**
|
|
821
|
-
* (Protected) Create an empty instance of the same concrete class.
|
|
822
|
-
* @remarks Time O(1), Space O(1)
|
|
823
|
-
* @param [options] - Options forwarded to the constructor.
|
|
824
|
-
* @returns An empty like-kind queue instance.
|
|
825
|
-
*/
|
|
826
|
-
_createInstance(options) {
|
|
827
|
-
const Ctor = this.constructor;
|
|
828
|
-
return new Ctor([], options);
|
|
829
|
-
}
|
|
830
|
-
/**
|
|
831
|
-
* (Protected) Create a like-kind queue and seed it from an iterable.
|
|
832
|
-
* @remarks Time O(N), Space O(N)
|
|
833
|
-
* @template EM
|
|
834
|
-
* @template RM
|
|
835
|
-
* @param [elements] - Iterable used to seed the new queue.
|
|
836
|
-
* @param [options] - Options forwarded to the constructor.
|
|
837
|
-
* @returns A like-kind Queue instance.
|
|
838
|
-
*/
|
|
839
|
-
_createLike(elements = [], options) {
|
|
840
|
-
const Ctor = this.constructor;
|
|
841
|
-
return new Ctor(elements, options);
|
|
842
|
-
}
|
|
843
|
-
};
|
|
844
|
-
__name(_Queue, "Queue");
|
|
845
|
-
var Queue = _Queue;
|
|
846
|
-
|
|
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];
|
|
1247
|
+
const cur = this.at(i);
|
|
1248
|
+
if (cur !== void 0) yield cur;
|
|
1249
|
+
}
|
|
1008
1250
|
}
|
|
1009
1251
|
/**
|
|
1010
|
-
*
|
|
1011
|
-
* @
|
|
1012
|
-
* @
|
|
1252
|
+
* (Protected) Create an empty instance of the same concrete class.
|
|
1253
|
+
* @remarks Time O(1), Space O(1)
|
|
1254
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1255
|
+
* @returns An empty like-kind queue instance.
|
|
1013
1256
|
*/
|
|
1014
|
-
|
|
1015
|
-
|
|
1257
|
+
_createInstance(options) {
|
|
1258
|
+
const Ctor = this.constructor;
|
|
1259
|
+
return new Ctor([], options);
|
|
1016
1260
|
}
|
|
1017
1261
|
/**
|
|
1018
|
-
*
|
|
1019
|
-
* @remarks Time O(
|
|
1262
|
+
* (Protected) Create a like-kind queue and seed it from an iterable.
|
|
1263
|
+
* @remarks Time O(N), Space O(N)
|
|
1264
|
+
* @template EM
|
|
1265
|
+
* @template RM
|
|
1266
|
+
* @param [elements] - Iterable used to seed the new queue.
|
|
1267
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1268
|
+
* @returns A like-kind Queue instance.
|
|
1020
1269
|
*/
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
};
|
|
1025
|
-
__name(_IterableEntryBase, "IterableEntryBase");
|
|
1026
|
-
var IterableEntryBase = _IterableEntryBase;
|
|
1027
|
-
|
|
1028
|
-
// src/common/index.ts
|
|
1029
|
-
var _Range = class _Range {
|
|
1030
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
1031
|
-
this.low = low;
|
|
1032
|
-
this.high = high;
|
|
1033
|
-
this.includeLow = includeLow;
|
|
1034
|
-
this.includeHigh = includeHigh;
|
|
1035
|
-
}
|
|
1036
|
-
// Determine whether a key is within the range
|
|
1037
|
-
isInRange(key, comparator) {
|
|
1038
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
1039
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
1040
|
-
return lowCheck && highCheck;
|
|
1270
|
+
_createLike(elements = [], options) {
|
|
1271
|
+
const Ctor = this.constructor;
|
|
1272
|
+
return new Ctor(elements, options);
|
|
1041
1273
|
}
|
|
1042
1274
|
};
|
|
1043
|
-
__name(
|
|
1044
|
-
var
|
|
1275
|
+
__name(_Queue, "Queue");
|
|
1276
|
+
var Queue = _Queue;
|
|
1045
1277
|
|
|
1046
1278
|
// src/data-structures/binary-tree/binary-tree.ts
|
|
1047
1279
|
var _BinaryTreeNode = class _BinaryTreeNode {
|
|
@@ -1215,7 +1447,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1215
1447
|
if (isMapMode !== void 0) this._isMapMode = isMapMode;
|
|
1216
1448
|
if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
|
|
1217
1449
|
if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
|
|
1218
|
-
else if (toEntryFn) throw TypeError("toEntryFn
|
|
1450
|
+
else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
|
|
1219
1451
|
}
|
|
1220
1452
|
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
1221
1453
|
}
|
|
@@ -1420,30 +1652,78 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1420
1652
|
return isComparable(key);
|
|
1421
1653
|
}
|
|
1422
1654
|
/**
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1655
|
+
* Adds a new node to the tree.
|
|
1656
|
+
* @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).
|
|
1657
|
+
*
|
|
1658
|
+
* @param keyNodeOrEntry - The key, node, or entry to add.
|
|
1659
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1660
|
+
|
|
1661
|
+
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
|
|
1666
|
+
* @example
|
|
1667
|
+
* // Add a single node
|
|
1668
|
+
* const tree = new BinaryTree<number>();
|
|
1669
|
+
* tree.add(1);
|
|
1670
|
+
* tree.add(2);
|
|
1671
|
+
* tree.add(3);
|
|
1672
|
+
* console.log(tree.size); // 3;
|
|
1673
|
+
* console.log(tree.has(1)); // true;
|
|
1674
|
+
*/
|
|
1429
1675
|
add(keyNodeOrEntry) {
|
|
1430
1676
|
return this.set(keyNodeOrEntry);
|
|
1431
1677
|
}
|
|
1432
1678
|
/**
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1679
|
+
* Adds or updates a new node to the tree.
|
|
1680
|
+
* @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).
|
|
1681
|
+
*
|
|
1682
|
+
* @param keyNodeOrEntry - The key, node, or entry to set or update.
|
|
1683
|
+
* @param [value] - The value, if providing just a key.
|
|
1684
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1685
|
+
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
|
|
1696
|
+
* @example
|
|
1697
|
+
* // basic BinaryTree creation and insertion
|
|
1698
|
+
* // Create a BinaryTree with entries
|
|
1699
|
+
* const entries: [number, string][] = [
|
|
1700
|
+
* [6, 'six'],
|
|
1701
|
+
* [1, 'one'],
|
|
1702
|
+
* [2, 'two'],
|
|
1703
|
+
* [7, 'seven'],
|
|
1704
|
+
* [5, 'five'],
|
|
1705
|
+
* [3, 'three'],
|
|
1706
|
+
* [4, 'four'],
|
|
1707
|
+
* [9, 'nine'],
|
|
1708
|
+
* [8, 'eight']
|
|
1709
|
+
* ];
|
|
1710
|
+
*
|
|
1711
|
+
* const tree = new BinaryTree(entries);
|
|
1712
|
+
*
|
|
1713
|
+
* // Verify size
|
|
1714
|
+
* console.log(tree.size); // 9;
|
|
1715
|
+
*
|
|
1716
|
+
* // Add new element
|
|
1717
|
+
* tree.set(10, 'ten');
|
|
1718
|
+
* console.log(tree.size); // 10;
|
|
1719
|
+
*/
|
|
1440
1720
|
set(keyNodeOrEntry, value) {
|
|
1441
1721
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
1442
1722
|
if (newNode === void 0) return false;
|
|
1443
1723
|
if (!this._root) {
|
|
1444
1724
|
this._setRoot(newNode);
|
|
1445
1725
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
1446
|
-
this._size = 1;
|
|
1726
|
+
if (newNode !== null) this._size = 1;
|
|
1447
1727
|
return true;
|
|
1448
1728
|
}
|
|
1449
1729
|
const queue = new Queue([this._root]);
|
|
@@ -1475,29 +1755,50 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1475
1755
|
potentialParent.right = newNode;
|
|
1476
1756
|
}
|
|
1477
1757
|
if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
|
|
1478
|
-
this._size++;
|
|
1758
|
+
if (newNode !== null) this._size++;
|
|
1479
1759
|
return true;
|
|
1480
1760
|
}
|
|
1481
1761
|
return false;
|
|
1482
1762
|
}
|
|
1483
1763
|
/**
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1764
|
+
* Adds multiple items to the tree.
|
|
1765
|
+
* @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).
|
|
1766
|
+
*
|
|
1767
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
1768
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1769
|
+
|
|
1770
|
+
|
|
1771
|
+
|
|
1772
|
+
|
|
1773
|
+
|
|
1774
|
+
|
|
1775
|
+
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
* @example
|
|
1779
|
+
* // Bulk add
|
|
1780
|
+
* const tree = new BinaryTree<number>();
|
|
1781
|
+
* tree.addMany([1, 2, 3, 4, 5]);
|
|
1782
|
+
* console.log(tree.size); // 5;
|
|
1783
|
+
*/
|
|
1490
1784
|
addMany(keysNodesEntriesOrRaws) {
|
|
1491
1785
|
return this.setMany(keysNodesEntriesOrRaws);
|
|
1492
1786
|
}
|
|
1493
1787
|
/**
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1788
|
+
* Adds or updates multiple items to the tree.
|
|
1789
|
+
* @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).
|
|
1790
|
+
*
|
|
1791
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set or update.
|
|
1792
|
+
* @param [values] - An optional parallel iterable of values.
|
|
1793
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1794
|
+
|
|
1795
|
+
|
|
1796
|
+
* @example
|
|
1797
|
+
* // Set multiple entries
|
|
1798
|
+
* const tree = new BinaryTree<number, string>();
|
|
1799
|
+
* tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
1800
|
+
* console.log(tree.size); // 3;
|
|
1801
|
+
*/
|
|
1501
1802
|
setMany(keysNodesEntriesOrRaws, values) {
|
|
1502
1803
|
const inserted = [];
|
|
1503
1804
|
let valuesIterator;
|
|
@@ -1518,11 +1819,26 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1518
1819
|
return inserted;
|
|
1519
1820
|
}
|
|
1520
1821
|
/**
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1822
|
+
* Merges another tree into this one by seting all its nodes.
|
|
1823
|
+
* @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`).
|
|
1824
|
+
*
|
|
1825
|
+
* @param anotherTree - The tree to merge.
|
|
1826
|
+
|
|
1827
|
+
|
|
1828
|
+
|
|
1829
|
+
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
|
|
1833
|
+
|
|
1834
|
+
|
|
1835
|
+
* @example
|
|
1836
|
+
* // Combine trees
|
|
1837
|
+
* const t1 = new BinaryTree<number>([1, 2]);
|
|
1838
|
+
* const t2 = new BinaryTree<number>([3, 4]);
|
|
1839
|
+
* t1.merge(t2);
|
|
1840
|
+
* console.log(t1.size); // 4;
|
|
1841
|
+
*/
|
|
1526
1842
|
merge(anotherTree) {
|
|
1527
1843
|
this.setMany(anotherTree, []);
|
|
1528
1844
|
}
|
|
@@ -1538,12 +1854,29 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1538
1854
|
this.setMany(keysNodesEntriesOrRaws, values);
|
|
1539
1855
|
}
|
|
1540
1856
|
/**
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1857
|
+
* Deletes a node from the tree.
|
|
1858
|
+
* @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).
|
|
1859
|
+
*
|
|
1860
|
+
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
1861
|
+
* @returns An array containing deletion results (for compatibility with self-balancing trees).
|
|
1862
|
+
|
|
1863
|
+
|
|
1864
|
+
|
|
1865
|
+
|
|
1866
|
+
|
|
1867
|
+
|
|
1868
|
+
|
|
1869
|
+
|
|
1870
|
+
|
|
1871
|
+
|
|
1872
|
+
|
|
1873
|
+
* @example
|
|
1874
|
+
* // Remove a node
|
|
1875
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
1876
|
+
* tree.delete(3);
|
|
1877
|
+
* console.log(tree.has(3)); // false;
|
|
1878
|
+
* console.log(tree.size); // 4;
|
|
1879
|
+
*/
|
|
1547
1880
|
delete(keyNodeEntryRawOrPredicate) {
|
|
1548
1881
|
const deletedResult = [];
|
|
1549
1882
|
if (!this._root) return deletedResult;
|
|
@@ -1637,14 +1970,27 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1637
1970
|
return this.search(keyNodeEntryOrPredicate, onlyOne, (node) => node, startNode, iterationType);
|
|
1638
1971
|
}
|
|
1639
1972
|
/**
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1973
|
+
* Gets the first node matching a predicate.
|
|
1974
|
+
* @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`).
|
|
1975
|
+
*
|
|
1976
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
1977
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
1978
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1979
|
+
* @returns The first matching node, or undefined if not found.
|
|
1980
|
+
|
|
1981
|
+
|
|
1982
|
+
|
|
1983
|
+
|
|
1984
|
+
|
|
1985
|
+
|
|
1986
|
+
|
|
1987
|
+
|
|
1988
|
+
|
|
1989
|
+
* @example
|
|
1990
|
+
* // Get node by key
|
|
1991
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
|
|
1992
|
+
* console.log(tree.getNode(2)?.value); // 'child';
|
|
1993
|
+
*/
|
|
1648
1994
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1649
1995
|
if (this._isMapMode && keyNodeEntryOrPredicate !== null && keyNodeEntryOrPredicate !== void 0) {
|
|
1650
1996
|
if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
@@ -1656,14 +2002,30 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1656
2002
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType)[0];
|
|
1657
2003
|
}
|
|
1658
2004
|
/**
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
2005
|
+
* Gets the value associated with a key.
|
|
2006
|
+
* @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.
|
|
2007
|
+
*
|
|
2008
|
+
* @param keyNodeEntryOrPredicate - The key, node, or entry to get the value for.
|
|
2009
|
+
* @param [startNode=this._root] - The node to start searching from (if not in Map mode).
|
|
2010
|
+
* @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
|
|
2011
|
+
* @returns The associated value, or undefined.
|
|
2012
|
+
|
|
2013
|
+
|
|
2014
|
+
|
|
2015
|
+
|
|
2016
|
+
|
|
2017
|
+
|
|
2018
|
+
|
|
2019
|
+
|
|
2020
|
+
|
|
2021
|
+
|
|
2022
|
+
|
|
2023
|
+
* @example
|
|
2024
|
+
* // Retrieve value by key
|
|
2025
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
|
|
2026
|
+
* console.log(tree.get(2)); // 'left';
|
|
2027
|
+
* console.log(tree.get(99)); // undefined;
|
|
2028
|
+
*/
|
|
1667
2029
|
get(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1668
2030
|
var _a, _b;
|
|
1669
2031
|
if (this._isMapMode) {
|
|
@@ -1684,19 +2046,45 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1684
2046
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType).length > 0;
|
|
1685
2047
|
}
|
|
1686
2048
|
/**
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
2049
|
+
* Clears the tree of all nodes and values.
|
|
2050
|
+
* @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
|
|
2051
|
+
|
|
2052
|
+
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
|
|
2056
|
+
|
|
2057
|
+
|
|
2058
|
+
|
|
2059
|
+
|
|
2060
|
+
* @example
|
|
2061
|
+
* // Remove all nodes
|
|
2062
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2063
|
+
* tree.clear();
|
|
2064
|
+
* console.log(tree.isEmpty()); // true;
|
|
2065
|
+
*/
|
|
1690
2066
|
clear() {
|
|
1691
2067
|
this._clearNodes();
|
|
1692
2068
|
if (this._isMapMode) this._clearValues();
|
|
1693
2069
|
}
|
|
1694
2070
|
/**
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
2071
|
+
* Checks if the tree is empty.
|
|
2072
|
+
* @remarks Time O(1), Space O(1)
|
|
2073
|
+
*
|
|
2074
|
+
* @returns True if the tree has no nodes, false otherwise.
|
|
2075
|
+
|
|
2076
|
+
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
|
|
2084
|
+
* @example
|
|
2085
|
+
* // Check empty
|
|
2086
|
+
* console.log(new BinaryTree().isEmpty()); // true;
|
|
2087
|
+
*/
|
|
1700
2088
|
isEmpty() {
|
|
1701
2089
|
return this._size === 0;
|
|
1702
2090
|
}
|
|
@@ -1711,13 +2099,27 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1711
2099
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
1712
2100
|
}
|
|
1713
2101
|
/**
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
2102
|
+
* Checks if the tree is a valid Binary Search Tree (BST).
|
|
2103
|
+
* @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).
|
|
2104
|
+
*
|
|
2105
|
+
* @param [startNode=this._root] - The node to start checking from.
|
|
2106
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2107
|
+
* @returns True if it's a valid BST, false otherwise.
|
|
2108
|
+
|
|
2109
|
+
|
|
2110
|
+
|
|
2111
|
+
|
|
2112
|
+
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
|
|
2116
|
+
|
|
2117
|
+
* @example
|
|
2118
|
+
* // Check BST property
|
|
2119
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2120
|
+
* // BinaryTree doesn't guarantee BST order
|
|
2121
|
+
* console.log(typeof tree.isBST()); // 'boolean';
|
|
2122
|
+
*/
|
|
1721
2123
|
isBST(startNode = this._root, iterationType = this.iterationType) {
|
|
1722
2124
|
const startNodeSired = this.ensureNode(startNode);
|
|
1723
2125
|
if (!startNodeSired) return true;
|
|
@@ -1755,13 +2157,29 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1755
2157
|
}
|
|
1756
2158
|
}
|
|
1757
2159
|
/**
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
2160
|
+
* Gets the depth of a node (distance from `startNode`).
|
|
2161
|
+
* @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
|
|
2162
|
+
*
|
|
2163
|
+
* @param dist - The node to find the depth of.
|
|
2164
|
+
* @param [startNode=this._root] - The node to measure depth from (defaults to root).
|
|
2165
|
+
* @returns The depth (0 if `dist` is `startNode`).
|
|
2166
|
+
|
|
2167
|
+
|
|
2168
|
+
|
|
2169
|
+
|
|
2170
|
+
|
|
2171
|
+
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
|
|
2177
|
+
* @example
|
|
2178
|
+
* // Get depth of a node
|
|
2179
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2180
|
+
* const node = tree.getNode(4);
|
|
2181
|
+
* console.log(tree.getDepth(node!)); // 2;
|
|
2182
|
+
*/
|
|
1765
2183
|
getDepth(dist, startNode = this._root) {
|
|
1766
2184
|
let distEnsured = this.ensureNode(dist);
|
|
1767
2185
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
@@ -1776,13 +2194,28 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1776
2194
|
return depth;
|
|
1777
2195
|
}
|
|
1778
2196
|
/**
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
2197
|
+
* Gets the maximum height of the tree (longest path from startNode to a leaf).
|
|
2198
|
+
* @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).
|
|
2199
|
+
*
|
|
2200
|
+
* @param [startNode=this._root] - The node to start measuring from.
|
|
2201
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2202
|
+
* @returns The height ( -1 for an empty tree, 0 for a single-node tree).
|
|
2203
|
+
|
|
2204
|
+
|
|
2205
|
+
|
|
2206
|
+
|
|
2207
|
+
|
|
2208
|
+
|
|
2209
|
+
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
|
|
2213
|
+
|
|
2214
|
+
* @example
|
|
2215
|
+
* // Get tree height
|
|
2216
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2217
|
+
* console.log(tree.getHeight()); // 2;
|
|
2218
|
+
*/
|
|
1786
2219
|
getHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
1787
2220
|
startNode = this.ensureNode(startNode);
|
|
1788
2221
|
if (!this.isRealNode(startNode)) return -1;
|
|
@@ -2044,7 +2477,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2044
2477
|
}
|
|
2045
2478
|
/**
|
|
2046
2479
|
* Finds all leaf nodes in the tree.
|
|
2047
|
-
* @remarks Time O(N), visits every node. Space O(H) for recursive
|
|
2480
|
+
* @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
|
|
2048
2481
|
*
|
|
2049
2482
|
* @template C - The type of the callback function.
|
|
2050
2483
|
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
|
|
@@ -2067,15 +2500,15 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2067
2500
|
}, "dfs");
|
|
2068
2501
|
dfs(startNode);
|
|
2069
2502
|
} else {
|
|
2070
|
-
const
|
|
2071
|
-
while (
|
|
2072
|
-
const cur =
|
|
2503
|
+
const stack = [startNode];
|
|
2504
|
+
while (stack.length > 0) {
|
|
2505
|
+
const cur = stack.pop();
|
|
2073
2506
|
if (this.isRealNode(cur)) {
|
|
2074
2507
|
if (this.isLeaf(cur)) {
|
|
2075
2508
|
leaves.push(callback(cur));
|
|
2076
2509
|
}
|
|
2077
|
-
if (this.isRealNode(cur.
|
|
2078
|
-
if (this.isRealNode(cur.
|
|
2510
|
+
if (this.isRealNode(cur.right)) stack.push(cur.right);
|
|
2511
|
+
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
|
2079
2512
|
}
|
|
2080
2513
|
}
|
|
2081
2514
|
}
|
|
@@ -2218,24 +2651,53 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2218
2651
|
return ans;
|
|
2219
2652
|
}
|
|
2220
2653
|
/**
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2654
|
+
* Clones the tree.
|
|
2655
|
+
* @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.
|
|
2656
|
+
*
|
|
2657
|
+
* @returns A new, cloned instance of the tree.
|
|
2658
|
+
|
|
2659
|
+
|
|
2660
|
+
|
|
2661
|
+
|
|
2662
|
+
|
|
2663
|
+
|
|
2664
|
+
|
|
2665
|
+
|
|
2666
|
+
|
|
2667
|
+
* @example
|
|
2668
|
+
* // Deep copy
|
|
2669
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2670
|
+
* const copy = tree.clone();
|
|
2671
|
+
* copy.delete(1);
|
|
2672
|
+
* console.log(tree.has(1)); // true;
|
|
2673
|
+
*/
|
|
2226
2674
|
clone() {
|
|
2227
2675
|
const out = this._createInstance();
|
|
2228
2676
|
this._clone(out);
|
|
2229
2677
|
return out;
|
|
2230
2678
|
}
|
|
2231
2679
|
/**
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2680
|
+
* Creates a new tree containing only the entries that satisfy the predicate.
|
|
2681
|
+
* @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.
|
|
2682
|
+
*
|
|
2683
|
+
* @param predicate - A function to test each [key, value] pair.
|
|
2684
|
+
* @param [thisArg] - `this` context for the predicate.
|
|
2685
|
+
* @returns A new, filtered tree.
|
|
2686
|
+
|
|
2687
|
+
|
|
2688
|
+
|
|
2689
|
+
|
|
2690
|
+
|
|
2691
|
+
|
|
2692
|
+
|
|
2693
|
+
|
|
2694
|
+
|
|
2695
|
+
* @example
|
|
2696
|
+
* // Filter nodes by condition
|
|
2697
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4]);
|
|
2698
|
+
* const result = tree.filter((_, key) => key > 2);
|
|
2699
|
+
* console.log(result.size); // 2;
|
|
2700
|
+
*/
|
|
2239
2701
|
filter(predicate, thisArg) {
|
|
2240
2702
|
const out = this._createInstance();
|
|
2241
2703
|
let i = 0;
|
|
@@ -2243,17 +2705,31 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2243
2705
|
return out;
|
|
2244
2706
|
}
|
|
2245
2707
|
/**
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2708
|
+
* Creates a new tree by mapping each [key, value] pair to a new entry.
|
|
2709
|
+
* @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.
|
|
2710
|
+
*
|
|
2711
|
+
* @template MK - New key type.
|
|
2712
|
+
* @template MV - New value type.
|
|
2713
|
+
* @template MR - New raw type.
|
|
2714
|
+
* @param cb - A function to map each [key, value] pair.
|
|
2715
|
+
* @param [options] - Options for the new tree.
|
|
2716
|
+
* @param [thisArg] - `this` context for the callback.
|
|
2717
|
+
* @returns A new, mapped tree.
|
|
2718
|
+
|
|
2719
|
+
|
|
2720
|
+
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
* @example
|
|
2728
|
+
* // Transform to new tree
|
|
2729
|
+
* const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
|
|
2730
|
+
* const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
|
|
2731
|
+
* console.log([...mapped.values()]); // contains 11;
|
|
2732
|
+
*/
|
|
2257
2733
|
map(cb, options, thisArg) {
|
|
2258
2734
|
const out = this._createLike([], options);
|
|
2259
2735
|
let i = 0;
|
|
@@ -2291,12 +2767,25 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2291
2767
|
return output;
|
|
2292
2768
|
}
|
|
2293
2769
|
/**
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2770
|
+
* Prints a visual representation of the tree to the console.
|
|
2771
|
+
* @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
|
|
2772
|
+
*
|
|
2773
|
+
* @param [options] - Options to control the output.
|
|
2774
|
+
* @param [startNode=this._root] - The node to start printing from.
|
|
2775
|
+
|
|
2776
|
+
|
|
2777
|
+
|
|
2778
|
+
|
|
2779
|
+
|
|
2780
|
+
|
|
2781
|
+
|
|
2782
|
+
|
|
2783
|
+
|
|
2784
|
+
* @example
|
|
2785
|
+
* // Display tree
|
|
2786
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2787
|
+
* expect(() => tree.print()).not.toThrow();
|
|
2788
|
+
*/
|
|
2300
2789
|
print(options, startNode = this._root) {
|
|
2301
2790
|
console.log(this.toVisual(startNode, options));
|
|
2302
2791
|
}
|
|
@@ -2529,44 +3018,99 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2529
3018
|
* @returns Layout information for this subtree.
|
|
2530
3019
|
*/
|
|
2531
3020
|
_displayAux(node, options) {
|
|
2532
|
-
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
2533
3021
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
const
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
3022
|
+
const newFrame = /* @__PURE__ */ __name((n) => ({
|
|
3023
|
+
node: n,
|
|
3024
|
+
stage: 0,
|
|
3025
|
+
leftLayout: emptyDisplayLayout,
|
|
3026
|
+
rightLayout: emptyDisplayLayout
|
|
3027
|
+
}), "newFrame");
|
|
3028
|
+
const stack = [newFrame(node)];
|
|
3029
|
+
let result = emptyDisplayLayout;
|
|
3030
|
+
const setChildResult = /* @__PURE__ */ __name((layout) => {
|
|
3031
|
+
if (stack.length === 0) {
|
|
3032
|
+
result = layout;
|
|
3033
|
+
return;
|
|
3034
|
+
}
|
|
3035
|
+
const parent = stack[stack.length - 1];
|
|
3036
|
+
if (parent.stage === 1) parent.leftLayout = layout;
|
|
3037
|
+
else parent.rightLayout = layout;
|
|
3038
|
+
}, "setChildResult");
|
|
3039
|
+
while (stack.length > 0) {
|
|
3040
|
+
const frame = stack[stack.length - 1];
|
|
3041
|
+
const cur = frame.node;
|
|
3042
|
+
if (frame.stage === 0) {
|
|
3043
|
+
if (this._isDisplayLeaf(cur, options)) {
|
|
3044
|
+
stack.pop();
|
|
3045
|
+
const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
|
|
3046
|
+
setChildResult(layout);
|
|
3047
|
+
continue;
|
|
3048
|
+
}
|
|
3049
|
+
frame.stage = 1;
|
|
3050
|
+
stack.push(newFrame(cur.left));
|
|
3051
|
+
} else if (frame.stage === 1) {
|
|
3052
|
+
frame.stage = 2;
|
|
3053
|
+
stack.push(newFrame(cur.right));
|
|
3054
|
+
} else {
|
|
3055
|
+
stack.pop();
|
|
3056
|
+
const line = this.isNIL(cur) ? "S" : String(cur.key);
|
|
3057
|
+
const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
|
|
3058
|
+
setChildResult(layout);
|
|
2562
3059
|
}
|
|
2563
|
-
return [
|
|
2564
|
-
mergedLines,
|
|
2565
|
-
leftWidth + width + rightWidth,
|
|
2566
|
-
Math.max(leftHeight, rightHeight) + 2,
|
|
2567
|
-
leftWidth + Math.floor(width / 2)
|
|
2568
|
-
];
|
|
2569
3060
|
}
|
|
3061
|
+
return result;
|
|
3062
|
+
}
|
|
3063
|
+
static _buildNodeDisplay(line, width, left, right) {
|
|
3064
|
+
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
3065
|
+
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
3066
|
+
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));
|
|
3067
|
+
const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
|
|
3068
|
+
const mergedLines = [firstLine, secondLine];
|
|
3069
|
+
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
3070
|
+
const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
|
|
3071
|
+
const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
|
|
3072
|
+
mergedLines.push(leftLine + " ".repeat(width) + rightLine);
|
|
3073
|
+
}
|
|
3074
|
+
return [
|
|
3075
|
+
mergedLines,
|
|
3076
|
+
leftWidth + width + rightWidth,
|
|
3077
|
+
Math.max(leftHeight, rightHeight) + 2,
|
|
3078
|
+
leftWidth + Math.floor(width / 2)
|
|
3079
|
+
];
|
|
3080
|
+
}
|
|
3081
|
+
/**
|
|
3082
|
+
* Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
|
|
3083
|
+
*/
|
|
3084
|
+
_isDisplayLeaf(node, options) {
|
|
3085
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3086
|
+
if (node === null && !isShowNull) return true;
|
|
3087
|
+
if (node === void 0 && !isShowUndefined) return true;
|
|
3088
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return true;
|
|
3089
|
+
if (node === null || node === void 0) return true;
|
|
3090
|
+
const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
|
|
3091
|
+
const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
|
|
3092
|
+
return !hasDisplayableLeft && !hasDisplayableRight;
|
|
3093
|
+
}
|
|
3094
|
+
_hasDisplayableChild(child, options) {
|
|
3095
|
+
if (child === null) return !!options.isShowNull;
|
|
3096
|
+
if (child === void 0) return !!options.isShowUndefined;
|
|
3097
|
+
if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
|
|
3098
|
+
return true;
|
|
3099
|
+
}
|
|
3100
|
+
/**
|
|
3101
|
+
* Resolve a display leaf node to its layout.
|
|
3102
|
+
*/
|
|
3103
|
+
_resolveDisplayLeaf(node, options, emptyDisplayLayout) {
|
|
3104
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3105
|
+
if (node === null && !isShowNull) return emptyDisplayLayout;
|
|
3106
|
+
if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
|
|
3107
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
|
|
3108
|
+
if (node !== null && node !== void 0) {
|
|
3109
|
+
const line2 = this.isNIL(node) ? "S" : String(node.key);
|
|
3110
|
+
return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
|
|
3111
|
+
}
|
|
3112
|
+
const line = node === void 0 ? "U" : "N";
|
|
3113
|
+
return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
|
|
2570
3114
|
}
|
|
2571
3115
|
/**
|
|
2572
3116
|
* (Protected) Swaps the key/value properties of two nodes.
|
|
@@ -2770,6 +3314,7 @@ var _BSTNode = class _BSTNode {
|
|
|
2770
3314
|
*
|
|
2771
3315
|
* @returns The height.
|
|
2772
3316
|
*/
|
|
3317
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
2773
3318
|
get height() {
|
|
2774
3319
|
return this._height;
|
|
2775
3320
|
}
|
|
@@ -2779,6 +3324,7 @@ var _BSTNode = class _BSTNode {
|
|
|
2779
3324
|
*
|
|
2780
3325
|
* @param value - The new height.
|
|
2781
3326
|
*/
|
|
3327
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
2782
3328
|
set height(value) {
|
|
2783
3329
|
this._height = value;
|
|
2784
3330
|
}
|
|
@@ -2788,6 +3334,7 @@ var _BSTNode = class _BSTNode {
|
|
|
2788
3334
|
*
|
|
2789
3335
|
* @returns The node's color.
|
|
2790
3336
|
*/
|
|
3337
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
2791
3338
|
get color() {
|
|
2792
3339
|
return this._color;
|
|
2793
3340
|
}
|
|
@@ -2797,6 +3344,7 @@ var _BSTNode = class _BSTNode {
|
|
|
2797
3344
|
*
|
|
2798
3345
|
* @param value - The new color.
|
|
2799
3346
|
*/
|
|
3347
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
2800
3348
|
set color(value) {
|
|
2801
3349
|
this._color = value;
|
|
2802
3350
|
}
|
|
@@ -2806,6 +3354,7 @@ var _BSTNode = class _BSTNode {
|
|
|
2806
3354
|
*
|
|
2807
3355
|
* @returns The subtree node count.
|
|
2808
3356
|
*/
|
|
3357
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
2809
3358
|
get count() {
|
|
2810
3359
|
return this._count;
|
|
2811
3360
|
}
|
|
@@ -2815,6 +3364,7 @@ var _BSTNode = class _BSTNode {
|
|
|
2815
3364
|
*
|
|
2816
3365
|
* @param value - The new count.
|
|
2817
3366
|
*/
|
|
3367
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
2818
3368
|
set count(value) {
|
|
2819
3369
|
this._count = value;
|
|
2820
3370
|
}
|
|
@@ -2969,14 +3519,39 @@ var _BST = class _BST extends BinaryTree {
|
|
|
2969
3519
|
return super.listLevels(callback, startNode, iterationType, false);
|
|
2970
3520
|
}
|
|
2971
3521
|
/**
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
3522
|
+
* Gets the first node matching a predicate.
|
|
3523
|
+
* @remarks Time O(log N) if searching by key, O(N) if searching by predicate. Space O(log N) or O(N).
|
|
3524
|
+
*
|
|
3525
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
3526
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
3527
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
3528
|
+
* @returns The first matching node, or undefined if not found.
|
|
3529
|
+
|
|
3530
|
+
|
|
3531
|
+
|
|
3532
|
+
|
|
3533
|
+
|
|
3534
|
+
|
|
3535
|
+
|
|
3536
|
+
|
|
3537
|
+
|
|
3538
|
+
|
|
3539
|
+
|
|
3540
|
+
|
|
3541
|
+
|
|
3542
|
+
|
|
3543
|
+
|
|
3544
|
+
|
|
3545
|
+
|
|
3546
|
+
|
|
3547
|
+
|
|
3548
|
+
* @example
|
|
3549
|
+
* // Get node object by key
|
|
3550
|
+
* const bst = new BST<number, string>([[5, 'root'], [3, 'left'], [7, 'right']]);
|
|
3551
|
+
* const node = bst.getNode(3);
|
|
3552
|
+
* console.log(node?.key); // 3;
|
|
3553
|
+
* console.log(node?.value); // 'left';
|
|
3554
|
+
*/
|
|
2980
3555
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
2981
3556
|
var _a, _b;
|
|
2982
3557
|
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === void 0) return void 0;
|
|
@@ -3126,13 +3701,44 @@ var _BST = class _BST extends BinaryTree {
|
|
|
3126
3701
|
return this.search(searchRange, false, callback, startNode, iterationType);
|
|
3127
3702
|
}
|
|
3128
3703
|
/**
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3704
|
+
* Adds a new node to the BST based on key comparison.
|
|
3705
|
+
* @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
|
|
3706
|
+
*
|
|
3707
|
+
* @param keyNodeOrEntry - The key, node, or entry to set.
|
|
3708
|
+
* @param [value] - The value, if providing just a key.
|
|
3709
|
+
* @returns True if the addition was successful, false otherwise.
|
|
3710
|
+
|
|
3711
|
+
|
|
3712
|
+
|
|
3713
|
+
|
|
3714
|
+
|
|
3715
|
+
|
|
3716
|
+
|
|
3717
|
+
|
|
3718
|
+
|
|
3719
|
+
|
|
3720
|
+
|
|
3721
|
+
|
|
3722
|
+
|
|
3723
|
+
|
|
3724
|
+
|
|
3725
|
+
|
|
3726
|
+
|
|
3727
|
+
|
|
3728
|
+
|
|
3729
|
+
|
|
3730
|
+
|
|
3731
|
+
|
|
3732
|
+
|
|
3733
|
+
|
|
3734
|
+
|
|
3735
|
+
* @example
|
|
3736
|
+
* // Set a key-value pair
|
|
3737
|
+
* const bst = new BST<number, string>();
|
|
3738
|
+
* bst.set(1, 'one');
|
|
3739
|
+
* bst.set(2, 'two');
|
|
3740
|
+
* console.log(bst.get(1)); // 'one';
|
|
3741
|
+
*/
|
|
3136
3742
|
set(keyNodeOrEntry, value) {
|
|
3137
3743
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
3138
3744
|
if (newNode === void 0) return false;
|
|
@@ -3169,17 +3775,34 @@ var _BST = class _BST extends BinaryTree {
|
|
|
3169
3775
|
return false;
|
|
3170
3776
|
}
|
|
3171
3777
|
/**
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3778
|
+
* Adds multiple items to the tree.
|
|
3779
|
+
* @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced set).
|
|
3780
|
+
* If false, adds items one by one. Time O(N * H), which is O(N^2) worst-case.
|
|
3781
|
+
* Space O(N) for sorting and recursion/iteration stack.
|
|
3782
|
+
*
|
|
3783
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
3784
|
+
* @param [values] - An optional parallel iterable of values.
|
|
3785
|
+
* @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
|
|
3786
|
+
* @param [iterationType=this.iterationType] - The traversal method for balanced set (recursive or iterative).
|
|
3787
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
3788
|
+
|
|
3789
|
+
|
|
3790
|
+
|
|
3791
|
+
|
|
3792
|
+
|
|
3793
|
+
|
|
3794
|
+
|
|
3795
|
+
|
|
3796
|
+
|
|
3797
|
+
|
|
3798
|
+
|
|
3799
|
+
* @example
|
|
3800
|
+
* // Set multiple key-value pairs
|
|
3801
|
+
* const bst = new BST<number, string>();
|
|
3802
|
+
* bst.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3803
|
+
* console.log(bst.size); // 3;
|
|
3804
|
+
* console.log(bst.get(2)); // 'b';
|
|
3805
|
+
*/
|
|
3183
3806
|
setMany(keysNodesEntriesOrRaws, values, isBalanceAdd = true, iterationType = this.iterationType) {
|
|
3184
3807
|
const inserted = [];
|
|
3185
3808
|
const valuesIterator = values == null ? void 0 : values[Symbol.iterator]();
|
|
@@ -3422,12 +4045,29 @@ var _BST = class _BST extends BinaryTree {
|
|
|
3422
4045
|
}
|
|
3423
4046
|
}
|
|
3424
4047
|
/**
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
4048
|
+
* Rebuilds the tree to be perfectly balanced.
|
|
4049
|
+
* @remarks Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
|
|
4050
|
+
*
|
|
4051
|
+
* @param [iterationType=this.iterationType] - The traversal method for the initial node export.
|
|
4052
|
+
* @returns True if successful, false if the tree was empty.
|
|
4053
|
+
|
|
4054
|
+
|
|
4055
|
+
|
|
4056
|
+
|
|
4057
|
+
|
|
4058
|
+
|
|
4059
|
+
|
|
4060
|
+
|
|
4061
|
+
|
|
4062
|
+
* @example
|
|
4063
|
+
* // Rebalance the tree
|
|
4064
|
+
* const bst = new BST<number>();
|
|
4065
|
+
* // Insert in sorted order (worst case for BST)
|
|
4066
|
+
* for (let i = 1; i <= 7; i++) bst.add(i);
|
|
4067
|
+
* console.log(bst.isAVLBalanced()); // false;
|
|
4068
|
+
* bst.perfectlyBalance();
|
|
4069
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
4070
|
+
*/
|
|
3431
4071
|
perfectlyBalance(iterationType = this.iterationType) {
|
|
3432
4072
|
const nodes = this.dfs((node) => node, "IN", false, this._root, iterationType);
|
|
3433
4073
|
const n = nodes.length;
|
|
@@ -3450,12 +4090,25 @@ var _BST = class _BST extends BinaryTree {
|
|
|
3450
4090
|
return true;
|
|
3451
4091
|
}
|
|
3452
4092
|
/**
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
4093
|
+
* Checks if the tree meets the AVL balance condition (height difference <= 1).
|
|
4094
|
+
* @remarks Time O(N), as it must visit every node to compute height. Space O(log N) for recursion or O(N) for iterative map.
|
|
4095
|
+
*
|
|
4096
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
4097
|
+
* @returns True if the tree is AVL balanced, false otherwise.
|
|
4098
|
+
|
|
4099
|
+
|
|
4100
|
+
|
|
4101
|
+
|
|
4102
|
+
|
|
4103
|
+
|
|
4104
|
+
|
|
4105
|
+
|
|
4106
|
+
|
|
4107
|
+
* @example
|
|
4108
|
+
* // Check if tree is height-balanced
|
|
4109
|
+
* const bst = new BST<number>([3, 1, 5, 2, 4]);
|
|
4110
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
4111
|
+
*/
|
|
3459
4112
|
isAVLBalanced(iterationType = this.iterationType) {
|
|
3460
4113
|
if (!this._root) return true;
|
|
3461
4114
|
let balanced = true;
|
|
@@ -3495,18 +4148,42 @@ var _BST = class _BST extends BinaryTree {
|
|
|
3495
4148
|
return balanced;
|
|
3496
4149
|
}
|
|
3497
4150
|
/**
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
4151
|
+
* Creates a new BST by mapping each [key, value] pair to a new entry.
|
|
4152
|
+
* @remarks Time O(N * H), where N is nodes in this tree, and H is height of the new tree during insertion.
|
|
4153
|
+
* Space O(N) for the new tree.
|
|
4154
|
+
*
|
|
4155
|
+
* @template MK - New key type.
|
|
4156
|
+
* @template MV - New value type.
|
|
4157
|
+
* @template MR - New raw type.
|
|
4158
|
+
* @param callback - A function to map each [key, value] pair.
|
|
4159
|
+
* @param [options] - Options for the new BST.
|
|
4160
|
+
* @param [thisArg] - `this` context for the callback.
|
|
4161
|
+
* @returns A new, mapped BST.
|
|
4162
|
+
|
|
4163
|
+
|
|
4164
|
+
|
|
4165
|
+
|
|
4166
|
+
|
|
4167
|
+
|
|
4168
|
+
|
|
4169
|
+
|
|
4170
|
+
|
|
4171
|
+
|
|
4172
|
+
|
|
4173
|
+
|
|
4174
|
+
|
|
4175
|
+
|
|
4176
|
+
|
|
4177
|
+
|
|
4178
|
+
|
|
4179
|
+
|
|
4180
|
+
|
|
4181
|
+
* @example
|
|
4182
|
+
* // Transform to new tree
|
|
4183
|
+
* const bst = new BST<number, number>([[1, 10], [2, 20], [3, 30]]);
|
|
4184
|
+
* const doubled = bst.map((value, key) => [key, (value ?? 0) * 2] as [number, number]);
|
|
4185
|
+
* console.log([...doubled.values()]); // [20, 40, 60];
|
|
4186
|
+
*/
|
|
3510
4187
|
map(callback, options, thisArg) {
|
|
3511
4188
|
const out = this._createLike([], options);
|
|
3512
4189
|
let index = 0;
|
|
@@ -3572,9 +4249,15 @@ var _BST = class _BST extends BinaryTree {
|
|
|
3572
4249
|
if (a < b) return -1;
|
|
3573
4250
|
return 0;
|
|
3574
4251
|
}
|
|
4252
|
+
if (a instanceof Date && b instanceof Date) {
|
|
4253
|
+
const ta = a.getTime();
|
|
4254
|
+
const tb = b.getTime();
|
|
4255
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
|
|
4256
|
+
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
4257
|
+
}
|
|
3575
4258
|
if (typeof a === "object" || typeof b === "object") {
|
|
3576
|
-
throw TypeError(
|
|
3577
|
-
|
|
4259
|
+
throw new TypeError(
|
|
4260
|
+
ERR.comparatorRequired("BST")
|
|
3578
4261
|
);
|
|
3579
4262
|
}
|
|
3580
4263
|
return 0;
|
|
@@ -4074,15 +4757,12 @@ var _AVLTreeNode = class _AVLTreeNode {
|
|
|
4074
4757
|
*
|
|
4075
4758
|
* @returns The node's color.
|
|
4076
4759
|
*/
|
|
4760
|
+
/* istanbul ignore next -- inherited field, used by RedBlackTree subclass */
|
|
4761
|
+
/* istanbul ignore next -- inherited field, not used by AVLTree */
|
|
4077
4762
|
get color() {
|
|
4078
4763
|
return this._color;
|
|
4079
4764
|
}
|
|
4080
|
-
|
|
4081
|
-
* Sets the color of the node.
|
|
4082
|
-
* @remarks Time O(1), Space O(1)
|
|
4083
|
-
*
|
|
4084
|
-
* @param value - The new color.
|
|
4085
|
-
*/
|
|
4765
|
+
/* istanbul ignore next -- inherited field, not used by AVLTree */
|
|
4086
4766
|
set color(value) {
|
|
4087
4767
|
this._color = value;
|
|
4088
4768
|
}
|
|
@@ -4092,15 +4772,11 @@ var _AVLTreeNode = class _AVLTreeNode {
|
|
|
4092
4772
|
*
|
|
4093
4773
|
* @returns The subtree node count.
|
|
4094
4774
|
*/
|
|
4775
|
+
/* istanbul ignore next -- inherited field, not used by AVLTree */
|
|
4095
4776
|
get count() {
|
|
4096
4777
|
return this._count;
|
|
4097
4778
|
}
|
|
4098
|
-
|
|
4099
|
-
* Sets the count of nodes in the subtree.
|
|
4100
|
-
* @remarks Time O(1), Space O(1)
|
|
4101
|
-
*
|
|
4102
|
-
* @param value - The new count.
|
|
4103
|
-
*/
|
|
4779
|
+
/* istanbul ignore next -- inherited field, not used by AVLTree */
|
|
4104
4780
|
set count(value) {
|
|
4105
4781
|
this._count = value;
|
|
4106
4782
|
}
|
|
@@ -4158,13 +4834,55 @@ var _AVLTree = class _AVLTree extends BST {
|
|
|
4158
4834
|
return keyNodeOrEntry instanceof AVLTreeNode;
|
|
4159
4835
|
}
|
|
4160
4836
|
/**
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4837
|
+
* Sets a new node to the AVL tree and balances the tree path.
|
|
4838
|
+
* @remarks Time O(log N) (O(H) for BST set + O(H) for `_balancePath`). Space O(H) for path/recursion.
|
|
4839
|
+
*
|
|
4840
|
+
* @param keyNodeOrEntry - The key, node, or entry to set.
|
|
4841
|
+
* @param [value] - The value, if providing just a key.
|
|
4842
|
+
* @returns True if the addition was successful, false otherwise.
|
|
4843
|
+
|
|
4844
|
+
|
|
4845
|
+
|
|
4846
|
+
|
|
4847
|
+
|
|
4848
|
+
|
|
4849
|
+
|
|
4850
|
+
|
|
4851
|
+
|
|
4852
|
+
|
|
4853
|
+
|
|
4854
|
+
|
|
4855
|
+
|
|
4856
|
+
|
|
4857
|
+
|
|
4858
|
+
|
|
4859
|
+
|
|
4860
|
+
|
|
4861
|
+
|
|
4862
|
+
|
|
4863
|
+
|
|
4864
|
+
|
|
4865
|
+
|
|
4866
|
+
|
|
4867
|
+
|
|
4868
|
+
|
|
4869
|
+
|
|
4870
|
+
|
|
4871
|
+
|
|
4872
|
+
|
|
4873
|
+
|
|
4874
|
+
|
|
4875
|
+
|
|
4876
|
+
|
|
4877
|
+
|
|
4878
|
+
|
|
4879
|
+
* @example
|
|
4880
|
+
* // Set a key-value pair
|
|
4881
|
+
* const avl = new AVLTree<number, string>();
|
|
4882
|
+
* avl.set(1, 'one');
|
|
4883
|
+
* avl.set(2, 'two');
|
|
4884
|
+
* console.log(avl.get(1)); // 'one';
|
|
4885
|
+
*/
|
|
4168
4886
|
set(keyNodeOrEntry, value) {
|
|
4169
4887
|
if (keyNodeOrEntry === null) return false;
|
|
4170
4888
|
const inserted = super.set(keyNodeOrEntry, value);
|
|
@@ -4172,12 +4890,51 @@ var _AVLTree = class _AVLTree extends BST {
|
|
|
4172
4890
|
return inserted;
|
|
4173
4891
|
}
|
|
4174
4892
|
/**
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4893
|
+
* Deletes a node from the AVL tree and re-balances the tree.
|
|
4894
|
+
* @remarks Time O(log N) (O(H) for BST delete + O(H) for `_balancePath`). Space O(H) for path/recursion.
|
|
4895
|
+
*
|
|
4896
|
+
* @param keyNodeOrEntry - The node to delete.
|
|
4897
|
+
* @returns An array containing deletion results.
|
|
4898
|
+
|
|
4899
|
+
|
|
4900
|
+
|
|
4901
|
+
|
|
4902
|
+
|
|
4903
|
+
|
|
4904
|
+
|
|
4905
|
+
|
|
4906
|
+
|
|
4907
|
+
|
|
4908
|
+
|
|
4909
|
+
|
|
4910
|
+
|
|
4911
|
+
|
|
4912
|
+
|
|
4913
|
+
|
|
4914
|
+
|
|
4915
|
+
|
|
4916
|
+
|
|
4917
|
+
|
|
4918
|
+
|
|
4919
|
+
|
|
4920
|
+
|
|
4921
|
+
|
|
4922
|
+
|
|
4923
|
+
|
|
4924
|
+
|
|
4925
|
+
|
|
4926
|
+
|
|
4927
|
+
|
|
4928
|
+
|
|
4929
|
+
|
|
4930
|
+
|
|
4931
|
+
* @example
|
|
4932
|
+
* // Remove nodes and verify structure
|
|
4933
|
+
* const avl = new AVLTree<number>([5, 3, 7, 1, 4, 6, 8]);
|
|
4934
|
+
* avl.delete(3);
|
|
4935
|
+
* console.log(avl.has(3)); // false;
|
|
4936
|
+
* console.log(avl.size); // 6;
|
|
4937
|
+
*/
|
|
4181
4938
|
delete(keyNodeOrEntry) {
|
|
4182
4939
|
const deletedResults = super.delete(keyNodeOrEntry);
|
|
4183
4940
|
for (const { needBalanced } of deletedResults) {
|
|
@@ -4188,13 +4945,33 @@ var _AVLTree = class _AVLTree extends BST {
|
|
|
4188
4945
|
return deletedResults;
|
|
4189
4946
|
}
|
|
4190
4947
|
/**
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4948
|
+
* Rebuilds the tree to be perfectly balanced.
|
|
4949
|
+
* @remarks AVL trees are already height-balanced, but this makes them *perfectly* balanced (minimal height and all leaves at N or N-1).
|
|
4950
|
+
* Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
|
|
4951
|
+
*
|
|
4952
|
+
* @param [iterationType=this.iterationType] - The traversal method for the initial node export.
|
|
4953
|
+
* @returns True if successful, false if the tree was empty.
|
|
4954
|
+
|
|
4955
|
+
|
|
4956
|
+
|
|
4957
|
+
|
|
4958
|
+
|
|
4959
|
+
|
|
4960
|
+
|
|
4961
|
+
|
|
4962
|
+
|
|
4963
|
+
|
|
4964
|
+
|
|
4965
|
+
|
|
4966
|
+
* @example
|
|
4967
|
+
* // Rebalance the tree
|
|
4968
|
+
* const avl = new AVLTree<number>();
|
|
4969
|
+
* // Insert in sorted order (worst case for BST)
|
|
4970
|
+
* for (let i = 1; i <= 7; i++) avl.add(i);
|
|
4971
|
+
* console.log(avl.isAVLBalanced()); // false;
|
|
4972
|
+
* avl.perfectlyBalance();
|
|
4973
|
+
* console.log(avl.isAVLBalanced()); // true;
|
|
4974
|
+
*/
|
|
4198
4975
|
perfectlyBalance(iterationType = this.iterationType) {
|
|
4199
4976
|
const nodes = this.dfs((node) => node, "IN", false, this._root, iterationType);
|
|
4200
4977
|
const n = nodes.length;
|
|
@@ -4218,17 +4995,44 @@ var _AVLTree = class _AVLTree extends BST {
|
|
|
4218
4995
|
return true;
|
|
4219
4996
|
}
|
|
4220
4997
|
/**
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4998
|
+
* Creates a new AVLTree by mapping each [key, value] pair.
|
|
4999
|
+
* @remarks Time O(N log N) (O(N) iteration + O(log M) `set` for each item into the new tree). Space O(N) for the new tree.
|
|
5000
|
+
*
|
|
5001
|
+
* @template MK - New key type.
|
|
5002
|
+
* @template MV - New value type.
|
|
5003
|
+
* @template MR - New raw type.
|
|
5004
|
+
* @param callback - A function to map each [key, value] pair.
|
|
5005
|
+
* @param [options] - Options for the new AVLTree.
|
|
5006
|
+
* @param [thisArg] - `this` context for the callback.
|
|
5007
|
+
* @returns A new, mapped AVLTree.
|
|
5008
|
+
|
|
5009
|
+
|
|
5010
|
+
|
|
5011
|
+
|
|
5012
|
+
|
|
5013
|
+
|
|
5014
|
+
|
|
5015
|
+
|
|
5016
|
+
|
|
5017
|
+
|
|
5018
|
+
|
|
5019
|
+
|
|
5020
|
+
|
|
5021
|
+
|
|
5022
|
+
|
|
5023
|
+
|
|
5024
|
+
|
|
5025
|
+
|
|
5026
|
+
|
|
5027
|
+
|
|
5028
|
+
|
|
5029
|
+
|
|
5030
|
+
* @example
|
|
5031
|
+
* // Transform to new tree
|
|
5032
|
+
* const avl = new AVLTree<number, number>([[1, 10], [2, 20], [3, 30]]);
|
|
5033
|
+
* const doubled = avl.map((value, key) => [key, (value ?? 0) * 2] as [number, number]);
|
|
5034
|
+
* console.log([...doubled.values()]); // [20, 40, 60];
|
|
5035
|
+
*/
|
|
4232
5036
|
map(callback, options, thisArg) {
|
|
4233
5037
|
const out = this._createLike([], options);
|
|
4234
5038
|
let index = 0;
|