priority-queue-typed 1.46.7 → 1.46.9
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/data-structures/binary-tree/avl-tree.d.ts +4 -2
- package/dist/data-structures/binary-tree/avl-tree.js +10 -0
- package/dist/data-structures/binary-tree/binary-tree.d.ts +19 -13
- package/dist/data-structures/binary-tree/binary-tree.js +121 -55
- package/dist/data-structures/binary-tree/bst.d.ts +10 -9
- package/dist/data-structures/binary-tree/bst.js +16 -14
- package/dist/data-structures/binary-tree/rb-tree.d.ts +7 -5
- package/dist/data-structures/binary-tree/rb-tree.js +32 -23
- package/dist/data-structures/binary-tree/tree-multimap.d.ts +5 -3
- package/dist/data-structures/binary-tree/tree-multimap.js +11 -2
- package/dist/interfaces/binary-tree.d.ts +3 -3
- package/dist/types/common.d.ts +5 -4
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +2 -1
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +3 -1
- package/dist/types/data-structures/binary-tree/binary-tree.js +0 -6
- package/dist/types/data-structures/binary-tree/bst.d.ts +2 -1
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -1
- package/dist/types/data-structures/binary-tree/tree-multimap.d.ts +2 -1
- package/package.json +2 -2
- package/src/data-structures/binary-tree/avl-tree.ts +17 -5
- package/src/data-structures/binary-tree/binary-tree.ts +143 -62
- package/src/data-structures/binary-tree/bst.ts +23 -19
- package/src/data-structures/binary-tree/rb-tree.ts +38 -27
- package/src/data-structures/binary-tree/tree-multimap.ts +19 -6
- package/src/interfaces/binary-tree.ts +3 -3
- package/src/types/common.ts +2 -5
- package/src/types/data-structures/binary-tree/avl-tree.ts +5 -1
- package/src/types/data-structures/binary-tree/binary-tree.ts +5 -7
- package/src/types/data-structures/binary-tree/bst.ts +3 -1
- package/src/types/data-structures/binary-tree/rb-tree.ts +3 -1
- package/src/types/data-structures/binary-tree/tree-multimap.ts +3 -1
|
@@ -7,7 +7,15 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, BTNKey } from '../../types';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
BinaryTreeNested,
|
|
12
|
+
BinaryTreePrintOptions,
|
|
13
|
+
BiTreeDeleteResult,
|
|
14
|
+
DFSOrderPattern,
|
|
15
|
+
FamilyPosition,
|
|
16
|
+
IterationType,
|
|
17
|
+
NodeDisplayLayout
|
|
18
|
+
} from '../../types';
|
|
11
19
|
import { IBinaryTree } from '../../interfaces';
|
|
12
20
|
import { trampoline } from '../../utils';
|
|
13
21
|
import { Queue } from '../queue';
|
|
@@ -107,9 +115,10 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|
|
107
115
|
* Represents a binary tree data structure.
|
|
108
116
|
* @template N - The type of the binary tree's nodes.
|
|
109
117
|
*/
|
|
110
|
-
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>>
|
|
111
|
-
implements IBinaryTree<V, N> {
|
|
112
|
-
|
|
118
|
+
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>, TREE extends BinaryTree<V, N, TREE> = BinaryTree<V, N, BinaryTreeNested<V, N>>>
|
|
119
|
+
implements IBinaryTree<V, N, TREE> {
|
|
120
|
+
|
|
121
|
+
options: BinaryTreeOptions;
|
|
113
122
|
|
|
114
123
|
/**
|
|
115
124
|
* Creates a new instance of BinaryTree.
|
|
@@ -117,9 +126,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
117
126
|
*/
|
|
118
127
|
constructor(options?: BinaryTreeOptions) {
|
|
119
128
|
if (options) {
|
|
120
|
-
|
|
121
|
-
|
|
129
|
+
this.options = { iterationType: IterationType.ITERATIVE, ...options }
|
|
130
|
+
} else {
|
|
131
|
+
this.options = { iterationType: IterationType.ITERATIVE };
|
|
122
132
|
}
|
|
133
|
+
|
|
123
134
|
this._size = 0;
|
|
124
135
|
}
|
|
125
136
|
|
|
@@ -151,6 +162,10 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
151
162
|
return new BinaryTreeNode<V, N>(key, value) as N;
|
|
152
163
|
}
|
|
153
164
|
|
|
165
|
+
createTree(options?: BinaryTreeOptions): TREE {
|
|
166
|
+
return new BinaryTree<V, N, TREE>({ ...this.options, ...options }) as TREE;
|
|
167
|
+
}
|
|
168
|
+
|
|
154
169
|
/**
|
|
155
170
|
* Time Complexity: O(n)
|
|
156
171
|
* Space Complexity: O(1)
|
|
@@ -397,7 +412,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
397
412
|
* values:
|
|
398
413
|
* @returns the height of the binary tree.
|
|
399
414
|
*/
|
|
400
|
-
getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
|
|
415
|
+
getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.options.iterationType): number {
|
|
401
416
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
402
417
|
if (!beginRoot) return -1;
|
|
403
418
|
|
|
@@ -446,7 +461,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
446
461
|
* to calculate the minimum height of a binary tree. It can have two possible values:
|
|
447
462
|
* @returns The function `getMinHeight` returns the minimum height of a binary tree.
|
|
448
463
|
*/
|
|
449
|
-
getMinHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
|
|
464
|
+
getMinHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.options.iterationType): number {
|
|
450
465
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
451
466
|
if (!beginRoot) return -1;
|
|
452
467
|
|
|
@@ -568,7 +583,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
568
583
|
callback: C = this._defaultOneParamCallback as C,
|
|
569
584
|
onlyOne = false,
|
|
570
585
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
571
|
-
iterationType = this.iterationType
|
|
586
|
+
iterationType = this.options.iterationType
|
|
572
587
|
): N[] {
|
|
573
588
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
574
589
|
callback = (node => node) as C;
|
|
@@ -657,7 +672,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
657
672
|
identifier: ReturnType<C> | null | undefined,
|
|
658
673
|
callback: C = this._defaultOneParamCallback as C,
|
|
659
674
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
660
|
-
iterationType = this.iterationType
|
|
675
|
+
iterationType = this.options.iterationType
|
|
661
676
|
): boolean {
|
|
662
677
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
663
678
|
callback = (node => node) as C;
|
|
@@ -716,7 +731,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
716
731
|
identifier: ReturnType<C> | null | undefined,
|
|
717
732
|
callback: C = this._defaultOneParamCallback as C,
|
|
718
733
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
719
|
-
iterationType = this.iterationType
|
|
734
|
+
iterationType = this.options.iterationType
|
|
720
735
|
): N | null | undefined {
|
|
721
736
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
722
737
|
callback = (node => node) as C;
|
|
@@ -835,7 +850,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
835
850
|
identifier: ReturnType<C> | null | undefined,
|
|
836
851
|
callback: C = this._defaultOneParamCallback as C,
|
|
837
852
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
838
|
-
iterationType = this.iterationType
|
|
853
|
+
iterationType = this.options.iterationType
|
|
839
854
|
): V | undefined {
|
|
840
855
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
841
856
|
callback = (node => node) as C;
|
|
@@ -916,7 +931,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
916
931
|
*/
|
|
917
932
|
getLeftMost(
|
|
918
933
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
919
|
-
iterationType = this.iterationType
|
|
934
|
+
iterationType = this.options.iterationType
|
|
920
935
|
): N | null | undefined {
|
|
921
936
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
922
937
|
|
|
@@ -962,7 +977,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
962
977
|
*/
|
|
963
978
|
getRightMost(
|
|
964
979
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
965
|
-
iterationType = this.iterationType
|
|
980
|
+
iterationType = this.options.iterationType
|
|
966
981
|
): N | null | undefined {
|
|
967
982
|
// TODO support get right most by passing key in
|
|
968
983
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
@@ -1003,7 +1018,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1003
1018
|
* possible values:
|
|
1004
1019
|
* @returns a boolean value.
|
|
1005
1020
|
*/
|
|
1006
|
-
isSubtreeBST(beginRoot: BTNKey | N | null | undefined, iterationType = this.iterationType): boolean {
|
|
1021
|
+
isSubtreeBST(beginRoot: BTNKey | N | null | undefined, iterationType = this.options.iterationType): boolean {
|
|
1007
1022
|
// TODO there is a bug
|
|
1008
1023
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
1009
1024
|
if (!beginRoot) return true;
|
|
@@ -1050,7 +1065,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1050
1065
|
* expected to be
|
|
1051
1066
|
* @returns a boolean value.
|
|
1052
1067
|
*/
|
|
1053
|
-
isBST(iterationType = this.iterationType): boolean {
|
|
1068
|
+
isBST(iterationType = this.options.iterationType): boolean {
|
|
1054
1069
|
if (this.root === null) return true;
|
|
1055
1070
|
return this.isSubtreeBST(this.root, iterationType);
|
|
1056
1071
|
}
|
|
@@ -1097,7 +1112,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1097
1112
|
* @param iterationType - The `iterationType` parameter determines the type of traversal to be
|
|
1098
1113
|
* performed on the subtree. It can have two possible values:
|
|
1099
1114
|
* @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
|
|
1100
|
-
* whether
|
|
1115
|
+
* whether to include null values in the traversal. If `includeNull` is set to `true`, the
|
|
1101
1116
|
* traversal will include null values, otherwise it will skip them.
|
|
1102
1117
|
* @returns The function `subTreeTraverse` returns an array of values that are the result of invoking
|
|
1103
1118
|
* the `callback` function on each node in the subtree. The type of the array elements is determined
|
|
@@ -1106,7 +1121,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1106
1121
|
subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
|
|
1107
1122
|
callback: C = this._defaultOneParamCallback as C,
|
|
1108
1123
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
1109
|
-
iterationType = this.iterationType,
|
|
1124
|
+
iterationType = this.options.iterationType,
|
|
1110
1125
|
includeNull = false
|
|
1111
1126
|
): ReturnType<C>[] {
|
|
1112
1127
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
@@ -1376,7 +1391,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1376
1391
|
* @param iterationType - The `iterationType` parameter determines the type of iteration to be
|
|
1377
1392
|
* performed during the breadth-first search (BFS). It can have two possible values:
|
|
1378
1393
|
* @param [includeNull=false] - The `includeNull` parameter is a boolean flag that determines whether
|
|
1379
|
-
*
|
|
1394
|
+
* to include null values in the breadth-first search traversal. If `includeNull` is set to
|
|
1380
1395
|
* `true`, null values will be included in the traversal, otherwise they will be skipped.
|
|
1381
1396
|
* @returns an array of values that are the result of invoking the callback function on each node in
|
|
1382
1397
|
* the breadth-first traversal of a binary tree.
|
|
@@ -1384,7 +1399,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1384
1399
|
bfs<C extends BTNCallback<N | null | undefined>>(
|
|
1385
1400
|
callback: C = this._defaultOneParamCallback as C,
|
|
1386
1401
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
1387
|
-
iterationType = this.iterationType,
|
|
1402
|
+
iterationType = this.options.iterationType,
|
|
1388
1403
|
includeNull = false
|
|
1389
1404
|
): ReturnType<C>[] {
|
|
1390
1405
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
@@ -1477,7 +1492,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1477
1492
|
* @param iterationType - The `iterationType` parameter determines the type of iteration to be
|
|
1478
1493
|
* performed on the tree. It can have two possible values:
|
|
1479
1494
|
* @param [includeNull=false] - The `includeNull` parameter is a boolean value that determines
|
|
1480
|
-
* whether
|
|
1495
|
+
* whether to include null values in the resulting levels. If `includeNull` is set to `true`,
|
|
1481
1496
|
* null values will be included in the levels. If `includeNull` is set to `false`, null values will
|
|
1482
1497
|
* be excluded
|
|
1483
1498
|
* @returns The function `listLevels` returns a two-dimensional array of type `ReturnType<C>[][]`.
|
|
@@ -1485,7 +1500,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1485
1500
|
listLevels<C extends BTNCallback<N | null | undefined>>(
|
|
1486
1501
|
callback: C = this._defaultOneParamCallback as C,
|
|
1487
1502
|
beginRoot: BTNKey | N | null | undefined = this.root,
|
|
1488
|
-
iterationType = this.iterationType,
|
|
1503
|
+
iterationType = this.options.iterationType,
|
|
1489
1504
|
includeNull = false
|
|
1490
1505
|
): ReturnType<C>[][] {
|
|
1491
1506
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
@@ -1685,6 +1700,48 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1685
1700
|
return ans;
|
|
1686
1701
|
}
|
|
1687
1702
|
|
|
1703
|
+
forEach(callback: (entry: [BTNKey, V | undefined], tree: typeof this) => void): void {
|
|
1704
|
+
for (const entry of this) {
|
|
1705
|
+
callback(entry, this);
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
filter(predicate: (entry: [BTNKey, V | undefined], tree: typeof this) => boolean) {
|
|
1710
|
+
const newTree = this.createTree();
|
|
1711
|
+
for (const [key, value] of this) {
|
|
1712
|
+
if (predicate([key, value], this)) {
|
|
1713
|
+
newTree.add(key, value);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
return newTree;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
// TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
|
|
1720
|
+
// map<NV>(callback: (entry: [BTNKey, V | undefined], tree: typeof this) => NV) {
|
|
1721
|
+
// const newTree = this.createTree();
|
|
1722
|
+
// for (const [key, value] of this) {
|
|
1723
|
+
// newTree.add(key, callback([key, value], this));
|
|
1724
|
+
// }
|
|
1725
|
+
// return newTree;
|
|
1726
|
+
// }
|
|
1727
|
+
|
|
1728
|
+
map(callback: (entry: [BTNKey, V | undefined], tree: typeof this) => V) {
|
|
1729
|
+
const newTree = this.createTree();
|
|
1730
|
+
for (const [key, value] of this) {
|
|
1731
|
+
newTree.add(key, callback([key, value], this));
|
|
1732
|
+
}
|
|
1733
|
+
return newTree;
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
reduce<T>(callback: (accumulator: T, entry: [BTNKey, V | undefined], tree: typeof this) => T, initialValue: T): T {
|
|
1737
|
+
let accumulator = initialValue;
|
|
1738
|
+
for (const [key, value] of this) {
|
|
1739
|
+
accumulator = callback(accumulator, [key, value], this);
|
|
1740
|
+
}
|
|
1741
|
+
return accumulator;
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
|
|
1688
1745
|
/**
|
|
1689
1746
|
* The above function is an iterator for a binary tree that can be used to traverse the tree in
|
|
1690
1747
|
* either an iterative or recursive manner.
|
|
@@ -1694,32 +1751,32 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1694
1751
|
* @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
|
|
1695
1752
|
* binary tree nodes in a specific order.
|
|
1696
1753
|
*/
|
|
1697
|
-
* [Symbol.iterator](node = this.root): Generator<BTNKey, void, undefined> {
|
|
1698
|
-
if (!node)
|
|
1699
|
-
return;
|
|
1700
|
-
}
|
|
1754
|
+
* [Symbol.iterator](node = this.root): Generator<[BTNKey, V | undefined], void, undefined> {
|
|
1755
|
+
if (!node) return;
|
|
1701
1756
|
|
|
1702
|
-
if (this.iterationType === IterationType.ITERATIVE) {
|
|
1757
|
+
if (this.options.iterationType === IterationType.ITERATIVE) {
|
|
1703
1758
|
const stack: (N | null | undefined)[] = [];
|
|
1704
1759
|
let current: N | null | undefined = node;
|
|
1705
1760
|
|
|
1706
1761
|
while (current || stack.length > 0) {
|
|
1707
|
-
while (current) {
|
|
1762
|
+
while (current && !isNaN(current.key)) {
|
|
1708
1763
|
stack.push(current);
|
|
1709
1764
|
current = current.left;
|
|
1710
1765
|
}
|
|
1711
1766
|
|
|
1712
1767
|
current = stack.pop();
|
|
1713
1768
|
|
|
1714
|
-
if (current
|
|
1715
|
-
|
|
1769
|
+
if (current && !isNaN(current.key)) {
|
|
1770
|
+
yield [current.key, current.value];
|
|
1771
|
+
current = current.right;
|
|
1772
|
+
}
|
|
1716
1773
|
}
|
|
1717
1774
|
} else {
|
|
1718
|
-
if (node.left) {
|
|
1775
|
+
if (node.left && !isNaN(node.key)) {
|
|
1719
1776
|
yield* this[Symbol.iterator](node.left);
|
|
1720
1777
|
}
|
|
1721
|
-
yield node.key;
|
|
1722
|
-
if (node.right) {
|
|
1778
|
+
yield [node.key, node.value];
|
|
1779
|
+
if (node.right && !isNaN(node.key)) {
|
|
1723
1780
|
yield* this[Symbol.iterator](node.right);
|
|
1724
1781
|
}
|
|
1725
1782
|
}
|
|
@@ -1727,16 +1784,25 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1727
1784
|
|
|
1728
1785
|
/**
|
|
1729
1786
|
* The `print` function is used to display a binary tree structure in a visually appealing way.
|
|
1730
|
-
* @param {N | null | undefined} beginRoot - The `root` parameter is of type `BTNKey | N | null |
|
|
1787
|
+
* @param {BTNKey | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `BTNKey | N | null |
|
|
1731
1788
|
* undefined`. It represents the root node of a binary tree. The root node can have one of the
|
|
1732
1789
|
* following types:
|
|
1790
|
+
* @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
|
|
1733
1791
|
*/
|
|
1734
|
-
print(beginRoot: BTNKey | N | null | undefined = this.root): void {
|
|
1792
|
+
print(beginRoot: BTNKey | N | null | undefined = this.root, options?: BinaryTreePrintOptions): void {
|
|
1793
|
+
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
|
|
1735
1794
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
1736
1795
|
if (!beginRoot) return;
|
|
1737
1796
|
|
|
1797
|
+
if (opts.isShowUndefined) console.log(`U for undefined
|
|
1798
|
+
`);
|
|
1799
|
+
if (opts.isShowNull) console.log(`N for null
|
|
1800
|
+
`);
|
|
1801
|
+
if (opts.isShowRedBlackNIL) console.log(`S for Sentinel Node
|
|
1802
|
+
`);
|
|
1803
|
+
|
|
1738
1804
|
const display = (root: N | null | undefined): void => {
|
|
1739
|
-
const [lines, , ,] = this._displayAux(root);
|
|
1805
|
+
const [lines, , ,] = this._displayAux(root, opts);
|
|
1740
1806
|
for (const line of lines) {
|
|
1741
1807
|
console.log(line);
|
|
1742
1808
|
}
|
|
@@ -1745,39 +1811,54 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
1745
1811
|
display(beginRoot);
|
|
1746
1812
|
}
|
|
1747
1813
|
|
|
1748
|
-
protected _displayAux(node: N | null | undefined
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
}
|
|
1752
|
-
|
|
1753
|
-
const line = node.key.toString();
|
|
1754
|
-
const width = line.length;
|
|
1814
|
+
protected _displayAux(node: N | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout {
|
|
1815
|
+
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
|
1816
|
+
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
|
1755
1817
|
|
|
1756
|
-
if
|
|
1757
|
-
|
|
1758
|
-
|
|
1818
|
+
// Check if node is null or undefined or key is NaN
|
|
1819
|
+
if (node === null && !isShowNull) {
|
|
1820
|
+
return emptyDisplayLayout;
|
|
1821
|
+
} else if (node === undefined && !isShowUndefined) {
|
|
1822
|
+
return emptyDisplayLayout;
|
|
1823
|
+
} else if (node !== null && node !== undefined && isNaN(node.key) && !isShowRedBlackNIL) {
|
|
1824
|
+
return emptyDisplayLayout;
|
|
1825
|
+
} else if (node !== null && node !== undefined) {
|
|
1826
|
+
// Display logic of normal nodes
|
|
1759
1827
|
|
|
1760
|
-
|
|
1761
|
-
const [rightLines, rightWidth, rightHeight, rightMiddle] = node.right ? this._displayAux(node.right) : [[''], 0, 0, 0];
|
|
1828
|
+
const key = node.key, line = isNaN(key) ? 'S' : key.toString(), width = line.length;
|
|
1762
1829
|
|
|
1763
|
-
|
|
1764
|
-
+ '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1))
|
|
1765
|
-
+ line
|
|
1766
|
-
+ '_'.repeat(Math.max(0, rightMiddle))
|
|
1767
|
-
+ ' '.repeat(Math.max(0, rightWidth - rightMiddle));
|
|
1830
|
+
return _buildNodeDisplay(line, width, this._displayAux(node.left, options), this._displayAux(node.right, options))
|
|
1768
1831
|
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1832
|
+
} else {
|
|
1833
|
+
// For cases where none of the conditions are met, null, undefined, and NaN nodes are not displayed
|
|
1834
|
+
const line = node === undefined ? 'U' : 'N', width = line.length;
|
|
1772
1835
|
|
|
1773
|
-
|
|
1774
|
-
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
1775
|
-
const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);
|
|
1776
|
-
const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);
|
|
1777
|
-
mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
|
|
1836
|
+
return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0])
|
|
1778
1837
|
}
|
|
1779
1838
|
|
|
1780
|
-
|
|
1839
|
+
function _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
|
|
1840
|
+
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
|
1841
|
+
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
|
1842
|
+
const firstLine = ' '.repeat(Math.max(0, leftMiddle + 1))
|
|
1843
|
+
+ '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1))
|
|
1844
|
+
+ line
|
|
1845
|
+
+ '_'.repeat(Math.max(0, rightMiddle))
|
|
1846
|
+
+ ' '.repeat(Math.max(0, rightWidth - rightMiddle));
|
|
1847
|
+
|
|
1848
|
+
const secondLine = (leftHeight > 0 ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1) : ' '.repeat(leftWidth))
|
|
1849
|
+
+ ' '.repeat(width)
|
|
1850
|
+
+ (rightHeight > 0 ? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1) : ' '.repeat(rightWidth));
|
|
1851
|
+
|
|
1852
|
+
const mergedLines = [firstLine, secondLine];
|
|
1853
|
+
|
|
1854
|
+
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
|
1855
|
+
const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);
|
|
1856
|
+
const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);
|
|
1857
|
+
mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
return <NodeDisplayLayout>[mergedLines, leftWidth + width + rightWidth, Math.max(leftHeight, rightHeight) + 2, leftWidth + Math.floor(width / 2)];
|
|
1861
|
+
}
|
|
1781
1862
|
}
|
|
1782
1863
|
|
|
1783
1864
|
protected _defaultOneParamCallback = (node: N) => node.key;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
6
|
* @license MIT License
|
|
7
7
|
*/
|
|
8
|
-
import type {
|
|
8
|
+
import type { BSTNested, BSTNodeNested, BSTOptions, BTNCallback, BTNKey } from '../../types';
|
|
9
9
|
import { CP, IterationType } from '../../types';
|
|
10
10
|
import { BinaryTree, BinaryTreeNode } from './binary-tree';
|
|
11
11
|
import { IBinaryTree } from '../../interfaces';
|
|
@@ -62,9 +62,12 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>>
|
|
66
|
-
extends BinaryTree<V, N>
|
|
67
|
-
implements IBinaryTree<V, N> {
|
|
65
|
+
export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>, TREE extends BST<V, N, TREE> = BST<V, N, BSTNested<V, N>>>
|
|
66
|
+
extends BinaryTree<V, N, TREE>
|
|
67
|
+
implements IBinaryTree<V, N, TREE> {
|
|
68
|
+
|
|
69
|
+
override options: BSTOptions;
|
|
70
|
+
|
|
68
71
|
/**
|
|
69
72
|
* The constructor function initializes a binary search tree with an optional comparator function.
|
|
70
73
|
* @param {BSTOptions} [options] - An optional object that contains additional configuration options
|
|
@@ -72,13 +75,12 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
72
75
|
*/
|
|
73
76
|
constructor(options?: BSTOptions) {
|
|
74
77
|
super(options);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this._comparator = comparator;
|
|
80
|
-
}
|
|
78
|
+
if (options) {
|
|
79
|
+
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b, ...options }
|
|
80
|
+
} else {
|
|
81
|
+
this.options = { iterationType: IterationType.ITERATIVE, comparator: (a, b) => a - b };
|
|
81
82
|
}
|
|
83
|
+
this._root = undefined;
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
protected override _root?: N;
|
|
@@ -102,6 +104,10 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
102
104
|
return new BSTNode<V, N>(key, value) as N;
|
|
103
105
|
}
|
|
104
106
|
|
|
107
|
+
override createTree(options?: BSTOptions): TREE {
|
|
108
|
+
return new BST<V, N, TREE>({ ...this.options, ...options }) as TREE;
|
|
109
|
+
}
|
|
110
|
+
|
|
105
111
|
/**
|
|
106
112
|
* Time Complexity: O(log n) - Average case for a balanced tree. In the worst case (unbalanced tree), it can be O(n).
|
|
107
113
|
* Space Complexity: O(1) - Constant space is used.
|
|
@@ -215,7 +221,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
215
221
|
keysOrNodes: (BTNKey | N | undefined)[],
|
|
216
222
|
data?: (V | undefined)[],
|
|
217
223
|
isBalanceAdd = true,
|
|
218
|
-
iterationType = this.iterationType
|
|
224
|
+
iterationType = this.options.iterationType
|
|
219
225
|
): (N | undefined)[] {
|
|
220
226
|
// TODO this addMany function is inefficient, it should be optimized
|
|
221
227
|
function hasNoUndefined(arr: (BTNKey | N | undefined)[]): arr is (BTNKey | N)[] {
|
|
@@ -310,7 +316,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
310
316
|
* the key of the leftmost node if the comparison result is greater than, and the key of the
|
|
311
317
|
* rightmost node otherwise. If no node is found, it returns 0.
|
|
312
318
|
*/
|
|
313
|
-
lastKey(beginRoot: BTNKey | N | undefined = this.root, iterationType = this.iterationType): BTNKey {
|
|
319
|
+
lastKey(beginRoot: BTNKey | N | undefined = this.root, iterationType = this.options.iterationType): BTNKey {
|
|
314
320
|
if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
315
321
|
else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;
|
|
316
322
|
else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;
|
|
@@ -406,7 +412,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
406
412
|
callback: C = this._defaultOneParamCallback as C,
|
|
407
413
|
onlyOne = false,
|
|
408
414
|
beginRoot: BTNKey | N | undefined = this.root,
|
|
409
|
-
iterationType = this.iterationType
|
|
415
|
+
iterationType = this.options.iterationType
|
|
410
416
|
): N[] {
|
|
411
417
|
beginRoot = this.ensureNotKey(beginRoot);
|
|
412
418
|
if (!beginRoot) return [];
|
|
@@ -487,7 +493,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
487
493
|
callback: C = this._defaultOneParamCallback as C,
|
|
488
494
|
lesserOrGreater: CP = CP.lt,
|
|
489
495
|
targetNode: BTNKey | N | undefined = this.root,
|
|
490
|
-
iterationType = this.iterationType
|
|
496
|
+
iterationType = this.options.iterationType
|
|
491
497
|
): ReturnType<C>[] {
|
|
492
498
|
targetNode = this.ensureNotKey(targetNode);
|
|
493
499
|
const ans: ReturnType<BTNCallback<N>>[] = [];
|
|
@@ -550,7 +556,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
550
556
|
* values:
|
|
551
557
|
* @returns The function `perfectlyBalance` returns a boolean value.
|
|
552
558
|
*/
|
|
553
|
-
perfectlyBalance(iterationType = this.iterationType): boolean {
|
|
559
|
+
perfectlyBalance(iterationType = this.options.iterationType): boolean {
|
|
554
560
|
const sorted = this.dfs(node => node, 'in'),
|
|
555
561
|
n = sorted.length;
|
|
556
562
|
this.clear();
|
|
@@ -602,7 +608,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
602
608
|
* to check if the AVL tree is balanced. It can have two possible values:
|
|
603
609
|
* @returns a boolean value.
|
|
604
610
|
*/
|
|
605
|
-
isAVLBalanced(iterationType = this.iterationType): boolean {
|
|
611
|
+
isAVLBalanced(iterationType = this.options.iterationType): boolean {
|
|
606
612
|
if (!this.root) return true;
|
|
607
613
|
|
|
608
614
|
let balanced = true;
|
|
@@ -646,8 +652,6 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
646
652
|
return balanced;
|
|
647
653
|
}
|
|
648
654
|
|
|
649
|
-
protected _comparator: BSTComparator = (a, b) => a - b;
|
|
650
|
-
|
|
651
655
|
protected _setRoot(v: N | undefined) {
|
|
652
656
|
if (v) {
|
|
653
657
|
v.parent = undefined;
|
|
@@ -664,7 +668,7 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
|
|
|
664
668
|
* than), CP.lt (less than), or CP.eq (equal).
|
|
665
669
|
*/
|
|
666
670
|
protected _compare(a: BTNKey, b: BTNKey): CP {
|
|
667
|
-
const compared = this.
|
|
671
|
+
const compared = this.options.comparator!(a, b);
|
|
668
672
|
if (compared > 0) return CP.gt;
|
|
669
673
|
else if (compared < 0) return CP.lt;
|
|
670
674
|
else return CP.eq;
|