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