bst-typed 2.4.4 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -30
- package/dist/cjs/index.cjs +1228 -544
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +1225 -541
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1228 -545
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +1225 -542
- 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/bst-typed.js +1221 -537
- package/dist/umd/bst-typed.js.map +1 -1
- package/dist/umd/bst-typed.min.js +2 -2
- package/dist/umd/bst-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/common/error.ts +60 -0
- package/src/common/index.ts +2 -0
- package/src/data-structures/base/iterable-element-base.ts +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +303 -247
- package/src/data-structures/binary-tree/binary-tree.ts +542 -121
- package/src/data-structures/binary-tree/bst.ts +346 -37
- package/src/data-structures/binary-tree/red-black-tree.ts +309 -96
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1292 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +1098 -215
- package/src/data-structures/binary-tree/tree-multi-set.ts +863 -69
- package/src/data-structures/binary-tree/tree-set.ts +1143 -15
- package/src/data-structures/graph/abstract-graph.ts +106 -1
- package/src/data-structures/graph/directed-graph.ts +223 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +299 -59
- package/src/data-structures/hash/hash-map.ts +243 -79
- package/src/data-structures/heap/heap.ts +291 -102
- package/src/data-structures/heap/max-heap.ts +48 -3
- package/src/data-structures/heap/min-heap.ts +59 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +286 -44
- package/src/data-structures/linked-list/singly-linked-list.ts +278 -65
- package/src/data-structures/linked-list/skip-linked-list.ts +689 -90
- package/src/data-structures/matrix/matrix.ts +425 -22
- package/src/data-structures/priority-queue/max-priority-queue.ts +59 -3
- package/src/data-structures/priority-queue/min-priority-queue.ts +60 -0
- package/src/data-structures/priority-queue/priority-queue.ts +60 -0
- package/src/data-structures/queue/deque.ts +343 -68
- package/src/data-structures/queue/queue.ts +211 -42
- package/src/data-structures/stack/stack.ts +174 -32
- package/src/data-structures/trie/trie.ts +215 -44
- package/src/types/data-structures/binary-tree/segment-tree.ts +1 -1
- package/src/types/data-structures/linked-list/skip-linked-list.ts +2 -1
- package/src/types/data-structures/queue/deque.ts +7 -0
- package/src/utils/utils.ts +4 -2
package/dist/esm/index.mjs
CHANGED
|
@@ -473,6 +473,237 @@ var LinearBase = class _LinearBase extends IterableElementBase {
|
|
|
473
473
|
}
|
|
474
474
|
};
|
|
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 DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
503
|
+
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
504
|
+
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
505
|
+
return DFSOperation2;
|
|
506
|
+
})(DFSOperation || {});
|
|
507
|
+
var Range = class {
|
|
508
|
+
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
509
|
+
this.low = low;
|
|
510
|
+
this.high = high;
|
|
511
|
+
this.includeLow = includeLow;
|
|
512
|
+
this.includeHigh = includeHigh;
|
|
513
|
+
}
|
|
514
|
+
static {
|
|
515
|
+
__name(this, "Range");
|
|
516
|
+
}
|
|
517
|
+
// Determine whether a key is within the range
|
|
518
|
+
isInRange(key, comparator) {
|
|
519
|
+
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
520
|
+
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
521
|
+
return lowCheck && highCheck;
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
526
|
+
var IterableEntryBase = class {
|
|
527
|
+
static {
|
|
528
|
+
__name(this, "IterableEntryBase");
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Default iterator yielding `[key, value]` entries.
|
|
532
|
+
* @returns Iterator of `[K, V]`.
|
|
533
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
534
|
+
*/
|
|
535
|
+
*[Symbol.iterator](...args) {
|
|
536
|
+
yield* this._getIterator(...args);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
540
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
541
|
+
* @remarks Time O(n), Space O(1)
|
|
542
|
+
*/
|
|
543
|
+
*entries() {
|
|
544
|
+
for (const item of this) {
|
|
545
|
+
yield item;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Iterate over keys only.
|
|
550
|
+
* @returns Iterator of keys.
|
|
551
|
+
* @remarks Time O(n), Space O(1)
|
|
552
|
+
*/
|
|
553
|
+
*keys() {
|
|
554
|
+
for (const item of this) {
|
|
555
|
+
yield item[0];
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Iterate over values only.
|
|
560
|
+
* @returns Iterator of values.
|
|
561
|
+
* @remarks Time O(n), Space O(1)
|
|
562
|
+
*/
|
|
563
|
+
*values() {
|
|
564
|
+
for (const item of this) {
|
|
565
|
+
yield item[1];
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Test whether all entries satisfy the predicate.
|
|
570
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
571
|
+
* @param thisArg - Optional `this` for callback.
|
|
572
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
573
|
+
* @remarks Time O(n), Space O(1)
|
|
574
|
+
*/
|
|
575
|
+
every(predicate, thisArg) {
|
|
576
|
+
let index = 0;
|
|
577
|
+
for (const item of this) {
|
|
578
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
579
|
+
return false;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
return true;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Test whether any entry satisfies the predicate.
|
|
586
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
587
|
+
* @param thisArg - Optional `this` for callback.
|
|
588
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
589
|
+
* @remarks Time O(n), Space O(1)
|
|
590
|
+
*/
|
|
591
|
+
some(predicate, thisArg) {
|
|
592
|
+
let index = 0;
|
|
593
|
+
for (const item of this) {
|
|
594
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Visit each entry, left-to-right.
|
|
602
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
603
|
+
* @param thisArg - Optional `this` for callback.
|
|
604
|
+
* @remarks Time O(n), Space O(1)
|
|
605
|
+
*/
|
|
606
|
+
forEach(callbackfn, thisArg) {
|
|
607
|
+
let index = 0;
|
|
608
|
+
for (const item of this) {
|
|
609
|
+
const [key, value] = item;
|
|
610
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Find the first entry that matches a predicate.
|
|
615
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
616
|
+
* @param thisArg - Optional `this` for callback.
|
|
617
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
618
|
+
* @remarks Time O(n), Space O(1)
|
|
619
|
+
*/
|
|
620
|
+
find(callbackfn, thisArg) {
|
|
621
|
+
let index = 0;
|
|
622
|
+
for (const item of this) {
|
|
623
|
+
const [key, value] = item;
|
|
624
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
625
|
+
}
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Whether the given key exists.
|
|
630
|
+
* @param key - Key to test.
|
|
631
|
+
* @returns `true` if found; otherwise `false`.
|
|
632
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
633
|
+
*/
|
|
634
|
+
has(key) {
|
|
635
|
+
for (const item of this) {
|
|
636
|
+
const [itemKey] = item;
|
|
637
|
+
if (itemKey === key) return true;
|
|
638
|
+
}
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Whether there exists an entry with the given value.
|
|
643
|
+
* @param value - Value to test.
|
|
644
|
+
* @returns `true` if found; otherwise `false`.
|
|
645
|
+
* @remarks Time O(n), Space O(1)
|
|
646
|
+
*/
|
|
647
|
+
hasValue(value) {
|
|
648
|
+
for (const [, elementValue] of this) {
|
|
649
|
+
if (elementValue === value) return true;
|
|
650
|
+
}
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Get the value under a key.
|
|
655
|
+
* @param key - Key to look up.
|
|
656
|
+
* @returns Value or `undefined`.
|
|
657
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
658
|
+
*/
|
|
659
|
+
get(key) {
|
|
660
|
+
for (const item of this) {
|
|
661
|
+
const [itemKey, value] = item;
|
|
662
|
+
if (itemKey === key) return value;
|
|
663
|
+
}
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Reduce entries into a single accumulator.
|
|
668
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
669
|
+
* @param initialValue - Initial accumulator.
|
|
670
|
+
* @returns Final accumulator.
|
|
671
|
+
* @remarks Time O(n), Space O(1)
|
|
672
|
+
*/
|
|
673
|
+
reduce(callbackfn, initialValue) {
|
|
674
|
+
let accumulator = initialValue;
|
|
675
|
+
let index = 0;
|
|
676
|
+
for (const item of this) {
|
|
677
|
+
const [key, value] = item;
|
|
678
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
679
|
+
}
|
|
680
|
+
return accumulator;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Converts data structure to `[key, value]` pairs.
|
|
684
|
+
* @returns Array of entries.
|
|
685
|
+
* @remarks Time O(n), Space O(n)
|
|
686
|
+
*/
|
|
687
|
+
toArray() {
|
|
688
|
+
return [...this];
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
692
|
+
* @returns Array of entries (default) or a string.
|
|
693
|
+
* @remarks Time O(n), Space O(n)
|
|
694
|
+
*/
|
|
695
|
+
toVisual() {
|
|
696
|
+
return [...this];
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Print a human-friendly representation to the console.
|
|
700
|
+
* @remarks Time O(n), Space O(n)
|
|
701
|
+
*/
|
|
702
|
+
print() {
|
|
703
|
+
console.log(this.toVisual());
|
|
704
|
+
}
|
|
705
|
+
};
|
|
706
|
+
|
|
476
707
|
// src/data-structures/queue/queue.ts
|
|
477
708
|
var Queue = class _Queue extends LinearBase {
|
|
478
709
|
static {
|
|
@@ -530,18 +761,52 @@ var Queue = class _Queue extends LinearBase {
|
|
|
530
761
|
this._autoCompactRatio = value;
|
|
531
762
|
}
|
|
532
763
|
/**
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
764
|
+
* Get the number of elements currently in the queue.
|
|
765
|
+
* @remarks Time O(1), Space O(1)
|
|
766
|
+
* @returns Current length.
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
* @example
|
|
779
|
+
* // Track queue length
|
|
780
|
+
* const q = new Queue<number>();
|
|
781
|
+
* console.log(q.length); // 0;
|
|
782
|
+
* q.push(1);
|
|
783
|
+
* q.push(2);
|
|
784
|
+
* console.log(q.length); // 2;
|
|
785
|
+
*/
|
|
537
786
|
get length() {
|
|
538
787
|
return this.elements.length - this._offset;
|
|
539
788
|
}
|
|
540
789
|
/**
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
790
|
+
* Get the first element (front) without removing it.
|
|
791
|
+
* @remarks Time O(1), Space O(1)
|
|
792
|
+
* @returns Front element or undefined.
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
* @example
|
|
805
|
+
* // View the front element
|
|
806
|
+
* const q = new Queue<string>(['first', 'second', 'third']);
|
|
807
|
+
* console.log(q.first); // 'first';
|
|
808
|
+
* console.log(q.length); // 3;
|
|
809
|
+
*/
|
|
545
810
|
get first() {
|
|
546
811
|
return this.length > 0 ? this.elements[this._offset] : void 0;
|
|
547
812
|
}
|
|
@@ -564,19 +829,69 @@ var Queue = class _Queue extends LinearBase {
|
|
|
564
829
|
return new _Queue(elements);
|
|
565
830
|
}
|
|
566
831
|
/**
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
832
|
+
* Check whether the queue is empty.
|
|
833
|
+
* @remarks Time O(1), Space O(1)
|
|
834
|
+
* @returns True if length is 0.
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
* @example
|
|
847
|
+
* // Queue for...of iteration and isEmpty check
|
|
848
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
849
|
+
*
|
|
850
|
+
* const elements: string[] = [];
|
|
851
|
+
* for (const item of queue) {
|
|
852
|
+
* elements.push(item);
|
|
853
|
+
* }
|
|
854
|
+
*
|
|
855
|
+
* // Verify all elements are iterated in order
|
|
856
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
857
|
+
*
|
|
858
|
+
* // Process all elements
|
|
859
|
+
* while (queue.length > 0) {
|
|
860
|
+
* queue.shift();
|
|
861
|
+
* }
|
|
862
|
+
*
|
|
863
|
+
* console.log(queue.length); // 0;
|
|
864
|
+
*/
|
|
571
865
|
isEmpty() {
|
|
572
866
|
return this.length === 0;
|
|
573
867
|
}
|
|
574
868
|
/**
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
869
|
+
* Enqueue one element at the back.
|
|
870
|
+
* @remarks Time O(1), Space O(1)
|
|
871
|
+
* @param element - Element to enqueue.
|
|
872
|
+
* @returns True on success.
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
* @example
|
|
885
|
+
* // basic Queue creation and push operation
|
|
886
|
+
* // Create a simple Queue with initial values
|
|
887
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
888
|
+
*
|
|
889
|
+
* // Verify the queue maintains insertion order
|
|
890
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
891
|
+
*
|
|
892
|
+
* // Check length
|
|
893
|
+
* console.log(queue.length); // 5;
|
|
894
|
+
*/
|
|
580
895
|
push(element) {
|
|
581
896
|
this.elements.push(element);
|
|
582
897
|
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
@@ -597,10 +912,35 @@ var Queue = class _Queue extends LinearBase {
|
|
|
597
912
|
return ans;
|
|
598
913
|
}
|
|
599
914
|
/**
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
915
|
+
* Dequeue one element from the front (amortized via offset).
|
|
916
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
917
|
+
* @returns Removed element or undefined.
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
* @example
|
|
930
|
+
* // Queue shift and peek operations
|
|
931
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
932
|
+
*
|
|
933
|
+
* // Peek at the front element without removing it
|
|
934
|
+
* console.log(queue.first); // 10;
|
|
935
|
+
*
|
|
936
|
+
* // Remove and get the first element (FIFO)
|
|
937
|
+
* const first = queue.shift();
|
|
938
|
+
* console.log(first); // 10;
|
|
939
|
+
*
|
|
940
|
+
* // Verify remaining elements and length decreased
|
|
941
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
942
|
+
* console.log(queue.length); // 3;
|
|
943
|
+
*/
|
|
604
944
|
shift() {
|
|
605
945
|
if (this.length === 0) return void 0;
|
|
606
946
|
const first = this.first;
|
|
@@ -609,11 +949,24 @@ var Queue = class _Queue extends LinearBase {
|
|
|
609
949
|
return first;
|
|
610
950
|
}
|
|
611
951
|
/**
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
952
|
+
* Delete the first occurrence of a specific element.
|
|
953
|
+
* @remarks Time O(N), Space O(1)
|
|
954
|
+
* @param element - Element to remove (strict equality via Object.is).
|
|
955
|
+
* @returns True if an element was removed.
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
* @example
|
|
965
|
+
* // Remove specific element
|
|
966
|
+
* const q = new Queue<number>([1, 2, 3, 2]);
|
|
967
|
+
* q.delete(2);
|
|
968
|
+
* console.log(q.length); // 3;
|
|
969
|
+
*/
|
|
617
970
|
delete(element) {
|
|
618
971
|
for (let i = this._offset; i < this.elements.length; i++) {
|
|
619
972
|
if (Object.is(this.elements[i], element)) {
|
|
@@ -624,11 +977,24 @@ var Queue = class _Queue extends LinearBase {
|
|
|
624
977
|
return false;
|
|
625
978
|
}
|
|
626
979
|
/**
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
980
|
+
* Get the element at a given logical index.
|
|
981
|
+
* @remarks Time O(1), Space O(1)
|
|
982
|
+
* @param index - Zero-based index from the front.
|
|
983
|
+
* @returns Element or undefined.
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
* @example
|
|
993
|
+
* // Access element by index
|
|
994
|
+
* const q = new Queue<string>(['a', 'b', 'c']);
|
|
995
|
+
* console.log(q.at(0)); // 'a';
|
|
996
|
+
* console.log(q.at(2)); // 'c';
|
|
997
|
+
*/
|
|
632
998
|
at(index) {
|
|
633
999
|
if (index < 0 || index >= this.length) return void 0;
|
|
634
1000
|
return this._elements[this._offset + index];
|
|
@@ -680,19 +1046,48 @@ var Queue = class _Queue extends LinearBase {
|
|
|
680
1046
|
return this;
|
|
681
1047
|
}
|
|
682
1048
|
/**
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
1049
|
+
* Remove all elements and reset offset.
|
|
1050
|
+
* @remarks Time O(1), Space O(1)
|
|
1051
|
+
* @returns void
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
* @example
|
|
1062
|
+
* // Remove all elements
|
|
1063
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1064
|
+
* q.clear();
|
|
1065
|
+
* console.log(q.length); // 0;
|
|
1066
|
+
*/
|
|
687
1067
|
clear() {
|
|
688
1068
|
this._elements = [];
|
|
689
1069
|
this._offset = 0;
|
|
690
1070
|
}
|
|
691
1071
|
/**
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
1072
|
+
* Compact storage by discarding consumed head elements.
|
|
1073
|
+
* @remarks Time O(N), Space O(N)
|
|
1074
|
+
* @returns True when compaction performed.
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
* @example
|
|
1084
|
+
* // Reclaim unused memory
|
|
1085
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1086
|
+
* q.shift();
|
|
1087
|
+
* q.shift();
|
|
1088
|
+
* q.compact();
|
|
1089
|
+
* console.log(q.length); // 3;
|
|
1090
|
+
*/
|
|
696
1091
|
compact() {
|
|
697
1092
|
this._elements = this.elements.slice(this._offset);
|
|
698
1093
|
this._offset = 0;
|
|
@@ -718,332 +1113,169 @@ var Queue = class _Queue extends LinearBase {
|
|
|
718
1113
|
return removed;
|
|
719
1114
|
}
|
|
720
1115
|
/**
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
1116
|
+
* Deep clone this queue and its parameters.
|
|
1117
|
+
* @remarks Time O(N), Space O(N)
|
|
1118
|
+
* @returns A new queue with the same content and options.
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
* @example
|
|
1129
|
+
* // Create independent copy
|
|
1130
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1131
|
+
* const copy = q.clone();
|
|
1132
|
+
* copy.shift();
|
|
1133
|
+
* console.log(q.length); // 3;
|
|
1134
|
+
* console.log(copy.length); // 2;
|
|
1135
|
+
*/
|
|
725
1136
|
clone() {
|
|
726
1137
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
727
1138
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
728
1139
|
for (let i = this._offset; i < this.elements.length; i++) out.push(this.elements[i]);
|
|
729
|
-
return out;
|
|
730
|
-
}
|
|
731
|
-
/**
|
|
732
|
-
* Filter elements into a new queue of the same class.
|
|
733
|
-
* @remarks Time O(N), Space O(N)
|
|
734
|
-
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
735
|
-
* @param [thisArg] - Value for `this` inside the predicate.
|
|
736
|
-
* @returns A new queue with kept elements.
|
|
737
|
-
*/
|
|
738
|
-
filter(predicate, thisArg) {
|
|
739
|
-
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
740
|
-
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
741
|
-
let index = 0;
|
|
742
|
-
for (const v of this) {
|
|
743
|
-
if (predicate.call(thisArg, v, index, this)) out.push(v);
|
|
744
|
-
index++;
|
|
745
|
-
}
|
|
746
|
-
return out;
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* Map each element to a new element in a possibly different-typed queue.
|
|
750
|
-
* @remarks Time O(N), Space O(N)
|
|
751
|
-
* @template EM
|
|
752
|
-
* @template RM
|
|
753
|
-
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
754
|
-
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
755
|
-
* @param [thisArg] - Value for `this` inside the callback.
|
|
756
|
-
* @returns A new Queue with mapped elements.
|
|
757
|
-
*/
|
|
758
|
-
map(callback, options, thisArg) {
|
|
759
|
-
const out = new this.constructor([], {
|
|
760
|
-
toElementFn: options?.toElementFn,
|
|
761
|
-
maxLen: options?.maxLen ?? this._maxLen,
|
|
762
|
-
autoCompactRatio: options?.autoCompactRatio ?? this._autoCompactRatio
|
|
763
|
-
});
|
|
764
|
-
let index = 0;
|
|
765
|
-
for (const v of this)
|
|
766
|
-
out.push(thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this));
|
|
767
|
-
return out;
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* Map each element to a new value of the same type.
|
|
771
|
-
* @remarks Time O(N), Space O(N)
|
|
772
|
-
* @param callback - Mapping function (element, index, queue) → element.
|
|
773
|
-
* @param [thisArg] - Value for `this` inside the callback.
|
|
774
|
-
* @returns A new queue with mapped elements (same element type).
|
|
775
|
-
*/
|
|
776
|
-
mapSame(callback, thisArg) {
|
|
777
|
-
const Ctor = this.constructor;
|
|
778
|
-
const out = new Ctor([], {
|
|
779
|
-
toElementFn: this.toElementFn,
|
|
780
|
-
maxLen: this._maxLen,
|
|
781
|
-
autoCompactRatio: this._autoCompactRatio
|
|
782
|
-
});
|
|
783
|
-
out._setAutoCompactRatio?.(this._autoCompactRatio);
|
|
784
|
-
let index = 0;
|
|
785
|
-
for (const v of this) {
|
|
786
|
-
const mv = thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
|
|
787
|
-
out.push(mv);
|
|
788
|
-
}
|
|
789
|
-
return out;
|
|
790
|
-
}
|
|
791
|
-
/**
|
|
792
|
-
* (Protected) Set the internal auto-compaction ratio.
|
|
793
|
-
* @remarks Time O(1), Space O(1)
|
|
794
|
-
* @param value - New ratio to assign.
|
|
795
|
-
* @returns void
|
|
796
|
-
*/
|
|
797
|
-
_setAutoCompactRatio(value) {
|
|
798
|
-
this._autoCompactRatio = value;
|
|
799
|
-
}
|
|
800
|
-
/**
|
|
801
|
-
* (Protected) Iterate elements from front to back.
|
|
802
|
-
* @remarks Time O(N), Space O(1)
|
|
803
|
-
* @returns Iterator of E.
|
|
804
|
-
*/
|
|
805
|
-
*_getIterator() {
|
|
806
|
-
for (let i = this._offset; i < this.elements.length; i++) yield this.elements[i];
|
|
807
|
-
}
|
|
808
|
-
/**
|
|
809
|
-
* (Protected) Iterate elements from back to front.
|
|
810
|
-
* @remarks Time O(N), Space O(1)
|
|
811
|
-
* @returns Iterator of E.
|
|
812
|
-
*/
|
|
813
|
-
*_getReverseIterator() {
|
|
814
|
-
for (let i = this.length - 1; i >= 0; i--) {
|
|
815
|
-
const cur = this.at(i);
|
|
816
|
-
if (cur !== void 0) yield cur;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
/**
|
|
820
|
-
* (Protected) Create an empty instance of the same concrete class.
|
|
821
|
-
* @remarks Time O(1), Space O(1)
|
|
822
|
-
* @param [options] - Options forwarded to the constructor.
|
|
823
|
-
* @returns An empty like-kind queue instance.
|
|
824
|
-
*/
|
|
825
|
-
_createInstance(options) {
|
|
826
|
-
const Ctor = this.constructor;
|
|
827
|
-
return new Ctor([], options);
|
|
828
|
-
}
|
|
829
|
-
/**
|
|
830
|
-
* (Protected) Create a like-kind queue and seed it from an iterable.
|
|
831
|
-
* @remarks Time O(N), Space O(N)
|
|
832
|
-
* @template EM
|
|
833
|
-
* @template RM
|
|
834
|
-
* @param [elements] - Iterable used to seed the new queue.
|
|
835
|
-
* @param [options] - Options forwarded to the constructor.
|
|
836
|
-
* @returns A like-kind Queue instance.
|
|
837
|
-
*/
|
|
838
|
-
_createLike(elements = [], options) {
|
|
839
|
-
const Ctor = this.constructor;
|
|
840
|
-
return new Ctor(elements, options);
|
|
841
|
-
}
|
|
842
|
-
};
|
|
843
|
-
|
|
844
|
-
// src/data-structures/base/iterable-entry-base.ts
|
|
845
|
-
var IterableEntryBase = class {
|
|
846
|
-
static {
|
|
847
|
-
__name(this, "IterableEntryBase");
|
|
848
|
-
}
|
|
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
|
-
}
|
|
1140
|
+
return out;
|
|
931
1141
|
}
|
|
932
1142
|
/**
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1143
|
+
* Filter elements into a new queue of the same class.
|
|
1144
|
+
* @remarks Time O(N), Space O(N)
|
|
1145
|
+
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
1146
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1147
|
+
* @returns A new queue with kept elements.
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
* @example
|
|
1158
|
+
* // Filter elements
|
|
1159
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1160
|
+
* const evens = q.filter(x => x % 2 === 0);
|
|
1161
|
+
* console.log(evens.length); // 2;
|
|
1162
|
+
*/
|
|
1163
|
+
filter(predicate, thisArg) {
|
|
1164
|
+
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
1165
|
+
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
940
1166
|
let index = 0;
|
|
941
|
-
for (const
|
|
942
|
-
|
|
943
|
-
|
|
1167
|
+
for (const v of this) {
|
|
1168
|
+
if (predicate.call(thisArg, v, index, this)) out.push(v);
|
|
1169
|
+
index++;
|
|
944
1170
|
}
|
|
945
|
-
return;
|
|
1171
|
+
return out;
|
|
946
1172
|
}
|
|
947
1173
|
/**
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1174
|
+
* Map each element to a new element in a possibly different-typed queue.
|
|
1175
|
+
* @remarks Time O(N), Space O(N)
|
|
1176
|
+
* @template EM
|
|
1177
|
+
* @template RM
|
|
1178
|
+
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
1179
|
+
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
1180
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1181
|
+
* @returns A new Queue with mapped elements.
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
* @example
|
|
1191
|
+
* // Transform elements
|
|
1192
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1193
|
+
* const doubled = q.map(x => x * 2);
|
|
1194
|
+
* console.log(doubled.toArray()); // [2, 4, 6];
|
|
1195
|
+
*/
|
|
1196
|
+
map(callback, options, thisArg) {
|
|
1197
|
+
const out = new this.constructor([], {
|
|
1198
|
+
toElementFn: options?.toElementFn,
|
|
1199
|
+
maxLen: options?.maxLen ?? this._maxLen,
|
|
1200
|
+
autoCompactRatio: options?.autoCompactRatio ?? this._autoCompactRatio
|
|
1201
|
+
});
|
|
1202
|
+
let index = 0;
|
|
1203
|
+
for (const v of this)
|
|
1204
|
+
out.push(thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this));
|
|
1205
|
+
return out;
|
|
959
1206
|
}
|
|
960
1207
|
/**
|
|
961
|
-
*
|
|
962
|
-
* @
|
|
963
|
-
* @
|
|
964
|
-
* @
|
|
1208
|
+
* Map each element to a new value of the same type.
|
|
1209
|
+
* @remarks Time O(N), Space O(N)
|
|
1210
|
+
* @param callback - Mapping function (element, index, queue) → element.
|
|
1211
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1212
|
+
* @returns A new queue with mapped elements (same element type).
|
|
965
1213
|
*/
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
1214
|
+
mapSame(callback, thisArg) {
|
|
1215
|
+
const Ctor = this.constructor;
|
|
1216
|
+
const out = new Ctor([], {
|
|
1217
|
+
toElementFn: this.toElementFn,
|
|
1218
|
+
maxLen: this._maxLen,
|
|
1219
|
+
autoCompactRatio: this._autoCompactRatio
|
|
1220
|
+
});
|
|
1221
|
+
out._setAutoCompactRatio?.(this._autoCompactRatio);
|
|
1222
|
+
let index = 0;
|
|
1223
|
+
for (const v of this) {
|
|
1224
|
+
const mv = thisArg === void 0 ? callback(v, index++, this) : callback.call(thisArg, v, index++, this);
|
|
1225
|
+
out.push(mv);
|
|
969
1226
|
}
|
|
970
|
-
return
|
|
1227
|
+
return out;
|
|
971
1228
|
}
|
|
972
1229
|
/**
|
|
973
|
-
*
|
|
974
|
-
* @
|
|
975
|
-
* @
|
|
976
|
-
* @
|
|
1230
|
+
* (Protected) Set the internal auto-compaction ratio.
|
|
1231
|
+
* @remarks Time O(1), Space O(1)
|
|
1232
|
+
* @param value - New ratio to assign.
|
|
1233
|
+
* @returns void
|
|
977
1234
|
*/
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
const [itemKey, value] = item;
|
|
981
|
-
if (itemKey === key) return value;
|
|
982
|
-
}
|
|
983
|
-
return;
|
|
1235
|
+
_setAutoCompactRatio(value) {
|
|
1236
|
+
this._autoCompactRatio = value;
|
|
984
1237
|
}
|
|
985
1238
|
/**
|
|
986
|
-
*
|
|
987
|
-
* @
|
|
988
|
-
* @
|
|
989
|
-
* @returns Final accumulator.
|
|
990
|
-
* @remarks Time O(n), Space O(1)
|
|
1239
|
+
* (Protected) Iterate elements from front to back.
|
|
1240
|
+
* @remarks Time O(N), Space O(1)
|
|
1241
|
+
* @returns Iterator of E.
|
|
991
1242
|
*/
|
|
992
|
-
|
|
993
|
-
let
|
|
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;
|
|
1243
|
+
*_getIterator() {
|
|
1244
|
+
for (let i = this._offset; i < this.elements.length; i++) yield this.elements[i];
|
|
1000
1245
|
}
|
|
1001
1246
|
/**
|
|
1002
|
-
*
|
|
1003
|
-
* @
|
|
1004
|
-
* @
|
|
1247
|
+
* (Protected) Iterate elements from back to front.
|
|
1248
|
+
* @remarks Time O(N), Space O(1)
|
|
1249
|
+
* @returns Iterator of E.
|
|
1005
1250
|
*/
|
|
1006
|
-
|
|
1007
|
-
|
|
1251
|
+
*_getReverseIterator() {
|
|
1252
|
+
for (let i = this.length - 1; i >= 0; i--) {
|
|
1253
|
+
const cur = this.at(i);
|
|
1254
|
+
if (cur !== void 0) yield cur;
|
|
1255
|
+
}
|
|
1008
1256
|
}
|
|
1009
1257
|
/**
|
|
1010
|
-
*
|
|
1011
|
-
* @
|
|
1012
|
-
* @
|
|
1258
|
+
* (Protected) Create an empty instance of the same concrete class.
|
|
1259
|
+
* @remarks Time O(1), Space O(1)
|
|
1260
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1261
|
+
* @returns An empty like-kind queue instance.
|
|
1013
1262
|
*/
|
|
1014
|
-
|
|
1015
|
-
|
|
1263
|
+
_createInstance(options) {
|
|
1264
|
+
const Ctor = this.constructor;
|
|
1265
|
+
return new Ctor([], options);
|
|
1016
1266
|
}
|
|
1017
1267
|
/**
|
|
1018
|
-
*
|
|
1019
|
-
* @remarks Time O(
|
|
1268
|
+
* (Protected) Create a like-kind queue and seed it from an iterable.
|
|
1269
|
+
* @remarks Time O(N), Space O(N)
|
|
1270
|
+
* @template EM
|
|
1271
|
+
* @template RM
|
|
1272
|
+
* @param [elements] - Iterable used to seed the new queue.
|
|
1273
|
+
* @param [options] - Options forwarded to the constructor.
|
|
1274
|
+
* @returns A like-kind Queue instance.
|
|
1020
1275
|
*/
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
};
|
|
1025
|
-
|
|
1026
|
-
// src/common/index.ts
|
|
1027
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
1028
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
1029
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
1030
|
-
return DFSOperation2;
|
|
1031
|
-
})(DFSOperation || {});
|
|
1032
|
-
var Range = class {
|
|
1033
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
1034
|
-
this.low = low;
|
|
1035
|
-
this.high = high;
|
|
1036
|
-
this.includeLow = includeLow;
|
|
1037
|
-
this.includeHigh = includeHigh;
|
|
1038
|
-
}
|
|
1039
|
-
static {
|
|
1040
|
-
__name(this, "Range");
|
|
1041
|
-
}
|
|
1042
|
-
// Determine whether a key is within the range
|
|
1043
|
-
isInRange(key, comparator) {
|
|
1044
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
1045
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
1046
|
-
return lowCheck && highCheck;
|
|
1276
|
+
_createLike(elements = [], options) {
|
|
1277
|
+
const Ctor = this.constructor;
|
|
1278
|
+
return new Ctor(elements, options);
|
|
1047
1279
|
}
|
|
1048
1280
|
};
|
|
1049
1281
|
|
|
@@ -1185,7 +1417,7 @@ var BinaryTreeNode = class {
|
|
|
1185
1417
|
return "MAL_NODE";
|
|
1186
1418
|
}
|
|
1187
1419
|
};
|
|
1188
|
-
var BinaryTree = class extends IterableEntryBase {
|
|
1420
|
+
var BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
1189
1421
|
static {
|
|
1190
1422
|
__name(this, "BinaryTree");
|
|
1191
1423
|
}
|
|
@@ -1205,7 +1437,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1205
1437
|
if (isMapMode !== void 0) this._isMapMode = isMapMode;
|
|
1206
1438
|
if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
|
|
1207
1439
|
if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
|
|
1208
|
-
else if (toEntryFn) throw TypeError("toEntryFn
|
|
1440
|
+
else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
|
|
1209
1441
|
}
|
|
1210
1442
|
if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
|
|
1211
1443
|
}
|
|
@@ -1420,30 +1652,78 @@ var BinaryTree = class 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 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 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 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 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 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
|
if (this._isMapMode) {
|
|
1669
2031
|
const key = this._extractKey(keyNodeEntryOrPredicate);
|
|
@@ -1683,19 +2045,45 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1683
2045
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType).length > 0;
|
|
1684
2046
|
}
|
|
1685
2047
|
/**
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
2048
|
+
* Clears the tree of all nodes and values.
|
|
2049
|
+
* @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
|
|
2050
|
+
|
|
2051
|
+
|
|
2052
|
+
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
|
|
2056
|
+
|
|
2057
|
+
|
|
2058
|
+
|
|
2059
|
+
* @example
|
|
2060
|
+
* // Remove all nodes
|
|
2061
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2062
|
+
* tree.clear();
|
|
2063
|
+
* console.log(tree.isEmpty()); // true;
|
|
2064
|
+
*/
|
|
1689
2065
|
clear() {
|
|
1690
2066
|
this._clearNodes();
|
|
1691
2067
|
if (this._isMapMode) this._clearValues();
|
|
1692
2068
|
}
|
|
1693
2069
|
/**
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
2070
|
+
* Checks if the tree is empty.
|
|
2071
|
+
* @remarks Time O(1), Space O(1)
|
|
2072
|
+
*
|
|
2073
|
+
* @returns True if the tree has no nodes, false otherwise.
|
|
2074
|
+
|
|
2075
|
+
|
|
2076
|
+
|
|
2077
|
+
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
* @example
|
|
2084
|
+
* // Check empty
|
|
2085
|
+
* console.log(new BinaryTree().isEmpty()); // true;
|
|
2086
|
+
*/
|
|
1699
2087
|
isEmpty() {
|
|
1700
2088
|
return this._size === 0;
|
|
1701
2089
|
}
|
|
@@ -1710,13 +2098,27 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1710
2098
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
1711
2099
|
}
|
|
1712
2100
|
/**
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
2101
|
+
* Checks if the tree is a valid Binary Search Tree (BST).
|
|
2102
|
+
* @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).
|
|
2103
|
+
*
|
|
2104
|
+
* @param [startNode=this._root] - The node to start checking from.
|
|
2105
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2106
|
+
* @returns True if it's a valid BST, false otherwise.
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
|
|
2110
|
+
|
|
2111
|
+
|
|
2112
|
+
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
|
|
2116
|
+
* @example
|
|
2117
|
+
* // Check BST property
|
|
2118
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2119
|
+
* // BinaryTree doesn't guarantee BST order
|
|
2120
|
+
* console.log(typeof tree.isBST()); // 'boolean';
|
|
2121
|
+
*/
|
|
1720
2122
|
isBST(startNode = this._root, iterationType = this.iterationType) {
|
|
1721
2123
|
const startNodeSired = this.ensureNode(startNode);
|
|
1722
2124
|
if (!startNodeSired) return true;
|
|
@@ -1754,13 +2156,29 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1754
2156
|
}
|
|
1755
2157
|
}
|
|
1756
2158
|
/**
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
2159
|
+
* Gets the depth of a node (distance from `startNode`).
|
|
2160
|
+
* @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
|
|
2161
|
+
*
|
|
2162
|
+
* @param dist - The node to find the depth of.
|
|
2163
|
+
* @param [startNode=this._root] - The node to measure depth from (defaults to root).
|
|
2164
|
+
* @returns The depth (0 if `dist` is `startNode`).
|
|
2165
|
+
|
|
2166
|
+
|
|
2167
|
+
|
|
2168
|
+
|
|
2169
|
+
|
|
2170
|
+
|
|
2171
|
+
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
* @example
|
|
2177
|
+
* // Get depth of a node
|
|
2178
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2179
|
+
* const node = tree.getNode(4);
|
|
2180
|
+
* console.log(tree.getDepth(node!)); // 2;
|
|
2181
|
+
*/
|
|
1764
2182
|
getDepth(dist, startNode = this._root) {
|
|
1765
2183
|
let distEnsured = this.ensureNode(dist);
|
|
1766
2184
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
@@ -1775,13 +2193,28 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
1775
2193
|
return depth;
|
|
1776
2194
|
}
|
|
1777
2195
|
/**
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
2196
|
+
* Gets the maximum height of the tree (longest path from startNode to a leaf).
|
|
2197
|
+
* @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).
|
|
2198
|
+
*
|
|
2199
|
+
* @param [startNode=this._root] - The node to start measuring from.
|
|
2200
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2201
|
+
* @returns The height ( -1 for an empty tree, 0 for a single-node tree).
|
|
2202
|
+
|
|
2203
|
+
|
|
2204
|
+
|
|
2205
|
+
|
|
2206
|
+
|
|
2207
|
+
|
|
2208
|
+
|
|
2209
|
+
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
|
|
2213
|
+
* @example
|
|
2214
|
+
* // Get tree height
|
|
2215
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2216
|
+
* console.log(tree.getHeight()); // 2;
|
|
2217
|
+
*/
|
|
1785
2218
|
getHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
1786
2219
|
startNode = this.ensureNode(startNode);
|
|
1787
2220
|
if (!this.isRealNode(startNode)) return -1;
|
|
@@ -2043,7 +2476,7 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2043
2476
|
}
|
|
2044
2477
|
/**
|
|
2045
2478
|
* Finds all leaf nodes in the tree.
|
|
2046
|
-
* @remarks Time O(N), visits every node. Space O(H) for recursive
|
|
2479
|
+
* @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
|
|
2047
2480
|
*
|
|
2048
2481
|
* @template C - The type of the callback function.
|
|
2049
2482
|
* @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
|
|
@@ -2066,15 +2499,15 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2066
2499
|
}, "dfs");
|
|
2067
2500
|
dfs(startNode);
|
|
2068
2501
|
} else {
|
|
2069
|
-
const
|
|
2070
|
-
while (
|
|
2071
|
-
const cur =
|
|
2502
|
+
const stack = [startNode];
|
|
2503
|
+
while (stack.length > 0) {
|
|
2504
|
+
const cur = stack.pop();
|
|
2072
2505
|
if (this.isRealNode(cur)) {
|
|
2073
2506
|
if (this.isLeaf(cur)) {
|
|
2074
2507
|
leaves.push(callback(cur));
|
|
2075
2508
|
}
|
|
2076
|
-
if (this.isRealNode(cur.
|
|
2077
|
-
if (this.isRealNode(cur.
|
|
2509
|
+
if (this.isRealNode(cur.right)) stack.push(cur.right);
|
|
2510
|
+
if (this.isRealNode(cur.left)) stack.push(cur.left);
|
|
2078
2511
|
}
|
|
2079
2512
|
}
|
|
2080
2513
|
}
|
|
@@ -2217,24 +2650,53 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2217
2650
|
return ans;
|
|
2218
2651
|
}
|
|
2219
2652
|
/**
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2653
|
+
* Clones the tree.
|
|
2654
|
+
* @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.
|
|
2655
|
+
*
|
|
2656
|
+
* @returns A new, cloned instance of the tree.
|
|
2657
|
+
|
|
2658
|
+
|
|
2659
|
+
|
|
2660
|
+
|
|
2661
|
+
|
|
2662
|
+
|
|
2663
|
+
|
|
2664
|
+
|
|
2665
|
+
|
|
2666
|
+
* @example
|
|
2667
|
+
* // Deep copy
|
|
2668
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2669
|
+
* const copy = tree.clone();
|
|
2670
|
+
* copy.delete(1);
|
|
2671
|
+
* console.log(tree.has(1)); // true;
|
|
2672
|
+
*/
|
|
2225
2673
|
clone() {
|
|
2226
2674
|
const out = this._createInstance();
|
|
2227
2675
|
this._clone(out);
|
|
2228
2676
|
return out;
|
|
2229
2677
|
}
|
|
2230
2678
|
/**
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2679
|
+
* Creates a new tree containing only the entries that satisfy the predicate.
|
|
2680
|
+
* @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.
|
|
2681
|
+
*
|
|
2682
|
+
* @param predicate - A function to test each [key, value] pair.
|
|
2683
|
+
* @param [thisArg] - `this` context for the predicate.
|
|
2684
|
+
* @returns A new, filtered tree.
|
|
2685
|
+
|
|
2686
|
+
|
|
2687
|
+
|
|
2688
|
+
|
|
2689
|
+
|
|
2690
|
+
|
|
2691
|
+
|
|
2692
|
+
|
|
2693
|
+
|
|
2694
|
+
* @example
|
|
2695
|
+
* // Filter nodes by condition
|
|
2696
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4]);
|
|
2697
|
+
* const result = tree.filter((_, key) => key > 2);
|
|
2698
|
+
* console.log(result.size); // 2;
|
|
2699
|
+
*/
|
|
2238
2700
|
filter(predicate, thisArg) {
|
|
2239
2701
|
const out = this._createInstance();
|
|
2240
2702
|
let i = 0;
|
|
@@ -2242,17 +2704,31 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2242
2704
|
return out;
|
|
2243
2705
|
}
|
|
2244
2706
|
/**
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2707
|
+
* Creates a new tree by mapping each [key, value] pair to a new entry.
|
|
2708
|
+
* @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.
|
|
2709
|
+
*
|
|
2710
|
+
* @template MK - New key type.
|
|
2711
|
+
* @template MV - New value type.
|
|
2712
|
+
* @template MR - New raw type.
|
|
2713
|
+
* @param cb - A function to map each [key, value] pair.
|
|
2714
|
+
* @param [options] - Options for the new tree.
|
|
2715
|
+
* @param [thisArg] - `this` context for the callback.
|
|
2716
|
+
* @returns A new, mapped tree.
|
|
2717
|
+
|
|
2718
|
+
|
|
2719
|
+
|
|
2720
|
+
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
* @example
|
|
2727
|
+
* // Transform to new tree
|
|
2728
|
+
* const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
|
|
2729
|
+
* const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
|
|
2730
|
+
* console.log([...mapped.values()]); // contains 11;
|
|
2731
|
+
*/
|
|
2256
2732
|
map(cb, options, thisArg) {
|
|
2257
2733
|
const out = this._createLike([], options);
|
|
2258
2734
|
let i = 0;
|
|
@@ -2290,12 +2766,25 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2290
2766
|
return output;
|
|
2291
2767
|
}
|
|
2292
2768
|
/**
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2769
|
+
* Prints a visual representation of the tree to the console.
|
|
2770
|
+
* @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
|
|
2771
|
+
*
|
|
2772
|
+
* @param [options] - Options to control the output.
|
|
2773
|
+
* @param [startNode=this._root] - The node to start printing from.
|
|
2774
|
+
|
|
2775
|
+
|
|
2776
|
+
|
|
2777
|
+
|
|
2778
|
+
|
|
2779
|
+
|
|
2780
|
+
|
|
2781
|
+
|
|
2782
|
+
|
|
2783
|
+
* @example
|
|
2784
|
+
* // Display tree
|
|
2785
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2786
|
+
* expect(() => tree.print()).not.toThrow();
|
|
2787
|
+
*/
|
|
2299
2788
|
print(options, startNode = this._root) {
|
|
2300
2789
|
console.log(this.toVisual(startNode, options));
|
|
2301
2790
|
}
|
|
@@ -2534,44 +3023,99 @@ var BinaryTree = class extends IterableEntryBase {
|
|
|
2534
3023
|
* @returns Layout information for this subtree.
|
|
2535
3024
|
*/
|
|
2536
3025
|
_displayAux(node, options) {
|
|
2537
|
-
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
2538
3026
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
const
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
3027
|
+
const newFrame = /* @__PURE__ */ __name((n) => ({
|
|
3028
|
+
node: n,
|
|
3029
|
+
stage: 0,
|
|
3030
|
+
leftLayout: emptyDisplayLayout,
|
|
3031
|
+
rightLayout: emptyDisplayLayout
|
|
3032
|
+
}), "newFrame");
|
|
3033
|
+
const stack = [newFrame(node)];
|
|
3034
|
+
let result = emptyDisplayLayout;
|
|
3035
|
+
const setChildResult = /* @__PURE__ */ __name((layout) => {
|
|
3036
|
+
if (stack.length === 0) {
|
|
3037
|
+
result = layout;
|
|
3038
|
+
return;
|
|
3039
|
+
}
|
|
3040
|
+
const parent = stack[stack.length - 1];
|
|
3041
|
+
if (parent.stage === 1) parent.leftLayout = layout;
|
|
3042
|
+
else parent.rightLayout = layout;
|
|
3043
|
+
}, "setChildResult");
|
|
3044
|
+
while (stack.length > 0) {
|
|
3045
|
+
const frame = stack[stack.length - 1];
|
|
3046
|
+
const cur = frame.node;
|
|
3047
|
+
if (frame.stage === 0) {
|
|
3048
|
+
if (this._isDisplayLeaf(cur, options)) {
|
|
3049
|
+
stack.pop();
|
|
3050
|
+
const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
|
|
3051
|
+
setChildResult(layout);
|
|
3052
|
+
continue;
|
|
3053
|
+
}
|
|
3054
|
+
frame.stage = 1;
|
|
3055
|
+
stack.push(newFrame(cur.left));
|
|
3056
|
+
} else if (frame.stage === 1) {
|
|
3057
|
+
frame.stage = 2;
|
|
3058
|
+
stack.push(newFrame(cur.right));
|
|
3059
|
+
} else {
|
|
3060
|
+
stack.pop();
|
|
3061
|
+
const line = this.isNIL(cur) ? "S" : String(cur.key);
|
|
3062
|
+
const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
|
|
3063
|
+
setChildResult(layout);
|
|
2567
3064
|
}
|
|
2568
|
-
return [
|
|
2569
|
-
mergedLines,
|
|
2570
|
-
leftWidth + width + rightWidth,
|
|
2571
|
-
Math.max(leftHeight, rightHeight) + 2,
|
|
2572
|
-
leftWidth + Math.floor(width / 2)
|
|
2573
|
-
];
|
|
2574
3065
|
}
|
|
3066
|
+
return result;
|
|
3067
|
+
}
|
|
3068
|
+
static _buildNodeDisplay(line, width, left, right) {
|
|
3069
|
+
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
3070
|
+
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
3071
|
+
const firstLine = " ".repeat(Math.max(0, leftMiddle + 1)) + "_".repeat(Math.max(0, leftWidth - leftMiddle - 1)) + line + "_".repeat(Math.max(0, rightMiddle)) + " ".repeat(Math.max(0, rightWidth - rightMiddle));
|
|
3072
|
+
const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
|
|
3073
|
+
const mergedLines = [firstLine, secondLine];
|
|
3074
|
+
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
3075
|
+
const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
|
|
3076
|
+
const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
|
|
3077
|
+
mergedLines.push(leftLine + " ".repeat(width) + rightLine);
|
|
3078
|
+
}
|
|
3079
|
+
return [
|
|
3080
|
+
mergedLines,
|
|
3081
|
+
leftWidth + width + rightWidth,
|
|
3082
|
+
Math.max(leftHeight, rightHeight) + 2,
|
|
3083
|
+
leftWidth + Math.floor(width / 2)
|
|
3084
|
+
];
|
|
3085
|
+
}
|
|
3086
|
+
/**
|
|
3087
|
+
* Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
|
|
3088
|
+
*/
|
|
3089
|
+
_isDisplayLeaf(node, options) {
|
|
3090
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3091
|
+
if (node === null && !isShowNull) return true;
|
|
3092
|
+
if (node === void 0 && !isShowUndefined) return true;
|
|
3093
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return true;
|
|
3094
|
+
if (node === null || node === void 0) return true;
|
|
3095
|
+
const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
|
|
3096
|
+
const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
|
|
3097
|
+
return !hasDisplayableLeft && !hasDisplayableRight;
|
|
3098
|
+
}
|
|
3099
|
+
_hasDisplayableChild(child, options) {
|
|
3100
|
+
if (child === null) return !!options.isShowNull;
|
|
3101
|
+
if (child === void 0) return !!options.isShowUndefined;
|
|
3102
|
+
if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
|
|
3103
|
+
return true;
|
|
3104
|
+
}
|
|
3105
|
+
/**
|
|
3106
|
+
* Resolve a display leaf node to its layout.
|
|
3107
|
+
*/
|
|
3108
|
+
_resolveDisplayLeaf(node, options, emptyDisplayLayout) {
|
|
3109
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
3110
|
+
if (node === null && !isShowNull) return emptyDisplayLayout;
|
|
3111
|
+
if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
|
|
3112
|
+
if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
|
|
3113
|
+
if (node !== null && node !== void 0) {
|
|
3114
|
+
const line2 = this.isNIL(node) ? "S" : String(node.key);
|
|
3115
|
+
return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
|
|
3116
|
+
}
|
|
3117
|
+
const line = node === void 0 ? "U" : "N";
|
|
3118
|
+
return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
|
|
2575
3119
|
}
|
|
2576
3120
|
/**
|
|
2577
3121
|
* (Protected) Swaps the key/value properties of two nodes.
|
|
@@ -2774,6 +3318,7 @@ var BSTNode = class {
|
|
|
2774
3318
|
*
|
|
2775
3319
|
* @returns The height.
|
|
2776
3320
|
*/
|
|
3321
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
2777
3322
|
get height() {
|
|
2778
3323
|
return this._height;
|
|
2779
3324
|
}
|
|
@@ -2783,6 +3328,7 @@ var BSTNode = class {
|
|
|
2783
3328
|
*
|
|
2784
3329
|
* @param value - The new height.
|
|
2785
3330
|
*/
|
|
3331
|
+
/* istanbul ignore next -- covered by AVLTree/RedBlackTree tests (subclass uses height) */
|
|
2786
3332
|
set height(value) {
|
|
2787
3333
|
this._height = value;
|
|
2788
3334
|
}
|
|
@@ -2793,6 +3339,7 @@ var BSTNode = class {
|
|
|
2793
3339
|
*
|
|
2794
3340
|
* @returns The node's color.
|
|
2795
3341
|
*/
|
|
3342
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
2796
3343
|
get color() {
|
|
2797
3344
|
return this._color;
|
|
2798
3345
|
}
|
|
@@ -2802,6 +3349,7 @@ var BSTNode = class {
|
|
|
2802
3349
|
*
|
|
2803
3350
|
* @param value - The new color.
|
|
2804
3351
|
*/
|
|
3352
|
+
/* istanbul ignore next -- covered by RedBlackTree tests (subclass uses color) */
|
|
2805
3353
|
set color(value) {
|
|
2806
3354
|
this._color = value;
|
|
2807
3355
|
}
|
|
@@ -2812,6 +3360,7 @@ var BSTNode = class {
|
|
|
2812
3360
|
*
|
|
2813
3361
|
* @returns The subtree node count.
|
|
2814
3362
|
*/
|
|
3363
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
2815
3364
|
get count() {
|
|
2816
3365
|
return this._count;
|
|
2817
3366
|
}
|
|
@@ -2821,6 +3370,7 @@ var BSTNode = class {
|
|
|
2821
3370
|
*
|
|
2822
3371
|
* @param value - The new count.
|
|
2823
3372
|
*/
|
|
3373
|
+
/* istanbul ignore next -- internal field used by subclasses */
|
|
2824
3374
|
set count(value) {
|
|
2825
3375
|
this._count = value;
|
|
2826
3376
|
}
|
|
@@ -2975,14 +3525,39 @@ var BST = class extends BinaryTree {
|
|
|
2975
3525
|
return super.listLevels(callback, startNode, iterationType, false);
|
|
2976
3526
|
}
|
|
2977
3527
|
/**
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
3528
|
+
* Gets the first node matching a predicate.
|
|
3529
|
+
* @remarks Time O(log N) if searching by key, O(N) if searching by predicate. Space O(log N) or O(N).
|
|
3530
|
+
*
|
|
3531
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
3532
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
3533
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
3534
|
+
* @returns The first matching node, or undefined if not found.
|
|
3535
|
+
|
|
3536
|
+
|
|
3537
|
+
|
|
3538
|
+
|
|
3539
|
+
|
|
3540
|
+
|
|
3541
|
+
|
|
3542
|
+
|
|
3543
|
+
|
|
3544
|
+
|
|
3545
|
+
|
|
3546
|
+
|
|
3547
|
+
|
|
3548
|
+
|
|
3549
|
+
|
|
3550
|
+
|
|
3551
|
+
|
|
3552
|
+
|
|
3553
|
+
|
|
3554
|
+
* @example
|
|
3555
|
+
* // Get node object by key
|
|
3556
|
+
* const bst = new BST<number, string>([[5, 'root'], [3, 'left'], [7, 'right']]);
|
|
3557
|
+
* const node = bst.getNode(3);
|
|
3558
|
+
* console.log(node?.key); // 3;
|
|
3559
|
+
* console.log(node?.value); // 'left';
|
|
3560
|
+
*/
|
|
2986
3561
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
2987
3562
|
if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === void 0) return void 0;
|
|
2988
3563
|
if (this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
@@ -3131,13 +3706,44 @@ var BST = class extends BinaryTree {
|
|
|
3131
3706
|
return this.search(searchRange, false, callback, startNode, iterationType);
|
|
3132
3707
|
}
|
|
3133
3708
|
/**
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3709
|
+
* Adds a new node to the BST based on key comparison.
|
|
3710
|
+
* @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
|
|
3711
|
+
*
|
|
3712
|
+
* @param keyNodeOrEntry - The key, node, or entry to set.
|
|
3713
|
+
* @param [value] - The value, if providing just a key.
|
|
3714
|
+
* @returns True if the addition was successful, false otherwise.
|
|
3715
|
+
|
|
3716
|
+
|
|
3717
|
+
|
|
3718
|
+
|
|
3719
|
+
|
|
3720
|
+
|
|
3721
|
+
|
|
3722
|
+
|
|
3723
|
+
|
|
3724
|
+
|
|
3725
|
+
|
|
3726
|
+
|
|
3727
|
+
|
|
3728
|
+
|
|
3729
|
+
|
|
3730
|
+
|
|
3731
|
+
|
|
3732
|
+
|
|
3733
|
+
|
|
3734
|
+
|
|
3735
|
+
|
|
3736
|
+
|
|
3737
|
+
|
|
3738
|
+
|
|
3739
|
+
|
|
3740
|
+
* @example
|
|
3741
|
+
* // Set a key-value pair
|
|
3742
|
+
* const bst = new BST<number, string>();
|
|
3743
|
+
* bst.set(1, 'one');
|
|
3744
|
+
* bst.set(2, 'two');
|
|
3745
|
+
* console.log(bst.get(1)); // 'one';
|
|
3746
|
+
*/
|
|
3141
3747
|
set(keyNodeOrEntry, value) {
|
|
3142
3748
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
3143
3749
|
if (newNode === void 0) return false;
|
|
@@ -3174,17 +3780,34 @@ var BST = class extends BinaryTree {
|
|
|
3174
3780
|
return false;
|
|
3175
3781
|
}
|
|
3176
3782
|
/**
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3783
|
+
* Adds multiple items to the tree.
|
|
3784
|
+
* @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced set).
|
|
3785
|
+
* If false, adds items one by one. Time O(N * H), which is O(N^2) worst-case.
|
|
3786
|
+
* Space O(N) for sorting and recursion/iteration stack.
|
|
3787
|
+
*
|
|
3788
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
3789
|
+
* @param [values] - An optional parallel iterable of values.
|
|
3790
|
+
* @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
|
|
3791
|
+
* @param [iterationType=this.iterationType] - The traversal method for balanced set (recursive or iterative).
|
|
3792
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
3793
|
+
|
|
3794
|
+
|
|
3795
|
+
|
|
3796
|
+
|
|
3797
|
+
|
|
3798
|
+
|
|
3799
|
+
|
|
3800
|
+
|
|
3801
|
+
|
|
3802
|
+
|
|
3803
|
+
|
|
3804
|
+
* @example
|
|
3805
|
+
* // Set multiple key-value pairs
|
|
3806
|
+
* const bst = new BST<number, string>();
|
|
3807
|
+
* bst.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
3808
|
+
* console.log(bst.size); // 3;
|
|
3809
|
+
* console.log(bst.get(2)); // 'b';
|
|
3810
|
+
*/
|
|
3188
3811
|
setMany(keysNodesEntriesOrRaws, values, isBalanceAdd = true, iterationType = this.iterationType) {
|
|
3189
3812
|
const inserted = [];
|
|
3190
3813
|
const valuesIterator = values?.[Symbol.iterator]();
|
|
@@ -3427,12 +4050,29 @@ var BST = class extends BinaryTree {
|
|
|
3427
4050
|
}
|
|
3428
4051
|
}
|
|
3429
4052
|
/**
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
4053
|
+
* Rebuilds the tree to be perfectly balanced.
|
|
4054
|
+
* @remarks Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
|
|
4055
|
+
*
|
|
4056
|
+
* @param [iterationType=this.iterationType] - The traversal method for the initial node export.
|
|
4057
|
+
* @returns True if successful, false if the tree was empty.
|
|
4058
|
+
|
|
4059
|
+
|
|
4060
|
+
|
|
4061
|
+
|
|
4062
|
+
|
|
4063
|
+
|
|
4064
|
+
|
|
4065
|
+
|
|
4066
|
+
|
|
4067
|
+
* @example
|
|
4068
|
+
* // Rebalance the tree
|
|
4069
|
+
* const bst = new BST<number>();
|
|
4070
|
+
* // Insert in sorted order (worst case for BST)
|
|
4071
|
+
* for (let i = 1; i <= 7; i++) bst.add(i);
|
|
4072
|
+
* console.log(bst.isAVLBalanced()); // false;
|
|
4073
|
+
* bst.perfectlyBalance();
|
|
4074
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
4075
|
+
*/
|
|
3436
4076
|
perfectlyBalance(iterationType = this.iterationType) {
|
|
3437
4077
|
const nodes = this.dfs((node) => node, "IN", false, this._root, iterationType);
|
|
3438
4078
|
const n = nodes.length;
|
|
@@ -3455,12 +4095,25 @@ var BST = class extends BinaryTree {
|
|
|
3455
4095
|
return true;
|
|
3456
4096
|
}
|
|
3457
4097
|
/**
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
4098
|
+
* Checks if the tree meets the AVL balance condition (height difference <= 1).
|
|
4099
|
+
* @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.
|
|
4100
|
+
*
|
|
4101
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
4102
|
+
* @returns True if the tree is AVL balanced, false otherwise.
|
|
4103
|
+
|
|
4104
|
+
|
|
4105
|
+
|
|
4106
|
+
|
|
4107
|
+
|
|
4108
|
+
|
|
4109
|
+
|
|
4110
|
+
|
|
4111
|
+
|
|
4112
|
+
* @example
|
|
4113
|
+
* // Check if tree is height-balanced
|
|
4114
|
+
* const bst = new BST<number>([3, 1, 5, 2, 4]);
|
|
4115
|
+
* console.log(bst.isAVLBalanced()); // true;
|
|
4116
|
+
*/
|
|
3464
4117
|
isAVLBalanced(iterationType = this.iterationType) {
|
|
3465
4118
|
if (!this._root) return true;
|
|
3466
4119
|
let balanced = true;
|
|
@@ -3500,18 +4153,42 @@ var BST = class extends BinaryTree {
|
|
|
3500
4153
|
return balanced;
|
|
3501
4154
|
}
|
|
3502
4155
|
/**
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
4156
|
+
* Creates a new BST by mapping each [key, value] pair to a new entry.
|
|
4157
|
+
* @remarks Time O(N * H), where N is nodes in this tree, and H is height of the new tree during insertion.
|
|
4158
|
+
* Space O(N) for the new tree.
|
|
4159
|
+
*
|
|
4160
|
+
* @template MK - New key type.
|
|
4161
|
+
* @template MV - New value type.
|
|
4162
|
+
* @template MR - New raw type.
|
|
4163
|
+
* @param callback - A function to map each [key, value] pair.
|
|
4164
|
+
* @param [options] - Options for the new BST.
|
|
4165
|
+
* @param [thisArg] - `this` context for the callback.
|
|
4166
|
+
* @returns A new, mapped BST.
|
|
4167
|
+
|
|
4168
|
+
|
|
4169
|
+
|
|
4170
|
+
|
|
4171
|
+
|
|
4172
|
+
|
|
4173
|
+
|
|
4174
|
+
|
|
4175
|
+
|
|
4176
|
+
|
|
4177
|
+
|
|
4178
|
+
|
|
4179
|
+
|
|
4180
|
+
|
|
4181
|
+
|
|
4182
|
+
|
|
4183
|
+
|
|
4184
|
+
|
|
4185
|
+
|
|
4186
|
+
* @example
|
|
4187
|
+
* // Transform to new tree
|
|
4188
|
+
* const bst = new BST<number, number>([[1, 10], [2, 20], [3, 30]]);
|
|
4189
|
+
* const doubled = bst.map((value, key) => [key, (value ?? 0) * 2] as [number, number]);
|
|
4190
|
+
* console.log([...doubled.values()]); // [20, 40, 60];
|
|
4191
|
+
*/
|
|
3515
4192
|
map(callback, options, thisArg) {
|
|
3516
4193
|
const out = this._createLike([], options);
|
|
3517
4194
|
let index = 0;
|
|
@@ -3577,9 +4254,15 @@ var BST = class extends BinaryTree {
|
|
|
3577
4254
|
if (a < b) return -1;
|
|
3578
4255
|
return 0;
|
|
3579
4256
|
}
|
|
4257
|
+
if (a instanceof Date && b instanceof Date) {
|
|
4258
|
+
const ta = a.getTime();
|
|
4259
|
+
const tb = b.getTime();
|
|
4260
|
+
if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
|
|
4261
|
+
return ta > tb ? 1 : ta < tb ? -1 : 0;
|
|
4262
|
+
}
|
|
3580
4263
|
if (typeof a === "object" || typeof b === "object") {
|
|
3581
|
-
throw TypeError(
|
|
3582
|
-
|
|
4264
|
+
throw new TypeError(
|
|
4265
|
+
ERR.comparatorRequired("BST")
|
|
3583
4266
|
);
|
|
3584
4267
|
}
|
|
3585
4268
|
return 0;
|
|
@@ -3994,6 +4677,6 @@ var BST = class extends BinaryTree {
|
|
|
3994
4677
|
* @license MIT License
|
|
3995
4678
|
*/
|
|
3996
4679
|
|
|
3997
|
-
export { BST, BSTNode, BinaryTree, BinaryTreeNode, DFSOperation, Range };
|
|
4680
|
+
export { BST, BSTNode, BinaryTree, BinaryTreeNode, DFSOperation, ERR, Range };
|
|
3998
4681
|
//# sourceMappingURL=index.mjs.map
|
|
3999
4682
|
//# sourceMappingURL=index.mjs.map
|