binary-tree-typed 2.4.5 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -84
- package/dist/cjs/index.cjs +867 -404
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +864 -401
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +867 -404
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +864 -401
- package/dist/esm-legacy/index.mjs.map +1 -1
- 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 +429 -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 +212 -32
- 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/directed-graph.d.ts +219 -47
- package/dist/types/data-structures/graph/map-graph.d.ts +59 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +204 -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 +272 -65
- 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/umd/binary-tree-typed.js +860 -397
- package/dist/umd/binary-tree-typed.js.map +1 -1
- package/dist/umd/binary-tree-typed.min.js +2 -2
- package/dist/umd/binary-tree-typed.min.js.map +1 -1
- package/package.json +2 -2
- package/src/data-structures/base/iterable-element-base.ts +4 -5
- package/src/data-structures/binary-tree/avl-tree.ts +134 -51
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +302 -247
- package/src/data-structures/binary-tree/binary-tree.ts +429 -79
- package/src/data-structures/binary-tree/bst.ts +335 -34
- package/src/data-structures/binary-tree/red-black-tree.ts +290 -97
- package/src/data-structures/binary-tree/segment-tree.ts +372 -248
- package/src/data-structures/binary-tree/tree-map.ts +1284 -6
- package/src/data-structures/binary-tree/tree-multi-map.ts +1094 -211
- package/src/data-structures/binary-tree/tree-multi-set.ts +858 -65
- package/src/data-structures/binary-tree/tree-set.ts +1136 -9
- package/src/data-structures/graph/directed-graph.ts +219 -47
- package/src/data-structures/graph/map-graph.ts +59 -1
- package/src/data-structures/graph/undirected-graph.ts +204 -59
- package/src/data-structures/hash/hash-map.ts +230 -77
- package/src/data-structures/heap/heap.ts +287 -99
- package/src/data-structures/heap/max-heap.ts +46 -0
- 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 +416 -12
- package/src/data-structures/priority-queue/max-priority-queue.ts +57 -0
- 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 +272 -65
- 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 +213 -43
- 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
|
@@ -59,54 +59,6 @@ function makeTrampoline(fn) {
|
|
|
59
59
|
}
|
|
60
60
|
__name(makeTrampoline, "makeTrampoline");
|
|
61
61
|
|
|
62
|
-
// src/common/error.ts
|
|
63
|
-
var ERR = {
|
|
64
|
-
// Range / index
|
|
65
|
-
indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
|
|
66
|
-
invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
|
|
67
|
-
// Type / argument
|
|
68
|
-
invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
|
|
69
|
-
comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
|
|
70
|
-
invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
|
|
71
|
-
notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
|
|
72
|
-
invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
|
|
73
|
-
invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
|
|
74
|
-
invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
|
|
75
|
-
reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
|
|
76
|
-
callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
|
|
77
|
-
// State / operation
|
|
78
|
-
invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
|
|
79
|
-
// Matrix
|
|
80
|
-
matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
|
|
81
|
-
matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
|
|
82
|
-
matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
|
|
83
|
-
matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
|
|
84
|
-
matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// src/common/index.ts
|
|
88
|
-
var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
|
|
89
|
-
DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
|
|
90
|
-
DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
|
|
91
|
-
return DFSOperation2;
|
|
92
|
-
})(DFSOperation || {});
|
|
93
|
-
var _Range = class _Range {
|
|
94
|
-
constructor(low, high, includeLow = true, includeHigh = true) {
|
|
95
|
-
this.low = low;
|
|
96
|
-
this.high = high;
|
|
97
|
-
this.includeLow = includeLow;
|
|
98
|
-
this.includeHigh = includeHigh;
|
|
99
|
-
}
|
|
100
|
-
// Determine whether a key is within the range
|
|
101
|
-
isInRange(key, comparator) {
|
|
102
|
-
const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
|
|
103
|
-
const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
|
|
104
|
-
return lowCheck && highCheck;
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
__name(_Range, "Range");
|
|
108
|
-
var Range = _Range;
|
|
109
|
-
|
|
110
62
|
// src/data-structures/base/iterable-element-base.ts
|
|
111
63
|
var _IterableElementBase = class _IterableElementBase {
|
|
112
64
|
/**
|
|
@@ -129,7 +81,7 @@ var _IterableElementBase = class _IterableElementBase {
|
|
|
129
81
|
if (options) {
|
|
130
82
|
const { toElementFn } = options;
|
|
131
83
|
if (typeof toElementFn === "function") this._toElementFn = toElementFn;
|
|
132
|
-
else if (toElementFn) throw new TypeError(
|
|
84
|
+
else if (toElementFn) throw new TypeError("toElementFn must be a function type");
|
|
133
85
|
}
|
|
134
86
|
}
|
|
135
87
|
/**
|
|
@@ -285,7 +237,7 @@ var _IterableElementBase = class _IterableElementBase {
|
|
|
285
237
|
acc = initialValue;
|
|
286
238
|
} else {
|
|
287
239
|
const first = iter.next();
|
|
288
|
-
if (first.done) throw new TypeError(
|
|
240
|
+
if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
|
|
289
241
|
acc = first.value;
|
|
290
242
|
index = 1;
|
|
291
243
|
}
|
|
@@ -521,6 +473,235 @@ var _LinearBase = class _LinearBase extends IterableElementBase {
|
|
|
521
473
|
__name(_LinearBase, "LinearBase");
|
|
522
474
|
var LinearBase = _LinearBase;
|
|
523
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 _Range {
|
|
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
|
+
// 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
|
+
__name(_Range, "Range");
|
|
522
|
+
var Range = _Range;
|
|
523
|
+
|
|
524
|
+
// src/data-structures/base/iterable-entry-base.ts
|
|
525
|
+
var _IterableEntryBase = class _IterableEntryBase {
|
|
526
|
+
/**
|
|
527
|
+
* Default iterator yielding `[key, value]` entries.
|
|
528
|
+
* @returns Iterator of `[K, V]`.
|
|
529
|
+
* @remarks Time O(n) to iterate, Space O(1)
|
|
530
|
+
*/
|
|
531
|
+
*[Symbol.iterator](...args) {
|
|
532
|
+
yield* this._getIterator(...args);
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
536
|
+
* @returns Iterator of `[K, V | undefined]`.
|
|
537
|
+
* @remarks Time O(n), Space O(1)
|
|
538
|
+
*/
|
|
539
|
+
*entries() {
|
|
540
|
+
for (const item of this) {
|
|
541
|
+
yield item;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Iterate over keys only.
|
|
546
|
+
* @returns Iterator of keys.
|
|
547
|
+
* @remarks Time O(n), Space O(1)
|
|
548
|
+
*/
|
|
549
|
+
*keys() {
|
|
550
|
+
for (const item of this) {
|
|
551
|
+
yield item[0];
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Iterate over values only.
|
|
556
|
+
* @returns Iterator of values.
|
|
557
|
+
* @remarks Time O(n), Space O(1)
|
|
558
|
+
*/
|
|
559
|
+
*values() {
|
|
560
|
+
for (const item of this) {
|
|
561
|
+
yield item[1];
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Test whether all entries satisfy the predicate.
|
|
566
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
567
|
+
* @param thisArg - Optional `this` for callback.
|
|
568
|
+
* @returns `true` if all pass; otherwise `false`.
|
|
569
|
+
* @remarks Time O(n), Space O(1)
|
|
570
|
+
*/
|
|
571
|
+
every(predicate, thisArg) {
|
|
572
|
+
let index = 0;
|
|
573
|
+
for (const item of this) {
|
|
574
|
+
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Test whether any entry satisfies the predicate.
|
|
582
|
+
* @param predicate - `(key, value, index, self) => boolean`.
|
|
583
|
+
* @param thisArg - Optional `this` for callback.
|
|
584
|
+
* @returns `true` if any passes; otherwise `false`.
|
|
585
|
+
* @remarks Time O(n), Space O(1)
|
|
586
|
+
*/
|
|
587
|
+
some(predicate, thisArg) {
|
|
588
|
+
let index = 0;
|
|
589
|
+
for (const item of this) {
|
|
590
|
+
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
591
|
+
return true;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return false;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Visit each entry, left-to-right.
|
|
598
|
+
* @param callbackfn - `(key, value, index, self) => void`.
|
|
599
|
+
* @param thisArg - Optional `this` for callback.
|
|
600
|
+
* @remarks Time O(n), Space O(1)
|
|
601
|
+
*/
|
|
602
|
+
forEach(callbackfn, thisArg) {
|
|
603
|
+
let index = 0;
|
|
604
|
+
for (const item of this) {
|
|
605
|
+
const [key, value] = item;
|
|
606
|
+
callbackfn.call(thisArg, value, key, index++, this);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Find the first entry that matches a predicate.
|
|
611
|
+
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
612
|
+
* @param thisArg - Optional `this` for callback.
|
|
613
|
+
* @returns Matching `[key, value]` or `undefined`.
|
|
614
|
+
* @remarks Time O(n), Space O(1)
|
|
615
|
+
*/
|
|
616
|
+
find(callbackfn, thisArg) {
|
|
617
|
+
let index = 0;
|
|
618
|
+
for (const item of this) {
|
|
619
|
+
const [key, value] = item;
|
|
620
|
+
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
621
|
+
}
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Whether the given key exists.
|
|
626
|
+
* @param key - Key to test.
|
|
627
|
+
* @returns `true` if found; otherwise `false`.
|
|
628
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
629
|
+
*/
|
|
630
|
+
has(key) {
|
|
631
|
+
for (const item of this) {
|
|
632
|
+
const [itemKey] = item;
|
|
633
|
+
if (itemKey === key) return true;
|
|
634
|
+
}
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Whether there exists an entry with the given value.
|
|
639
|
+
* @param value - Value to test.
|
|
640
|
+
* @returns `true` if found; otherwise `false`.
|
|
641
|
+
* @remarks Time O(n), Space O(1)
|
|
642
|
+
*/
|
|
643
|
+
hasValue(value) {
|
|
644
|
+
for (const [, elementValue] of this) {
|
|
645
|
+
if (elementValue === value) return true;
|
|
646
|
+
}
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Get the value under a key.
|
|
651
|
+
* @param key - Key to look up.
|
|
652
|
+
* @returns Value or `undefined`.
|
|
653
|
+
* @remarks Time O(n) generic, Space O(1)
|
|
654
|
+
*/
|
|
655
|
+
get(key) {
|
|
656
|
+
for (const item of this) {
|
|
657
|
+
const [itemKey, value] = item;
|
|
658
|
+
if (itemKey === key) return value;
|
|
659
|
+
}
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Reduce entries into a single accumulator.
|
|
664
|
+
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
665
|
+
* @param initialValue - Initial accumulator.
|
|
666
|
+
* @returns Final accumulator.
|
|
667
|
+
* @remarks Time O(n), Space O(1)
|
|
668
|
+
*/
|
|
669
|
+
reduce(callbackfn, initialValue) {
|
|
670
|
+
let accumulator = initialValue;
|
|
671
|
+
let index = 0;
|
|
672
|
+
for (const item of this) {
|
|
673
|
+
const [key, value] = item;
|
|
674
|
+
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
675
|
+
}
|
|
676
|
+
return accumulator;
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Converts data structure to `[key, value]` pairs.
|
|
680
|
+
* @returns Array of entries.
|
|
681
|
+
* @remarks Time O(n), Space O(n)
|
|
682
|
+
*/
|
|
683
|
+
toArray() {
|
|
684
|
+
return [...this];
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
688
|
+
* @returns Array of entries (default) or a string.
|
|
689
|
+
* @remarks Time O(n), Space O(n)
|
|
690
|
+
*/
|
|
691
|
+
toVisual() {
|
|
692
|
+
return [...this];
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Print a human-friendly representation to the console.
|
|
696
|
+
* @remarks Time O(n), Space O(n)
|
|
697
|
+
*/
|
|
698
|
+
print() {
|
|
699
|
+
console.log(this.toVisual());
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
__name(_IterableEntryBase, "IterableEntryBase");
|
|
703
|
+
var IterableEntryBase = _IterableEntryBase;
|
|
704
|
+
|
|
524
705
|
// src/data-structures/queue/queue.ts
|
|
525
706
|
var _Queue = class _Queue extends LinearBase {
|
|
526
707
|
/**
|
|
@@ -575,18 +756,52 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
575
756
|
this._autoCompactRatio = value;
|
|
576
757
|
}
|
|
577
758
|
/**
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
759
|
+
* Get the number of elements currently in the queue.
|
|
760
|
+
* @remarks Time O(1), Space O(1)
|
|
761
|
+
* @returns Current length.
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
* @example
|
|
774
|
+
* // Track queue length
|
|
775
|
+
* const q = new Queue<number>();
|
|
776
|
+
* console.log(q.length); // 0;
|
|
777
|
+
* q.push(1);
|
|
778
|
+
* q.push(2);
|
|
779
|
+
* console.log(q.length); // 2;
|
|
780
|
+
*/
|
|
582
781
|
get length() {
|
|
583
782
|
return this.elements.length - this._offset;
|
|
584
783
|
}
|
|
585
784
|
/**
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
785
|
+
* Get the first element (front) without removing it.
|
|
786
|
+
* @remarks Time O(1), Space O(1)
|
|
787
|
+
* @returns Front element or undefined.
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
* @example
|
|
800
|
+
* // View the front element
|
|
801
|
+
* const q = new Queue<string>(['first', 'second', 'third']);
|
|
802
|
+
* console.log(q.first); // 'first';
|
|
803
|
+
* console.log(q.length); // 3;
|
|
804
|
+
*/
|
|
590
805
|
get first() {
|
|
591
806
|
return this.length > 0 ? this.elements[this._offset] : void 0;
|
|
592
807
|
}
|
|
@@ -609,19 +824,69 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
609
824
|
return new _Queue(elements);
|
|
610
825
|
}
|
|
611
826
|
/**
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
827
|
+
* Check whether the queue is empty.
|
|
828
|
+
* @remarks Time O(1), Space O(1)
|
|
829
|
+
* @returns True if length is 0.
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
* @example
|
|
842
|
+
* // Queue for...of iteration and isEmpty check
|
|
843
|
+
* const queue = new Queue<string>(['A', 'B', 'C', 'D']);
|
|
844
|
+
*
|
|
845
|
+
* const elements: string[] = [];
|
|
846
|
+
* for (const item of queue) {
|
|
847
|
+
* elements.push(item);
|
|
848
|
+
* }
|
|
849
|
+
*
|
|
850
|
+
* // Verify all elements are iterated in order
|
|
851
|
+
* console.log(elements); // ['A', 'B', 'C', 'D'];
|
|
852
|
+
*
|
|
853
|
+
* // Process all elements
|
|
854
|
+
* while (queue.length > 0) {
|
|
855
|
+
* queue.shift();
|
|
856
|
+
* }
|
|
857
|
+
*
|
|
858
|
+
* console.log(queue.length); // 0;
|
|
859
|
+
*/
|
|
616
860
|
isEmpty() {
|
|
617
861
|
return this.length === 0;
|
|
618
862
|
}
|
|
619
863
|
/**
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
864
|
+
* Enqueue one element at the back.
|
|
865
|
+
* @remarks Time O(1), Space O(1)
|
|
866
|
+
* @param element - Element to enqueue.
|
|
867
|
+
* @returns True on success.
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
* @example
|
|
880
|
+
* // basic Queue creation and push operation
|
|
881
|
+
* // Create a simple Queue with initial values
|
|
882
|
+
* const queue = new Queue([1, 2, 3, 4, 5]);
|
|
883
|
+
*
|
|
884
|
+
* // Verify the queue maintains insertion order
|
|
885
|
+
* console.log([...queue]); // [1, 2, 3, 4, 5];
|
|
886
|
+
*
|
|
887
|
+
* // Check length
|
|
888
|
+
* console.log(queue.length); // 5;
|
|
889
|
+
*/
|
|
625
890
|
push(element) {
|
|
626
891
|
this.elements.push(element);
|
|
627
892
|
if (this._maxLen > 0 && this.length > this._maxLen) this.shift();
|
|
@@ -642,10 +907,35 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
642
907
|
return ans;
|
|
643
908
|
}
|
|
644
909
|
/**
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
910
|
+
* Dequeue one element from the front (amortized via offset).
|
|
911
|
+
* @remarks Time O(1) amortized, Space O(1)
|
|
912
|
+
* @returns Removed element or undefined.
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
* @example
|
|
925
|
+
* // Queue shift and peek operations
|
|
926
|
+
* const queue = new Queue<number>([10, 20, 30, 40]);
|
|
927
|
+
*
|
|
928
|
+
* // Peek at the front element without removing it
|
|
929
|
+
* console.log(queue.first); // 10;
|
|
930
|
+
*
|
|
931
|
+
* // Remove and get the first element (FIFO)
|
|
932
|
+
* const first = queue.shift();
|
|
933
|
+
* console.log(first); // 10;
|
|
934
|
+
*
|
|
935
|
+
* // Verify remaining elements and length decreased
|
|
936
|
+
* console.log([...queue]); // [20, 30, 40];
|
|
937
|
+
* console.log(queue.length); // 3;
|
|
938
|
+
*/
|
|
649
939
|
shift() {
|
|
650
940
|
if (this.length === 0) return void 0;
|
|
651
941
|
const first = this.first;
|
|
@@ -654,11 +944,24 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
654
944
|
return first;
|
|
655
945
|
}
|
|
656
946
|
/**
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
947
|
+
* Delete the first occurrence of a specific element.
|
|
948
|
+
* @remarks Time O(N), Space O(1)
|
|
949
|
+
* @param element - Element to remove (strict equality via Object.is).
|
|
950
|
+
* @returns True if an element was removed.
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
* @example
|
|
960
|
+
* // Remove specific element
|
|
961
|
+
* const q = new Queue<number>([1, 2, 3, 2]);
|
|
962
|
+
* q.delete(2);
|
|
963
|
+
* console.log(q.length); // 3;
|
|
964
|
+
*/
|
|
662
965
|
delete(element) {
|
|
663
966
|
for (let i = this._offset; i < this.elements.length; i++) {
|
|
664
967
|
if (Object.is(this.elements[i], element)) {
|
|
@@ -669,11 +972,24 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
669
972
|
return false;
|
|
670
973
|
}
|
|
671
974
|
/**
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
975
|
+
* Get the element at a given logical index.
|
|
976
|
+
* @remarks Time O(1), Space O(1)
|
|
977
|
+
* @param index - Zero-based index from the front.
|
|
978
|
+
* @returns Element or undefined.
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
* @example
|
|
988
|
+
* // Access element by index
|
|
989
|
+
* const q = new Queue<string>(['a', 'b', 'c']);
|
|
990
|
+
* console.log(q.at(0)); // 'a';
|
|
991
|
+
* console.log(q.at(2)); // 'c';
|
|
992
|
+
*/
|
|
677
993
|
at(index) {
|
|
678
994
|
if (index < 0 || index >= this.length) return void 0;
|
|
679
995
|
return this._elements[this._offset + index];
|
|
@@ -725,19 +1041,48 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
725
1041
|
return this;
|
|
726
1042
|
}
|
|
727
1043
|
/**
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
1044
|
+
* Remove all elements and reset offset.
|
|
1045
|
+
* @remarks Time O(1), Space O(1)
|
|
1046
|
+
* @returns void
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
* @example
|
|
1057
|
+
* // Remove all elements
|
|
1058
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1059
|
+
* q.clear();
|
|
1060
|
+
* console.log(q.length); // 0;
|
|
1061
|
+
*/
|
|
732
1062
|
clear() {
|
|
733
1063
|
this._elements = [];
|
|
734
1064
|
this._offset = 0;
|
|
735
1065
|
}
|
|
736
1066
|
/**
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
1067
|
+
* Compact storage by discarding consumed head elements.
|
|
1068
|
+
* @remarks Time O(N), Space O(N)
|
|
1069
|
+
* @returns True when compaction performed.
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
* @example
|
|
1079
|
+
* // Reclaim unused memory
|
|
1080
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1081
|
+
* q.shift();
|
|
1082
|
+
* q.shift();
|
|
1083
|
+
* q.compact();
|
|
1084
|
+
* console.log(q.length); // 3;
|
|
1085
|
+
*/
|
|
741
1086
|
compact() {
|
|
742
1087
|
this._elements = this.elements.slice(this._offset);
|
|
743
1088
|
this._offset = 0;
|
|
@@ -763,10 +1108,26 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
763
1108
|
return removed;
|
|
764
1109
|
}
|
|
765
1110
|
/**
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
1111
|
+
* Deep clone this queue and its parameters.
|
|
1112
|
+
* @remarks Time O(N), Space O(N)
|
|
1113
|
+
* @returns A new queue with the same content and options.
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
* @example
|
|
1124
|
+
* // Create independent copy
|
|
1125
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1126
|
+
* const copy = q.clone();
|
|
1127
|
+
* copy.shift();
|
|
1128
|
+
* console.log(q.length); // 3;
|
|
1129
|
+
* console.log(copy.length); // 2;
|
|
1130
|
+
*/
|
|
770
1131
|
clone() {
|
|
771
1132
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
772
1133
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -774,12 +1135,26 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
774
1135
|
return out;
|
|
775
1136
|
}
|
|
776
1137
|
/**
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
1138
|
+
* Filter elements into a new queue of the same class.
|
|
1139
|
+
* @remarks Time O(N), Space O(N)
|
|
1140
|
+
* @param predicate - Predicate (element, index, queue) → boolean to keep element.
|
|
1141
|
+
* @param [thisArg] - Value for `this` inside the predicate.
|
|
1142
|
+
* @returns A new queue with kept elements.
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
* @example
|
|
1153
|
+
* // Filter elements
|
|
1154
|
+
* const q = new Queue<number>([1, 2, 3, 4, 5]);
|
|
1155
|
+
* const evens = q.filter(x => x % 2 === 0);
|
|
1156
|
+
* console.log(evens.length); // 2;
|
|
1157
|
+
*/
|
|
783
1158
|
filter(predicate, thisArg) {
|
|
784
1159
|
const out = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });
|
|
785
1160
|
out._setAutoCompactRatio(this._autoCompactRatio);
|
|
@@ -791,15 +1166,28 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
791
1166
|
return out;
|
|
792
1167
|
}
|
|
793
1168
|
/**
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
1169
|
+
* Map each element to a new element in a possibly different-typed queue.
|
|
1170
|
+
* @remarks Time O(N), Space O(N)
|
|
1171
|
+
* @template EM
|
|
1172
|
+
* @template RM
|
|
1173
|
+
* @param callback - Mapping function (element, index, queue) → newElement.
|
|
1174
|
+
* @param [options] - Options for the output queue (e.g., toElementFn, maxLen, autoCompactRatio).
|
|
1175
|
+
* @param [thisArg] - Value for `this` inside the callback.
|
|
1176
|
+
* @returns A new Queue with mapped elements.
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
* @example
|
|
1186
|
+
* // Transform elements
|
|
1187
|
+
* const q = new Queue<number>([1, 2, 3]);
|
|
1188
|
+
* const doubled = q.map(x => x * 2);
|
|
1189
|
+
* console.log(doubled.toArray()); // [2, 4, 6];
|
|
1190
|
+
*/
|
|
803
1191
|
map(callback, options, thisArg) {
|
|
804
1192
|
var _a, _b;
|
|
805
1193
|
const out = new this.constructor([], {
|
|
@@ -890,187 +1278,6 @@ var _Queue = class _Queue extends LinearBase {
|
|
|
890
1278
|
__name(_Queue, "Queue");
|
|
891
1279
|
var Queue = _Queue;
|
|
892
1280
|
|
|
893
|
-
// src/data-structures/base/iterable-entry-base.ts
|
|
894
|
-
var _IterableEntryBase = class _IterableEntryBase {
|
|
895
|
-
/**
|
|
896
|
-
* Default iterator yielding `[key, value]` entries.
|
|
897
|
-
* @returns Iterator of `[K, V]`.
|
|
898
|
-
* @remarks Time O(n) to iterate, Space O(1)
|
|
899
|
-
*/
|
|
900
|
-
*[Symbol.iterator](...args) {
|
|
901
|
-
yield* this._getIterator(...args);
|
|
902
|
-
}
|
|
903
|
-
/**
|
|
904
|
-
* Iterate over `[key, value]` pairs (may yield `undefined` values).
|
|
905
|
-
* @returns Iterator of `[K, V | undefined]`.
|
|
906
|
-
* @remarks Time O(n), Space O(1)
|
|
907
|
-
*/
|
|
908
|
-
*entries() {
|
|
909
|
-
for (const item of this) {
|
|
910
|
-
yield item;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
/**
|
|
914
|
-
* Iterate over keys only.
|
|
915
|
-
* @returns Iterator of keys.
|
|
916
|
-
* @remarks Time O(n), Space O(1)
|
|
917
|
-
*/
|
|
918
|
-
*keys() {
|
|
919
|
-
for (const item of this) {
|
|
920
|
-
yield item[0];
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
/**
|
|
924
|
-
* Iterate over values only.
|
|
925
|
-
* @returns Iterator of values.
|
|
926
|
-
* @remarks Time O(n), Space O(1)
|
|
927
|
-
*/
|
|
928
|
-
*values() {
|
|
929
|
-
for (const item of this) {
|
|
930
|
-
yield item[1];
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
/**
|
|
934
|
-
* Test whether all entries satisfy the predicate.
|
|
935
|
-
* @param predicate - `(key, value, index, self) => boolean`.
|
|
936
|
-
* @param thisArg - Optional `this` for callback.
|
|
937
|
-
* @returns `true` if all pass; otherwise `false`.
|
|
938
|
-
* @remarks Time O(n), Space O(1)
|
|
939
|
-
*/
|
|
940
|
-
every(predicate, thisArg) {
|
|
941
|
-
let index = 0;
|
|
942
|
-
for (const item of this) {
|
|
943
|
-
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
944
|
-
return false;
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
return true;
|
|
948
|
-
}
|
|
949
|
-
/**
|
|
950
|
-
* Test whether any entry satisfies the predicate.
|
|
951
|
-
* @param predicate - `(key, value, index, self) => boolean`.
|
|
952
|
-
* @param thisArg - Optional `this` for callback.
|
|
953
|
-
* @returns `true` if any passes; otherwise `false`.
|
|
954
|
-
* @remarks Time O(n), Space O(1)
|
|
955
|
-
*/
|
|
956
|
-
some(predicate, thisArg) {
|
|
957
|
-
let index = 0;
|
|
958
|
-
for (const item of this) {
|
|
959
|
-
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
|
960
|
-
return true;
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
return false;
|
|
964
|
-
}
|
|
965
|
-
/**
|
|
966
|
-
* Visit each entry, left-to-right.
|
|
967
|
-
* @param callbackfn - `(key, value, index, self) => void`.
|
|
968
|
-
* @param thisArg - Optional `this` for callback.
|
|
969
|
-
* @remarks Time O(n), Space O(1)
|
|
970
|
-
*/
|
|
971
|
-
forEach(callbackfn, thisArg) {
|
|
972
|
-
let index = 0;
|
|
973
|
-
for (const item of this) {
|
|
974
|
-
const [key, value] = item;
|
|
975
|
-
callbackfn.call(thisArg, value, key, index++, this);
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
/**
|
|
979
|
-
* Find the first entry that matches a predicate.
|
|
980
|
-
* @param callbackfn - `(key, value, index, self) => boolean`.
|
|
981
|
-
* @param thisArg - Optional `this` for callback.
|
|
982
|
-
* @returns Matching `[key, value]` or `undefined`.
|
|
983
|
-
* @remarks Time O(n), Space O(1)
|
|
984
|
-
*/
|
|
985
|
-
find(callbackfn, thisArg) {
|
|
986
|
-
let index = 0;
|
|
987
|
-
for (const item of this) {
|
|
988
|
-
const [key, value] = item;
|
|
989
|
-
if (callbackfn.call(thisArg, value, key, index++, this)) return item;
|
|
990
|
-
}
|
|
991
|
-
return;
|
|
992
|
-
}
|
|
993
|
-
/**
|
|
994
|
-
* Whether the given key exists.
|
|
995
|
-
* @param key - Key to test.
|
|
996
|
-
* @returns `true` if found; otherwise `false`.
|
|
997
|
-
* @remarks Time O(n) generic, Space O(1)
|
|
998
|
-
*/
|
|
999
|
-
has(key) {
|
|
1000
|
-
for (const item of this) {
|
|
1001
|
-
const [itemKey] = item;
|
|
1002
|
-
if (itemKey === key) return true;
|
|
1003
|
-
}
|
|
1004
|
-
return false;
|
|
1005
|
-
}
|
|
1006
|
-
/**
|
|
1007
|
-
* Whether there exists an entry with the given value.
|
|
1008
|
-
* @param value - Value to test.
|
|
1009
|
-
* @returns `true` if found; otherwise `false`.
|
|
1010
|
-
* @remarks Time O(n), Space O(1)
|
|
1011
|
-
*/
|
|
1012
|
-
hasValue(value) {
|
|
1013
|
-
for (const [, elementValue] of this) {
|
|
1014
|
-
if (elementValue === value) return true;
|
|
1015
|
-
}
|
|
1016
|
-
return false;
|
|
1017
|
-
}
|
|
1018
|
-
/**
|
|
1019
|
-
* Get the value under a key.
|
|
1020
|
-
* @param key - Key to look up.
|
|
1021
|
-
* @returns Value or `undefined`.
|
|
1022
|
-
* @remarks Time O(n) generic, Space O(1)
|
|
1023
|
-
*/
|
|
1024
|
-
get(key) {
|
|
1025
|
-
for (const item of this) {
|
|
1026
|
-
const [itemKey, value] = item;
|
|
1027
|
-
if (itemKey === key) return value;
|
|
1028
|
-
}
|
|
1029
|
-
return;
|
|
1030
|
-
}
|
|
1031
|
-
/**
|
|
1032
|
-
* Reduce entries into a single accumulator.
|
|
1033
|
-
* @param callbackfn - `(acc, value, key, index, self) => acc`.
|
|
1034
|
-
* @param initialValue - Initial accumulator.
|
|
1035
|
-
* @returns Final accumulator.
|
|
1036
|
-
* @remarks Time O(n), Space O(1)
|
|
1037
|
-
*/
|
|
1038
|
-
reduce(callbackfn, initialValue) {
|
|
1039
|
-
let accumulator = initialValue;
|
|
1040
|
-
let index = 0;
|
|
1041
|
-
for (const item of this) {
|
|
1042
|
-
const [key, value] = item;
|
|
1043
|
-
accumulator = callbackfn(accumulator, value, key, index++, this);
|
|
1044
|
-
}
|
|
1045
|
-
return accumulator;
|
|
1046
|
-
}
|
|
1047
|
-
/**
|
|
1048
|
-
* Converts data structure to `[key, value]` pairs.
|
|
1049
|
-
* @returns Array of entries.
|
|
1050
|
-
* @remarks Time O(n), Space O(n)
|
|
1051
|
-
*/
|
|
1052
|
-
toArray() {
|
|
1053
|
-
return [...this];
|
|
1054
|
-
}
|
|
1055
|
-
/**
|
|
1056
|
-
* Visualize the iterable as an array of `[key, value]` pairs (or a custom string).
|
|
1057
|
-
* @returns Array of entries (default) or a string.
|
|
1058
|
-
* @remarks Time O(n), Space O(n)
|
|
1059
|
-
*/
|
|
1060
|
-
toVisual() {
|
|
1061
|
-
return [...this];
|
|
1062
|
-
}
|
|
1063
|
-
/**
|
|
1064
|
-
* Print a human-friendly representation to the console.
|
|
1065
|
-
* @remarks Time O(n), Space O(n)
|
|
1066
|
-
*/
|
|
1067
|
-
print() {
|
|
1068
|
-
console.log(this.toVisual());
|
|
1069
|
-
}
|
|
1070
|
-
};
|
|
1071
|
-
__name(_IterableEntryBase, "IterableEntryBase");
|
|
1072
|
-
var IterableEntryBase = _IterableEntryBase;
|
|
1073
|
-
|
|
1074
1281
|
// src/data-structures/binary-tree/binary-tree.ts
|
|
1075
1282
|
var _BinaryTreeNode = class _BinaryTreeNode {
|
|
1076
1283
|
/**
|
|
@@ -1448,23 +1655,71 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1448
1655
|
return isComparable(key);
|
|
1449
1656
|
}
|
|
1450
1657
|
/**
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1658
|
+
* Adds a new node to the tree.
|
|
1659
|
+
* @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).
|
|
1660
|
+
*
|
|
1661
|
+
* @param keyNodeOrEntry - The key, node, or entry to add.
|
|
1662
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
|
|
1668
|
+
|
|
1669
|
+
* @example
|
|
1670
|
+
* // Add a single node
|
|
1671
|
+
* const tree = new BinaryTree<number>();
|
|
1672
|
+
* tree.add(1);
|
|
1673
|
+
* tree.add(2);
|
|
1674
|
+
* tree.add(3);
|
|
1675
|
+
* console.log(tree.size); // 3;
|
|
1676
|
+
* console.log(tree.has(1)); // true;
|
|
1677
|
+
*/
|
|
1457
1678
|
add(keyNodeOrEntry) {
|
|
1458
1679
|
return this.set(keyNodeOrEntry);
|
|
1459
1680
|
}
|
|
1460
1681
|
/**
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1682
|
+
* Adds or updates a new node to the tree.
|
|
1683
|
+
* @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).
|
|
1684
|
+
*
|
|
1685
|
+
* @param keyNodeOrEntry - The key, node, or entry to set or update.
|
|
1686
|
+
* @param [value] - The value, if providing just a key.
|
|
1687
|
+
* @returns True if the addition was successful, false otherwise.
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
|
|
1699
|
+
* @example
|
|
1700
|
+
* // basic BinaryTree creation and insertion
|
|
1701
|
+
* // Create a BinaryTree with entries
|
|
1702
|
+
* const entries: [number, string][] = [
|
|
1703
|
+
* [6, 'six'],
|
|
1704
|
+
* [1, 'one'],
|
|
1705
|
+
* [2, 'two'],
|
|
1706
|
+
* [7, 'seven'],
|
|
1707
|
+
* [5, 'five'],
|
|
1708
|
+
* [3, 'three'],
|
|
1709
|
+
* [4, 'four'],
|
|
1710
|
+
* [9, 'nine'],
|
|
1711
|
+
* [8, 'eight']
|
|
1712
|
+
* ];
|
|
1713
|
+
*
|
|
1714
|
+
* const tree = new BinaryTree(entries);
|
|
1715
|
+
*
|
|
1716
|
+
* // Verify size
|
|
1717
|
+
* console.log(tree.size); // 9;
|
|
1718
|
+
*
|
|
1719
|
+
* // Add new element
|
|
1720
|
+
* tree.set(10, 'ten');
|
|
1721
|
+
* console.log(tree.size); // 10;
|
|
1722
|
+
*/
|
|
1468
1723
|
set(keyNodeOrEntry, value) {
|
|
1469
1724
|
const [newNode] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
|
|
1470
1725
|
if (newNode === void 0) return false;
|
|
@@ -1509,23 +1764,44 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1509
1764
|
return false;
|
|
1510
1765
|
}
|
|
1511
1766
|
/**
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1767
|
+
* Adds multiple items to the tree.
|
|
1768
|
+
* @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).
|
|
1769
|
+
*
|
|
1770
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set.
|
|
1771
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1772
|
+
|
|
1773
|
+
|
|
1774
|
+
|
|
1775
|
+
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
|
|
1779
|
+
|
|
1780
|
+
|
|
1781
|
+
* @example
|
|
1782
|
+
* // Bulk add
|
|
1783
|
+
* const tree = new BinaryTree<number>();
|
|
1784
|
+
* tree.addMany([1, 2, 3, 4, 5]);
|
|
1785
|
+
* console.log(tree.size); // 5;
|
|
1786
|
+
*/
|
|
1518
1787
|
addMany(keysNodesEntriesOrRaws) {
|
|
1519
1788
|
return this.setMany(keysNodesEntriesOrRaws);
|
|
1520
1789
|
}
|
|
1521
1790
|
/**
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1791
|
+
* Adds or updates multiple items to the tree.
|
|
1792
|
+
* @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).
|
|
1793
|
+
*
|
|
1794
|
+
* @param keysNodesEntriesOrRaws - An iterable of items to set or update.
|
|
1795
|
+
* @param [values] - An optional parallel iterable of values.
|
|
1796
|
+
* @returns An array of booleans indicating the success of each individual `set` operation.
|
|
1797
|
+
|
|
1798
|
+
|
|
1799
|
+
* @example
|
|
1800
|
+
* // Set multiple entries
|
|
1801
|
+
* const tree = new BinaryTree<number, string>();
|
|
1802
|
+
* tree.setMany([[1, 'a'], [2, 'b'], [3, 'c']]);
|
|
1803
|
+
* console.log(tree.size); // 3;
|
|
1804
|
+
*/
|
|
1529
1805
|
setMany(keysNodesEntriesOrRaws, values) {
|
|
1530
1806
|
const inserted = [];
|
|
1531
1807
|
let valuesIterator;
|
|
@@ -1546,11 +1822,26 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1546
1822
|
return inserted;
|
|
1547
1823
|
}
|
|
1548
1824
|
/**
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1825
|
+
* Merges another tree into this one by seting all its nodes.
|
|
1826
|
+
* @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`).
|
|
1827
|
+
*
|
|
1828
|
+
* @param anotherTree - The tree to merge.
|
|
1829
|
+
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
|
|
1833
|
+
|
|
1834
|
+
|
|
1835
|
+
|
|
1836
|
+
|
|
1837
|
+
|
|
1838
|
+
* @example
|
|
1839
|
+
* // Combine trees
|
|
1840
|
+
* const t1 = new BinaryTree<number>([1, 2]);
|
|
1841
|
+
* const t2 = new BinaryTree<number>([3, 4]);
|
|
1842
|
+
* t1.merge(t2);
|
|
1843
|
+
* console.log(t1.size); // 4;
|
|
1844
|
+
*/
|
|
1554
1845
|
merge(anotherTree) {
|
|
1555
1846
|
this.setMany(anotherTree, []);
|
|
1556
1847
|
}
|
|
@@ -1566,12 +1857,29 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1566
1857
|
this.setMany(keysNodesEntriesOrRaws, values);
|
|
1567
1858
|
}
|
|
1568
1859
|
/**
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1860
|
+
* Deletes a node from the tree.
|
|
1861
|
+
* @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).
|
|
1862
|
+
*
|
|
1863
|
+
* @param keyNodeEntryRawOrPredicate - The node to delete.
|
|
1864
|
+
* @returns An array containing deletion results (for compatibility with self-balancing trees).
|
|
1865
|
+
|
|
1866
|
+
|
|
1867
|
+
|
|
1868
|
+
|
|
1869
|
+
|
|
1870
|
+
|
|
1871
|
+
|
|
1872
|
+
|
|
1873
|
+
|
|
1874
|
+
|
|
1875
|
+
|
|
1876
|
+
* @example
|
|
1877
|
+
* // Remove a node
|
|
1878
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
1879
|
+
* tree.delete(3);
|
|
1880
|
+
* console.log(tree.has(3)); // false;
|
|
1881
|
+
* console.log(tree.size); // 4;
|
|
1882
|
+
*/
|
|
1575
1883
|
delete(keyNodeEntryRawOrPredicate) {
|
|
1576
1884
|
const deletedResult = [];
|
|
1577
1885
|
if (!this._root) return deletedResult;
|
|
@@ -1665,14 +1973,27 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1665
1973
|
return this.search(keyNodeEntryOrPredicate, onlyOne, (node) => node, startNode, iterationType);
|
|
1666
1974
|
}
|
|
1667
1975
|
/**
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1976
|
+
* Gets the first node matching a predicate.
|
|
1977
|
+
* @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`).
|
|
1978
|
+
*
|
|
1979
|
+
* @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
|
|
1980
|
+
* @param [startNode=this._root] - The node to start the search from.
|
|
1981
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
1982
|
+
* @returns The first matching node, or undefined if not found.
|
|
1983
|
+
|
|
1984
|
+
|
|
1985
|
+
|
|
1986
|
+
|
|
1987
|
+
|
|
1988
|
+
|
|
1989
|
+
|
|
1990
|
+
|
|
1991
|
+
|
|
1992
|
+
* @example
|
|
1993
|
+
* // Get node by key
|
|
1994
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'child']]);
|
|
1995
|
+
* console.log(tree.getNode(2)?.value); // 'child';
|
|
1996
|
+
*/
|
|
1676
1997
|
getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1677
1998
|
if (this._isMapMode && keyNodeEntryOrPredicate !== null && keyNodeEntryOrPredicate !== void 0) {
|
|
1678
1999
|
if (!this._isPredicate(keyNodeEntryOrPredicate)) {
|
|
@@ -1684,14 +2005,30 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1684
2005
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType)[0];
|
|
1685
2006
|
}
|
|
1686
2007
|
/**
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
2008
|
+
* Gets the value associated with a key.
|
|
2009
|
+
* @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.
|
|
2010
|
+
*
|
|
2011
|
+
* @param keyNodeEntryOrPredicate - The key, node, or entry to get the value for.
|
|
2012
|
+
* @param [startNode=this._root] - The node to start searching from (if not in Map mode).
|
|
2013
|
+
* @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
|
|
2014
|
+
* @returns The associated value, or undefined.
|
|
2015
|
+
|
|
2016
|
+
|
|
2017
|
+
|
|
2018
|
+
|
|
2019
|
+
|
|
2020
|
+
|
|
2021
|
+
|
|
2022
|
+
|
|
2023
|
+
|
|
2024
|
+
|
|
2025
|
+
|
|
2026
|
+
* @example
|
|
2027
|
+
* // Retrieve value by key
|
|
2028
|
+
* const tree = new BinaryTree<number, string>([[1, 'root'], [2, 'left'], [3, 'right']]);
|
|
2029
|
+
* console.log(tree.get(2)); // 'left';
|
|
2030
|
+
* console.log(tree.get(99)); // undefined;
|
|
2031
|
+
*/
|
|
1695
2032
|
get(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
|
|
1696
2033
|
var _a, _b;
|
|
1697
2034
|
if (this._isMapMode) {
|
|
@@ -1712,19 +2049,45 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1712
2049
|
return this.search(keyNodeEntryOrPredicate, true, (node) => node, startNode, iterationType).length > 0;
|
|
1713
2050
|
}
|
|
1714
2051
|
/**
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
2052
|
+
* Clears the tree of all nodes and values.
|
|
2053
|
+
* @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
|
|
2054
|
+
|
|
2055
|
+
|
|
2056
|
+
|
|
2057
|
+
|
|
2058
|
+
|
|
2059
|
+
|
|
2060
|
+
|
|
2061
|
+
|
|
2062
|
+
|
|
2063
|
+
* @example
|
|
2064
|
+
* // Remove all nodes
|
|
2065
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2066
|
+
* tree.clear();
|
|
2067
|
+
* console.log(tree.isEmpty()); // true;
|
|
2068
|
+
*/
|
|
1718
2069
|
clear() {
|
|
1719
2070
|
this._clearNodes();
|
|
1720
2071
|
if (this._isMapMode) this._clearValues();
|
|
1721
2072
|
}
|
|
1722
2073
|
/**
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
2074
|
+
* Checks if the tree is empty.
|
|
2075
|
+
* @remarks Time O(1), Space O(1)
|
|
2076
|
+
*
|
|
2077
|
+
* @returns True if the tree has no nodes, false otherwise.
|
|
2078
|
+
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
|
|
2086
|
+
|
|
2087
|
+
* @example
|
|
2088
|
+
* // Check empty
|
|
2089
|
+
* console.log(new BinaryTree().isEmpty()); // true;
|
|
2090
|
+
*/
|
|
1728
2091
|
isEmpty() {
|
|
1729
2092
|
return this._size === 0;
|
|
1730
2093
|
}
|
|
@@ -1739,13 +2102,27 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1739
2102
|
return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
|
|
1740
2103
|
}
|
|
1741
2104
|
/**
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
2105
|
+
* Checks if the tree is a valid Binary Search Tree (BST).
|
|
2106
|
+
* @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).
|
|
2107
|
+
*
|
|
2108
|
+
* @param [startNode=this._root] - The node to start checking from.
|
|
2109
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2110
|
+
* @returns True if it's a valid BST, false otherwise.
|
|
2111
|
+
|
|
2112
|
+
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
|
|
2116
|
+
|
|
2117
|
+
|
|
2118
|
+
|
|
2119
|
+
|
|
2120
|
+
* @example
|
|
2121
|
+
* // Check BST property
|
|
2122
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2123
|
+
* // BinaryTree doesn't guarantee BST order
|
|
2124
|
+
* console.log(typeof tree.isBST()); // 'boolean';
|
|
2125
|
+
*/
|
|
1749
2126
|
isBST(startNode = this._root, iterationType = this.iterationType) {
|
|
1750
2127
|
const startNodeSired = this.ensureNode(startNode);
|
|
1751
2128
|
if (!startNodeSired) return true;
|
|
@@ -1783,13 +2160,29 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1783
2160
|
}
|
|
1784
2161
|
}
|
|
1785
2162
|
/**
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
2163
|
+
* Gets the depth of a node (distance from `startNode`).
|
|
2164
|
+
* @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
|
|
2165
|
+
*
|
|
2166
|
+
* @param dist - The node to find the depth of.
|
|
2167
|
+
* @param [startNode=this._root] - The node to measure depth from (defaults to root).
|
|
2168
|
+
* @returns The depth (0 if `dist` is `startNode`).
|
|
2169
|
+
|
|
2170
|
+
|
|
2171
|
+
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
|
|
2177
|
+
|
|
2178
|
+
|
|
2179
|
+
|
|
2180
|
+
* @example
|
|
2181
|
+
* // Get depth of a node
|
|
2182
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2183
|
+
* const node = tree.getNode(4);
|
|
2184
|
+
* console.log(tree.getDepth(node!)); // 2;
|
|
2185
|
+
*/
|
|
1793
2186
|
getDepth(dist, startNode = this._root) {
|
|
1794
2187
|
let distEnsured = this.ensureNode(dist);
|
|
1795
2188
|
const beginRootEnsured = this.ensureNode(startNode);
|
|
@@ -1804,13 +2197,28 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
1804
2197
|
return depth;
|
|
1805
2198
|
}
|
|
1806
2199
|
/**
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
2200
|
+
* Gets the maximum height of the tree (longest path from startNode to a leaf).
|
|
2201
|
+
* @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).
|
|
2202
|
+
*
|
|
2203
|
+
* @param [startNode=this._root] - The node to start measuring from.
|
|
2204
|
+
* @param [iterationType=this.iterationType] - The traversal method.
|
|
2205
|
+
* @returns The height ( -1 for an empty tree, 0 for a single-node tree).
|
|
2206
|
+
|
|
2207
|
+
|
|
2208
|
+
|
|
2209
|
+
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
|
|
2213
|
+
|
|
2214
|
+
|
|
2215
|
+
|
|
2216
|
+
|
|
2217
|
+
* @example
|
|
2218
|
+
* // Get tree height
|
|
2219
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4, 5]);
|
|
2220
|
+
* console.log(tree.getHeight()); // 2;
|
|
2221
|
+
*/
|
|
1814
2222
|
getHeight(startNode = this._root, iterationType = this.iterationType) {
|
|
1815
2223
|
startNode = this.ensureNode(startNode);
|
|
1816
2224
|
if (!this.isRealNode(startNode)) return -1;
|
|
@@ -2246,24 +2654,53 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2246
2654
|
return ans;
|
|
2247
2655
|
}
|
|
2248
2656
|
/**
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2657
|
+
* Clones the tree.
|
|
2658
|
+
* @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.
|
|
2659
|
+
*
|
|
2660
|
+
* @returns A new, cloned instance of the tree.
|
|
2661
|
+
|
|
2662
|
+
|
|
2663
|
+
|
|
2664
|
+
|
|
2665
|
+
|
|
2666
|
+
|
|
2667
|
+
|
|
2668
|
+
|
|
2669
|
+
|
|
2670
|
+
* @example
|
|
2671
|
+
* // Deep copy
|
|
2672
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2673
|
+
* const copy = tree.clone();
|
|
2674
|
+
* copy.delete(1);
|
|
2675
|
+
* console.log(tree.has(1)); // true;
|
|
2676
|
+
*/
|
|
2254
2677
|
clone() {
|
|
2255
2678
|
const out = this._createInstance();
|
|
2256
2679
|
this._clone(out);
|
|
2257
2680
|
return out;
|
|
2258
2681
|
}
|
|
2259
2682
|
/**
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2683
|
+
* Creates a new tree containing only the entries that satisfy the predicate.
|
|
2684
|
+
* @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.
|
|
2685
|
+
*
|
|
2686
|
+
* @param predicate - A function to test each [key, value] pair.
|
|
2687
|
+
* @param [thisArg] - `this` context for the predicate.
|
|
2688
|
+
* @returns A new, filtered tree.
|
|
2689
|
+
|
|
2690
|
+
|
|
2691
|
+
|
|
2692
|
+
|
|
2693
|
+
|
|
2694
|
+
|
|
2695
|
+
|
|
2696
|
+
|
|
2697
|
+
|
|
2698
|
+
* @example
|
|
2699
|
+
* // Filter nodes by condition
|
|
2700
|
+
* const tree = new BinaryTree<number>([1, 2, 3, 4]);
|
|
2701
|
+
* const result = tree.filter((_, key) => key > 2);
|
|
2702
|
+
* console.log(result.size); // 2;
|
|
2703
|
+
*/
|
|
2267
2704
|
filter(predicate, thisArg) {
|
|
2268
2705
|
const out = this._createInstance();
|
|
2269
2706
|
let i = 0;
|
|
@@ -2271,17 +2708,31 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2271
2708
|
return out;
|
|
2272
2709
|
}
|
|
2273
2710
|
/**
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2711
|
+
* Creates a new tree by mapping each [key, value] pair to a new entry.
|
|
2712
|
+
* @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.
|
|
2713
|
+
*
|
|
2714
|
+
* @template MK - New key type.
|
|
2715
|
+
* @template MV - New value type.
|
|
2716
|
+
* @template MR - New raw type.
|
|
2717
|
+
* @param cb - A function to map each [key, value] pair.
|
|
2718
|
+
* @param [options] - Options for the new tree.
|
|
2719
|
+
* @param [thisArg] - `this` context for the callback.
|
|
2720
|
+
* @returns A new, mapped tree.
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
|
|
2728
|
+
|
|
2729
|
+
|
|
2730
|
+
* @example
|
|
2731
|
+
* // Transform to new tree
|
|
2732
|
+
* const tree = new BinaryTree<number, number>([[1, 10], [2, 20]]);
|
|
2733
|
+
* const mapped = tree.map((v, key) => [key, (v ?? 0) + 1] as [number, number]);
|
|
2734
|
+
* console.log([...mapped.values()]); // contains 11;
|
|
2735
|
+
*/
|
|
2285
2736
|
map(cb, options, thisArg) {
|
|
2286
2737
|
const out = this._createLike([], options);
|
|
2287
2738
|
let i = 0;
|
|
@@ -2319,12 +2770,25 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2319
2770
|
return output;
|
|
2320
2771
|
}
|
|
2321
2772
|
/**
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2773
|
+
* Prints a visual representation of the tree to the console.
|
|
2774
|
+
* @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
|
|
2775
|
+
*
|
|
2776
|
+
* @param [options] - Options to control the output.
|
|
2777
|
+
* @param [startNode=this._root] - The node to start printing from.
|
|
2778
|
+
|
|
2779
|
+
|
|
2780
|
+
|
|
2781
|
+
|
|
2782
|
+
|
|
2783
|
+
|
|
2784
|
+
|
|
2785
|
+
|
|
2786
|
+
|
|
2787
|
+
* @example
|
|
2788
|
+
* // Display tree
|
|
2789
|
+
* const tree = new BinaryTree<number>([1, 2, 3]);
|
|
2790
|
+
* expect(() => tree.print()).not.toThrow();
|
|
2791
|
+
*/
|
|
2328
2792
|
print(options, startNode = this._root) {
|
|
2329
2793
|
console.log(this.toVisual(startNode, options));
|
|
2330
2794
|
}
|
|
@@ -2557,7 +3021,6 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
|
|
|
2557
3021
|
* @returns Layout information for this subtree.
|
|
2558
3022
|
*/
|
|
2559
3023
|
_displayAux(node, options) {
|
|
2560
|
-
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
2561
3024
|
const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
|
|
2562
3025
|
const newFrame = /* @__PURE__ */ __name((n) => ({
|
|
2563
3026
|
node: n,
|