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