data-structure-typed 1.50.8 → 1.50.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/CHANGELOG.md +1 -1
- package/README.md +73 -75
- package/benchmark/report.html +2 -2
- package/benchmark/report.json +15 -15
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +15 -3
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +14 -2
- package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +2 -2
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +11 -11
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +19 -2
- package/dist/cjs/data-structures/binary-tree/bst.js +20 -2
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +5 -5
- package/dist/cjs/data-structures/binary-tree/rb-tree.js +42 -44
- package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +40 -22
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +43 -27
- package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
- package/dist/cjs/data-structures/heap/heap.d.ts +1 -1
- package/dist/cjs/data-structures/heap/heap.js +5 -5
- package/dist/cjs/types/common.d.ts +1 -1
- package/dist/cjs/types/data-structures/binary-tree/rb-tree.d.ts +1 -4
- package/dist/cjs/types/data-structures/binary-tree/rb-tree.js +0 -6
- package/dist/cjs/types/data-structures/binary-tree/rb-tree.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +15 -3
- package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js +14 -2
- package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +2 -2
- package/dist/mjs/data-structures/binary-tree/binary-tree.js +11 -11
- package/dist/mjs/data-structures/binary-tree/bst.d.ts +19 -2
- package/dist/mjs/data-structures/binary-tree/bst.js +20 -2
- package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +5 -5
- package/dist/mjs/data-structures/binary-tree/rb-tree.js +42 -44
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.d.ts +40 -22
- package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +43 -27
- package/dist/mjs/data-structures/heap/heap.d.ts +1 -1
- package/dist/mjs/data-structures/heap/heap.js +5 -5
- package/dist/mjs/types/common.d.ts +1 -1
- package/dist/mjs/types/data-structures/binary-tree/rb-tree.d.ts +1 -4
- package/dist/mjs/types/data-structures/binary-tree/rb-tree.js +1 -5
- package/dist/umd/data-structure-typed.js +135 -97
- package/dist/umd/data-structure-typed.min.js +2 -2
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +1 -1
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +17 -3
- package/src/data-structures/binary-tree/binary-tree.ts +36 -24
- package/src/data-structures/binary-tree/bst.ts +32 -11
- package/src/data-structures/binary-tree/rb-tree.ts +44 -44
- package/src/data-structures/binary-tree/tree-multi-map.ts +46 -27
- package/src/data-structures/heap/heap.ts +5 -5
- package/src/types/common.ts +1 -1
- package/src/types/data-structures/binary-tree/rb-tree.ts +1 -1
- package/test/integration/all-in-one.test.ts +2 -2
- package/test/performance/data-structures/binary-tree/avl-tree.test.ts +20 -15
- package/test/performance/data-structures/binary-tree/binary-tree.test.ts +1 -1
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +7 -7
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +4 -4
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +24 -24
- package/test/unit/data-structures/binary-tree/bst.test.ts +12 -12
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +25 -25
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +19 -19
- package/test/unit/data-structures/priority-queue/priority-queue.test.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.50.
|
|
3
|
+
"version": "1.50.9",
|
|
4
4
|
"description": "Javascript Data Structure. Heap, Binary Tree, Red Black Tree, Linked List, Deque, Trie, HashMap, Directed Graph, Undirected Graph, Binary Search Tree(BST), AVL Tree, Priority Queue, Graph, Queue, Tree Multiset, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue, Stack. Benchmark compared with C++ STL. API aligned with ES6 and Java.util. Usability is comparable to Python",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/mjs/index.js",
|
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
BinaryTreeDeleteResult,
|
|
13
13
|
BSTNKeyOrNode,
|
|
14
14
|
BTNCallback,
|
|
15
|
+
IterationType,
|
|
15
16
|
KeyOrNodeOrEntry
|
|
16
17
|
} from '../../types';
|
|
17
18
|
import { IBinaryTree } from '../../interfaces';
|
|
@@ -85,7 +86,20 @@ export class AVLTreeMultiMap<
|
|
|
85
86
|
return this._count;
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Time Complexity: O(n)
|
|
91
|
+
* Space Complexity: O(1)
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Time Complexity: O(n)
|
|
96
|
+
* Space Complexity: O(1)
|
|
97
|
+
*
|
|
98
|
+
* The function calculates the sum of the count property of all nodes in a tree using depth-first
|
|
99
|
+
* search.
|
|
100
|
+
* @returns the sum of the count property of all nodes in the tree.
|
|
101
|
+
*/
|
|
102
|
+
getComputedCount(): number {
|
|
89
103
|
let sum = 0;
|
|
90
104
|
this.dfs(node => (sum += node.count));
|
|
91
105
|
return sum;
|
|
@@ -316,8 +330,8 @@ export class AVLTreeMultiMap<
|
|
|
316
330
|
* values:
|
|
317
331
|
* @returns a boolean value.
|
|
318
332
|
*/
|
|
319
|
-
override perfectlyBalance(iterationType = this.iterationType): boolean {
|
|
320
|
-
const sorted = this.dfs(node => node, '
|
|
333
|
+
override perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
|
|
334
|
+
const sorted = this.dfs(node => node, 'IN'),
|
|
321
335
|
n = sorted.length;
|
|
322
336
|
if (sorted.length < 1) return false;
|
|
323
337
|
|
|
@@ -264,7 +264,10 @@ export class BinaryTree<
|
|
|
264
264
|
* @returns either the node corresponding to the given key if it is a valid node key, or the key
|
|
265
265
|
* itself if it is not a valid node key.
|
|
266
266
|
*/
|
|
267
|
-
ensureNode(
|
|
267
|
+
ensureNode(
|
|
268
|
+
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
|
|
269
|
+
iterationType: IterationType = 'ITERATIVE'
|
|
270
|
+
): NODE | null | undefined {
|
|
268
271
|
let res: NODE | null | undefined;
|
|
269
272
|
if (this.isRealNode(keyOrNodeOrEntry)) {
|
|
270
273
|
res = keyOrNodeOrEntry;
|
|
@@ -594,7 +597,7 @@ export class BinaryTree<
|
|
|
594
597
|
callback: C = this._defaultOneParamCallback as C,
|
|
595
598
|
onlyOne = false,
|
|
596
599
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
597
|
-
iterationType = this.iterationType
|
|
600
|
+
iterationType: IterationType = this.iterationType
|
|
598
601
|
): NODE[] {
|
|
599
602
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
600
603
|
callback = (node => node) as C;
|
|
@@ -684,7 +687,7 @@ export class BinaryTree<
|
|
|
684
687
|
identifier: ReturnType<C> | null | undefined,
|
|
685
688
|
callback: C = this._defaultOneParamCallback as C,
|
|
686
689
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
687
|
-
iterationType = this.iterationType
|
|
690
|
+
iterationType: IterationType = this.iterationType
|
|
688
691
|
): NODE | null | undefined {
|
|
689
692
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
690
693
|
callback = (node => node) as C;
|
|
@@ -711,7 +714,7 @@ export class BinaryTree<
|
|
|
711
714
|
* @returns The function `getNodeByKey` returns a node (`NODE`) if a node with the specified key is
|
|
712
715
|
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
713
716
|
*/
|
|
714
|
-
getNodeByKey(key: K, iterationType = 'ITERATIVE'): NODE | undefined {
|
|
717
|
+
getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined {
|
|
715
718
|
if (!this.root) return undefined;
|
|
716
719
|
if (iterationType === 'RECURSIVE') {
|
|
717
720
|
const _dfs = (cur: NODE): NODE | undefined => {
|
|
@@ -788,7 +791,7 @@ export class BinaryTree<
|
|
|
788
791
|
identifier: ReturnType<C> | null | undefined,
|
|
789
792
|
callback: C = this._defaultOneParamCallback as C,
|
|
790
793
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
791
|
-
iterationType = this.iterationType
|
|
794
|
+
iterationType: IterationType = this.iterationType
|
|
792
795
|
): V | undefined {
|
|
793
796
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
794
797
|
callback = (node => node) as C;
|
|
@@ -847,7 +850,7 @@ export class BinaryTree<
|
|
|
847
850
|
identifier: ReturnType<C> | null | undefined,
|
|
848
851
|
callback: C = this._defaultOneParamCallback as C,
|
|
849
852
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
850
|
-
iterationType = this.iterationType
|
|
853
|
+
iterationType: IterationType = this.iterationType
|
|
851
854
|
): boolean {
|
|
852
855
|
if ((!callback || callback === this._defaultOneParamCallback) && (identifier as any) instanceof BinaryTreeNode)
|
|
853
856
|
callback = (node => node) as C;
|
|
@@ -924,7 +927,10 @@ export class BinaryTree<
|
|
|
924
927
|
* possible values:
|
|
925
928
|
* @returns a boolean value.
|
|
926
929
|
*/
|
|
927
|
-
isBST(
|
|
930
|
+
isBST(
|
|
931
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
932
|
+
iterationType: IterationType = this.iterationType
|
|
933
|
+
): boolean {
|
|
928
934
|
// TODO there is a bug
|
|
929
935
|
beginRoot = this.ensureNode(beginRoot);
|
|
930
936
|
if (!beginRoot) return true;
|
|
@@ -1016,7 +1022,10 @@ export class BinaryTree<
|
|
|
1016
1022
|
* values:
|
|
1017
1023
|
* @returns the height of the binary tree.
|
|
1018
1024
|
*/
|
|
1019
|
-
getHeight(
|
|
1025
|
+
getHeight(
|
|
1026
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1027
|
+
iterationType: IterationType = this.iterationType
|
|
1028
|
+
): number {
|
|
1020
1029
|
beginRoot = this.ensureNode(beginRoot);
|
|
1021
1030
|
if (!this.isRealNode(beginRoot)) return -1;
|
|
1022
1031
|
|
|
@@ -1064,7 +1073,10 @@ export class BinaryTree<
|
|
|
1064
1073
|
* to calculate the minimum height of a binary tree. It can have two possible values:
|
|
1065
1074
|
* @returns The function `getMinHeight` returns the minimum height of a binary tree.
|
|
1066
1075
|
*/
|
|
1067
|
-
getMinHeight(
|
|
1076
|
+
getMinHeight(
|
|
1077
|
+
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1078
|
+
iterationType: IterationType = this.iterationType
|
|
1079
|
+
): number {
|
|
1068
1080
|
beginRoot = this.ensureNode(beginRoot);
|
|
1069
1081
|
if (!beginRoot) return -1;
|
|
1070
1082
|
|
|
@@ -1164,7 +1176,7 @@ export class BinaryTree<
|
|
|
1164
1176
|
*/
|
|
1165
1177
|
getLeftMost(
|
|
1166
1178
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1167
|
-
iterationType = this.iterationType
|
|
1179
|
+
iterationType: IterationType = this.iterationType
|
|
1168
1180
|
): NODE | null | undefined {
|
|
1169
1181
|
if (this.isNIL(beginRoot)) return beginRoot as NODE;
|
|
1170
1182
|
beginRoot = this.ensureNode(beginRoot);
|
|
@@ -1211,7 +1223,7 @@ export class BinaryTree<
|
|
|
1211
1223
|
*/
|
|
1212
1224
|
getRightMost(
|
|
1213
1225
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1214
|
-
iterationType = this.iterationType
|
|
1226
|
+
iterationType: IterationType = this.iterationType
|
|
1215
1227
|
): NODE | null | undefined {
|
|
1216
1228
|
if (this.isNIL(beginRoot)) return beginRoot as NODE;
|
|
1217
1229
|
// TODO support get right most by passing key in
|
|
@@ -1340,7 +1352,7 @@ export class BinaryTree<
|
|
|
1340
1352
|
*/
|
|
1341
1353
|
dfs<C extends BTNCallback<NODE | null | undefined>>(
|
|
1342
1354
|
callback: C = this._defaultOneParamCallback as C,
|
|
1343
|
-
pattern: DFSOrderPattern = '
|
|
1355
|
+
pattern: DFSOrderPattern = 'IN',
|
|
1344
1356
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1345
1357
|
iterationType: IterationType = 'ITERATIVE',
|
|
1346
1358
|
includeNull = false
|
|
@@ -1351,7 +1363,7 @@ export class BinaryTree<
|
|
|
1351
1363
|
if (iterationType === 'RECURSIVE') {
|
|
1352
1364
|
const _traverse = (node: NODE | null | undefined) => {
|
|
1353
1365
|
switch (pattern) {
|
|
1354
|
-
case '
|
|
1366
|
+
case 'IN':
|
|
1355
1367
|
if (includeNull) {
|
|
1356
1368
|
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left);
|
|
1357
1369
|
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
@@ -1362,7 +1374,7 @@ export class BinaryTree<
|
|
|
1362
1374
|
if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right);
|
|
1363
1375
|
}
|
|
1364
1376
|
break;
|
|
1365
|
-
case '
|
|
1377
|
+
case 'PRE':
|
|
1366
1378
|
if (includeNull) {
|
|
1367
1379
|
this.isNodeOrNull(node) && ans.push(callback(node));
|
|
1368
1380
|
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left);
|
|
@@ -1373,7 +1385,7 @@ export class BinaryTree<
|
|
|
1373
1385
|
if (this.isRealNode(node) && this.isRealNode(node.right)) _traverse(node.right);
|
|
1374
1386
|
}
|
|
1375
1387
|
break;
|
|
1376
|
-
case '
|
|
1388
|
+
case 'POST':
|
|
1377
1389
|
if (includeNull) {
|
|
1378
1390
|
if (this.isRealNode(node) && this.isNodeOrNull(node.left)) _traverse(node.left);
|
|
1379
1391
|
if (this.isRealNode(node) && this.isNodeOrNull(node.right)) _traverse(node.right);
|
|
@@ -1405,17 +1417,17 @@ export class BinaryTree<
|
|
|
1405
1417
|
ans.push(callback(cur.node));
|
|
1406
1418
|
} else {
|
|
1407
1419
|
switch (pattern) {
|
|
1408
|
-
case '
|
|
1420
|
+
case 'IN':
|
|
1409
1421
|
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1410
1422
|
stack.push({ opt: 1, node: cur.node });
|
|
1411
1423
|
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1412
1424
|
break;
|
|
1413
|
-
case '
|
|
1425
|
+
case 'PRE':
|
|
1414
1426
|
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1415
1427
|
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
1416
1428
|
stack.push({ opt: 1, node: cur.node });
|
|
1417
1429
|
break;
|
|
1418
|
-
case '
|
|
1430
|
+
case 'POST':
|
|
1419
1431
|
stack.push({ opt: 1, node: cur.node });
|
|
1420
1432
|
cur.node && stack.push({ opt: 0, node: cur.node.right });
|
|
1421
1433
|
cur.node && stack.push({ opt: 0, node: cur.node.left });
|
|
@@ -1476,7 +1488,7 @@ export class BinaryTree<
|
|
|
1476
1488
|
bfs<C extends BTNCallback<NODE | null>>(
|
|
1477
1489
|
callback: C = this._defaultOneParamCallback as C,
|
|
1478
1490
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1479
|
-
iterationType = this.iterationType,
|
|
1491
|
+
iterationType: IterationType = this.iterationType,
|
|
1480
1492
|
includeNull = false
|
|
1481
1493
|
): ReturnType<C>[] {
|
|
1482
1494
|
beginRoot = this.ensureNode(beginRoot);
|
|
@@ -1570,7 +1582,7 @@ export class BinaryTree<
|
|
|
1570
1582
|
listLevels<C extends BTNCallback<NODE | null>>(
|
|
1571
1583
|
callback: C = this._defaultOneParamCallback as C,
|
|
1572
1584
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
1573
|
-
iterationType = this.iterationType,
|
|
1585
|
+
iterationType: IterationType = this.iterationType,
|
|
1574
1586
|
includeNull = false
|
|
1575
1587
|
): ReturnType<C>[][] {
|
|
1576
1588
|
beginRoot = this.ensureNode(beginRoot);
|
|
@@ -1640,7 +1652,7 @@ export class BinaryTree<
|
|
|
1640
1652
|
*/
|
|
1641
1653
|
morris<C extends BTNCallback<NODE>>(
|
|
1642
1654
|
callback: C = this._defaultOneParamCallback as C,
|
|
1643
|
-
pattern: DFSOrderPattern = '
|
|
1655
|
+
pattern: DFSOrderPattern = 'IN',
|
|
1644
1656
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root
|
|
1645
1657
|
): ReturnType<C>[] {
|
|
1646
1658
|
beginRoot = this.ensureNode(beginRoot);
|
|
@@ -1669,7 +1681,7 @@ export class BinaryTree<
|
|
|
1669
1681
|
_reverseEdge(tail);
|
|
1670
1682
|
};
|
|
1671
1683
|
switch (pattern) {
|
|
1672
|
-
case '
|
|
1684
|
+
case 'IN':
|
|
1673
1685
|
while (cur) {
|
|
1674
1686
|
if (cur.left) {
|
|
1675
1687
|
const predecessor = this.getPredecessor(cur);
|
|
@@ -1685,7 +1697,7 @@ export class BinaryTree<
|
|
|
1685
1697
|
cur = cur.right;
|
|
1686
1698
|
}
|
|
1687
1699
|
break;
|
|
1688
|
-
case '
|
|
1700
|
+
case 'PRE':
|
|
1689
1701
|
while (cur) {
|
|
1690
1702
|
if (cur.left) {
|
|
1691
1703
|
const predecessor = this.getPredecessor(cur);
|
|
@@ -1703,7 +1715,7 @@ export class BinaryTree<
|
|
|
1703
1715
|
cur = cur.right;
|
|
1704
1716
|
}
|
|
1705
1717
|
break;
|
|
1706
|
-
case '
|
|
1718
|
+
case 'POST':
|
|
1707
1719
|
while (cur) {
|
|
1708
1720
|
if (cur.left) {
|
|
1709
1721
|
const predecessor = this.getPredecessor(cur);
|
|
@@ -210,7 +210,10 @@ export class BST<
|
|
|
210
210
|
* type of iteration to be performed. It has a default value of `'ITERATIVE'`.
|
|
211
211
|
* @returns either a node object (NODE) or undefined.
|
|
212
212
|
*/
|
|
213
|
-
override ensureNode(
|
|
213
|
+
override ensureNode(
|
|
214
|
+
keyOrNodeOrEntry: KeyOrNodeOrEntry<K, V, NODE>,
|
|
215
|
+
iterationType: IterationType = 'ITERATIVE'
|
|
216
|
+
): NODE | undefined {
|
|
214
217
|
let res: NODE | undefined;
|
|
215
218
|
if (this.isRealNode(keyOrNodeOrEntry)) {
|
|
216
219
|
res = keyOrNodeOrEntry;
|
|
@@ -321,7 +324,7 @@ export class BST<
|
|
|
321
324
|
keysOrNodesOrEntries: Iterable<KeyOrNodeOrEntry<K, V, NODE>>,
|
|
322
325
|
values?: Iterable<V | undefined>,
|
|
323
326
|
isBalanceAdd = true,
|
|
324
|
-
iterationType = this.iterationType
|
|
327
|
+
iterationType: IterationType = this.iterationType
|
|
325
328
|
): boolean[] {
|
|
326
329
|
const inserted: boolean[] = [];
|
|
327
330
|
|
|
@@ -422,7 +425,8 @@ export class BST<
|
|
|
422
425
|
* @returns The function `getNodeByKey` returns a node (`NODE`) if a node with the specified key is
|
|
423
426
|
* found in the binary tree. If no node is found, it returns `undefined`.
|
|
424
427
|
*/
|
|
425
|
-
override getNodeByKey(key: K, iterationType = 'ITERATIVE'): NODE | undefined {
|
|
428
|
+
override getNodeByKey(key: K, iterationType: IterationType = 'ITERATIVE'): NODE | undefined {
|
|
429
|
+
// return this.getNodes(key, this._defaultOneParamCallback, true, this.root, iterationType)[0];
|
|
426
430
|
if (!this.isRealNode(this.root)) return undefined;
|
|
427
431
|
if (iterationType === 'RECURSIVE') {
|
|
428
432
|
const _dfs = (cur: NODE): NODE | undefined => {
|
|
@@ -480,7 +484,7 @@ export class BST<
|
|
|
480
484
|
callback: C = this._defaultOneParamCallback as C,
|
|
481
485
|
onlyOne = false,
|
|
482
486
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
483
|
-
iterationType = this.iterationType
|
|
487
|
+
iterationType: IterationType = this.iterationType
|
|
484
488
|
): NODE[] {
|
|
485
489
|
beginRoot = this.ensureNode(beginRoot);
|
|
486
490
|
if (!beginRoot) return [];
|
|
@@ -565,7 +569,7 @@ export class BST<
|
|
|
565
569
|
*/
|
|
566
570
|
override dfs<C extends BTNCallback<NODE>>(
|
|
567
571
|
callback: C = this._defaultOneParamCallback as C,
|
|
568
|
-
pattern: DFSOrderPattern = '
|
|
572
|
+
pattern: DFSOrderPattern = 'IN',
|
|
569
573
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
570
574
|
iterationType: IterationType = 'ITERATIVE'
|
|
571
575
|
): ReturnType<C>[] {
|
|
@@ -597,7 +601,7 @@ export class BST<
|
|
|
597
601
|
override bfs<C extends BTNCallback<NODE>>(
|
|
598
602
|
callback: C = this._defaultOneParamCallback as C,
|
|
599
603
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
600
|
-
iterationType = this.iterationType
|
|
604
|
+
iterationType: IterationType = this.iterationType
|
|
601
605
|
): ReturnType<C>[] {
|
|
602
606
|
return super.bfs(callback, beginRoot, iterationType, false);
|
|
603
607
|
}
|
|
@@ -628,7 +632,7 @@ export class BST<
|
|
|
628
632
|
override listLevels<C extends BTNCallback<NODE>>(
|
|
629
633
|
callback: C = this._defaultOneParamCallback as C,
|
|
630
634
|
beginRoot: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
631
|
-
iterationType = this.iterationType
|
|
635
|
+
iterationType: IterationType = this.iterationType
|
|
632
636
|
): ReturnType<C>[][] {
|
|
633
637
|
return super.listLevels(callback, beginRoot, iterationType, false);
|
|
634
638
|
}
|
|
@@ -699,7 +703,7 @@ export class BST<
|
|
|
699
703
|
callback: C = this._defaultOneParamCallback as C,
|
|
700
704
|
lesserOrGreater: CP = 'LT',
|
|
701
705
|
targetNode: KeyOrNodeOrEntry<K, V, NODE> = this.root,
|
|
702
|
-
iterationType = this.iterationType
|
|
706
|
+
iterationType: IterationType = this.iterationType
|
|
703
707
|
): ReturnType<C>[] {
|
|
704
708
|
targetNode = this.ensureNode(targetNode);
|
|
705
709
|
const ans: ReturnType<BTNCallback<NODE>>[] = [];
|
|
@@ -751,8 +755,8 @@ export class BST<
|
|
|
751
755
|
* values:
|
|
752
756
|
* @returns The function `perfectlyBalance` returns a boolean value.
|
|
753
757
|
*/
|
|
754
|
-
perfectlyBalance(iterationType = this.iterationType): boolean {
|
|
755
|
-
const sorted = this.dfs(node => node, '
|
|
758
|
+
perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
|
|
759
|
+
const sorted = this.dfs(node => node, 'IN'),
|
|
756
760
|
n = sorted.length;
|
|
757
761
|
this.clear();
|
|
758
762
|
|
|
@@ -812,7 +816,7 @@ export class BST<
|
|
|
812
816
|
* to check if the AVL tree is balanced. It can have two possible values:
|
|
813
817
|
* @returns a boolean value.
|
|
814
818
|
*/
|
|
815
|
-
isAVLBalanced(iterationType = this.iterationType): boolean {
|
|
819
|
+
isAVLBalanced(iterationType: IterationType = this.iterationType): boolean {
|
|
816
820
|
if (!this.root) return true;
|
|
817
821
|
|
|
818
822
|
let balanced = true;
|
|
@@ -884,6 +888,15 @@ export class BST<
|
|
|
884
888
|
return compared > 0 ? 'GT' : compared < 0 ? 'LT' : 'EQ';
|
|
885
889
|
}
|
|
886
890
|
|
|
891
|
+
/**
|
|
892
|
+
* The function `_lt` compares two values `a` and `b` using an extractor function and returns true if
|
|
893
|
+
* `a` is less than `b` based on the specified variant.
|
|
894
|
+
* @param {K} a - The parameter "a" is of type "K", which means it can be any type. It represents the
|
|
895
|
+
* first value to be compared in the function.
|
|
896
|
+
* @param {K} b - The parameter `b` is of type `K`, which means it can be any type. It is used as one
|
|
897
|
+
* of the arguments for the comparison in the `_lt` function.
|
|
898
|
+
* @returns a boolean value.
|
|
899
|
+
*/
|
|
887
900
|
protected _lt(a: K, b: K): boolean {
|
|
888
901
|
const extractedA = this.extractor(a);
|
|
889
902
|
const extractedB = this.extractor(b);
|
|
@@ -893,6 +906,14 @@ export class BST<
|
|
|
893
906
|
// return a < b;
|
|
894
907
|
}
|
|
895
908
|
|
|
909
|
+
/**
|
|
910
|
+
* The function compares two values using a custom extractor function and returns true if the first
|
|
911
|
+
* value is greater than the second value.
|
|
912
|
+
* @param {K} a - The parameter "a" is of type K, which means it can be any type.
|
|
913
|
+
* @param {K} b - The parameter "b" is of type K, which means it can be any type. It is used as one
|
|
914
|
+
* of the arguments for the comparison in the function.
|
|
915
|
+
* @returns a boolean value.
|
|
916
|
+
*/
|
|
896
917
|
protected _gt(a: K, b: K): boolean {
|
|
897
918
|
const extractedA = this.extractor(a);
|
|
898
919
|
const extractedB = this.extractor(b);
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
BinaryTreeDeleteResult,
|
|
3
3
|
BSTNKeyOrNode,
|
|
4
4
|
BTNCallback,
|
|
5
|
+
IterationType,
|
|
5
6
|
KeyOrNodeOrEntry,
|
|
6
7
|
RBTreeOptions,
|
|
7
8
|
RedBlackTreeNested,
|
|
@@ -25,9 +26,9 @@ export class RedBlackTreeNode<
|
|
|
25
26
|
* associated with the key in the Red-Black Tree Node. It is not required and can be omitted when
|
|
26
27
|
* creating a new instance of the Red-Black Tree Node.
|
|
27
28
|
* @param {RBTNColor} color - The `color` parameter is used to specify the color of the Red-Black
|
|
28
|
-
* Tree Node. It is an optional parameter with a default value of `
|
|
29
|
+
* Tree Node. It is an optional parameter with a default value of `'BLACK'`.
|
|
29
30
|
*/
|
|
30
|
-
constructor(key: K, value?: V, color: RBTNColor =
|
|
31
|
+
constructor(key: K, value?: V, color: RBTNColor = 'BLACK') {
|
|
31
32
|
super(key, value);
|
|
32
33
|
this._color = color;
|
|
33
34
|
}
|
|
@@ -106,12 +107,12 @@ export class RedBlackTree<
|
|
|
106
107
|
* @param {V} [value] - The `value` parameter is an optional parameter that represents the value
|
|
107
108
|
* associated with the key in the node. It is not required and can be omitted if not needed.
|
|
108
109
|
* @param {RBTNColor} color - The "color" parameter is used to specify the color of the node in a
|
|
109
|
-
* Red-Black Tree. It is an optional parameter with a default value of "
|
|
110
|
-
* can be either "
|
|
110
|
+
* Red-Black Tree. It is an optional parameter with a default value of "'BLACK'". The color
|
|
111
|
+
* can be either "'RED'" or "'BLACK'".
|
|
111
112
|
* @returns The method is returning a new instance of a RedBlackTreeNode with the specified key,
|
|
112
113
|
* value, and color.
|
|
113
114
|
*/
|
|
114
|
-
override createNode(key: K, value?: V, color: RBTNColor =
|
|
115
|
+
override createNode(key: K, value?: V, color: RBTNColor = 'BLACK'): NODE {
|
|
115
116
|
return new RedBlackTreeNode<K, V, NODE>(key, value, color) as NODE;
|
|
116
117
|
}
|
|
117
118
|
|
|
@@ -156,10 +157,10 @@ export class RedBlackTree<
|
|
|
156
157
|
if (key === undefined || key === null) {
|
|
157
158
|
return;
|
|
158
159
|
} else {
|
|
159
|
-
node = this.createNode(key, value,
|
|
160
|
+
node = this.createNode(key, value, 'RED');
|
|
160
161
|
}
|
|
161
162
|
} else if (!this.isNode(keyOrNodeOrEntry)) {
|
|
162
|
-
node = this.createNode(keyOrNodeOrEntry, value,
|
|
163
|
+
node = this.createNode(keyOrNodeOrEntry, value, 'RED');
|
|
163
164
|
} else {
|
|
164
165
|
return;
|
|
165
166
|
}
|
|
@@ -232,9 +233,8 @@ export class RedBlackTree<
|
|
|
232
233
|
identifier: ReturnType<C> | undefined,
|
|
233
234
|
callback: C = this._defaultOneParamCallback as C,
|
|
234
235
|
beginRoot: BSTNKeyOrNode<K, NODE> = this.root,
|
|
235
|
-
iterationType = this.iterationType
|
|
236
|
+
iterationType: IterationType = this.iterationType
|
|
236
237
|
): NODE | null | undefined {
|
|
237
|
-
// if ((identifier as any) instanceof RedBlackTreeNode) callback = (node => node) as C;
|
|
238
238
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
|
|
239
239
|
}
|
|
240
240
|
|
|
@@ -282,7 +282,7 @@ export class RedBlackTree<
|
|
|
282
282
|
if (insertStatus === 'CREATED') {
|
|
283
283
|
// Ensure the root is black
|
|
284
284
|
if (this.isRealNode(this._root)) {
|
|
285
|
-
this._root.color =
|
|
285
|
+
this._root.color = 'BLACK';
|
|
286
286
|
} else {
|
|
287
287
|
return false;
|
|
288
288
|
}
|
|
@@ -363,7 +363,7 @@ export class RedBlackTree<
|
|
|
363
363
|
this._size--;
|
|
364
364
|
|
|
365
365
|
// If the original color was black, fix the tree
|
|
366
|
-
if (originalColor ===
|
|
366
|
+
if (originalColor === 'BLACK') {
|
|
367
367
|
this._deleteFixup(replacementNode);
|
|
368
368
|
}
|
|
369
369
|
|
|
@@ -451,7 +451,7 @@ export class RedBlackTree<
|
|
|
451
451
|
|
|
452
452
|
node.left = this.SENTINEL;
|
|
453
453
|
node.right = this.SENTINEL;
|
|
454
|
-
node.color =
|
|
454
|
+
node.color = 'RED';
|
|
455
455
|
|
|
456
456
|
this._insertFixup(node);
|
|
457
457
|
return 'CREATED';
|
|
@@ -500,16 +500,16 @@ export class RedBlackTree<
|
|
|
500
500
|
*/
|
|
501
501
|
protected _insertFixup(z: NODE | undefined): void {
|
|
502
502
|
// Continue fixing the tree as long as the parent of z is red
|
|
503
|
-
while (z?.parent?.color ===
|
|
503
|
+
while (z?.parent?.color === 'RED') {
|
|
504
504
|
// Check if the parent of z is the left child of its parent
|
|
505
505
|
if (z.parent === z.parent.parent?.left) {
|
|
506
506
|
// Case 1: The uncle (y) of z is red
|
|
507
507
|
const y = z.parent.parent.right;
|
|
508
|
-
if (y?.color ===
|
|
508
|
+
if (y?.color === 'RED') {
|
|
509
509
|
// Set colors to restore properties of Red-Black Tree
|
|
510
|
-
z.parent.color =
|
|
511
|
-
y.color =
|
|
512
|
-
z.parent.parent.color =
|
|
510
|
+
z.parent.color = 'BLACK';
|
|
511
|
+
y.color = 'BLACK';
|
|
512
|
+
z.parent.parent.color = 'RED';
|
|
513
513
|
// Move up the tree to continue fixing
|
|
514
514
|
z = z.parent.parent;
|
|
515
515
|
} else {
|
|
@@ -523,8 +523,8 @@ export class RedBlackTree<
|
|
|
523
523
|
// Case 3: The uncle (y) of z is black, and z is a left child
|
|
524
524
|
// Adjust colors and perform a right rotation
|
|
525
525
|
if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {
|
|
526
|
-
z.parent.color =
|
|
527
|
-
z.parent.parent.color =
|
|
526
|
+
z.parent.color = 'BLACK';
|
|
527
|
+
z.parent.parent.color = 'RED';
|
|
528
528
|
this._rightRotate(z.parent.parent);
|
|
529
529
|
}
|
|
530
530
|
}
|
|
@@ -532,10 +532,10 @@ export class RedBlackTree<
|
|
|
532
532
|
// Symmetric case for the right child (left and right exchanged)
|
|
533
533
|
// Follow the same logic as above with left and right exchanged
|
|
534
534
|
const y: NODE | undefined = z?.parent?.parent?.left;
|
|
535
|
-
if (y?.color ===
|
|
536
|
-
z.parent.color =
|
|
537
|
-
y.color =
|
|
538
|
-
z.parent.parent!.color =
|
|
535
|
+
if (y?.color === 'RED') {
|
|
536
|
+
z.parent.color = 'BLACK';
|
|
537
|
+
y.color = 'BLACK';
|
|
538
|
+
z.parent.parent!.color = 'RED';
|
|
539
539
|
z = z.parent.parent;
|
|
540
540
|
} else {
|
|
541
541
|
if (z === z.parent.left) {
|
|
@@ -544,8 +544,8 @@ export class RedBlackTree<
|
|
|
544
544
|
}
|
|
545
545
|
|
|
546
546
|
if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {
|
|
547
|
-
z.parent.color =
|
|
548
|
-
z.parent.parent.color =
|
|
547
|
+
z.parent.color = 'BLACK';
|
|
548
|
+
z.parent.parent.color = 'RED';
|
|
549
549
|
this._leftRotate(z.parent.parent);
|
|
550
550
|
}
|
|
551
551
|
}
|
|
@@ -553,7 +553,7 @@ export class RedBlackTree<
|
|
|
553
553
|
}
|
|
554
554
|
|
|
555
555
|
// Ensure that the root is black after fixing
|
|
556
|
-
if (this.isRealNode(this._root)) this._root.color =
|
|
556
|
+
if (this.isRealNode(this._root)) this._root.color = 'BLACK';
|
|
557
557
|
}
|
|
558
558
|
|
|
559
559
|
/**
|
|
@@ -573,14 +573,14 @@ export class RedBlackTree<
|
|
|
573
573
|
*/
|
|
574
574
|
protected _deleteFixup(node: NODE | undefined): void {
|
|
575
575
|
// Early exit condition
|
|
576
|
-
if (!node || node === this.root || node.color ===
|
|
576
|
+
if (!node || node === this.root || node.color === 'BLACK') {
|
|
577
577
|
if (node) {
|
|
578
|
-
node.color =
|
|
578
|
+
node.color = 'BLACK'; // Ensure the final node is black
|
|
579
579
|
}
|
|
580
580
|
return;
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
-
while (node && node !== this.root && node.color ===
|
|
583
|
+
while (node && node !== this.root && node.color === 'BLACK') {
|
|
584
584
|
const parent: NODE | undefined = node.parent;
|
|
585
585
|
|
|
586
586
|
if (!parent) {
|
|
@@ -591,22 +591,22 @@ export class RedBlackTree<
|
|
|
591
591
|
let sibling = parent.right;
|
|
592
592
|
|
|
593
593
|
// Cases 1 and 2: Sibling is red or both children of sibling are black
|
|
594
|
-
if (sibling?.color ===
|
|
595
|
-
sibling.color =
|
|
596
|
-
parent.color =
|
|
594
|
+
if (sibling?.color === 'RED') {
|
|
595
|
+
sibling.color = 'BLACK';
|
|
596
|
+
parent.color = 'RED';
|
|
597
597
|
this._leftRotate(parent);
|
|
598
598
|
sibling = parent.right;
|
|
599
599
|
}
|
|
600
600
|
|
|
601
601
|
// Case 3: Sibling's left child is black
|
|
602
|
-
if ((sibling?.left?.color ??
|
|
603
|
-
if (sibling) sibling.color =
|
|
602
|
+
if ((sibling?.left?.color ?? 'BLACK') === 'BLACK') {
|
|
603
|
+
if (sibling) sibling.color = 'RED';
|
|
604
604
|
node = parent;
|
|
605
605
|
} else {
|
|
606
606
|
// Case 4: Adjust colors and perform a right rotation
|
|
607
|
-
if (sibling?.left) sibling.left.color =
|
|
607
|
+
if (sibling?.left) sibling.left.color = 'BLACK';
|
|
608
608
|
if (sibling) sibling.color = parent.color;
|
|
609
|
-
parent.color =
|
|
609
|
+
parent.color = 'BLACK';
|
|
610
610
|
this._rightRotate(parent);
|
|
611
611
|
node = this.root;
|
|
612
612
|
}
|
|
@@ -615,22 +615,22 @@ export class RedBlackTree<
|
|
|
615
615
|
let sibling = parent.left;
|
|
616
616
|
|
|
617
617
|
// Cases 1 and 2: Sibling is red or both children of sibling are black
|
|
618
|
-
if (sibling?.color ===
|
|
619
|
-
sibling.color =
|
|
620
|
-
if (parent) parent.color =
|
|
618
|
+
if (sibling?.color === 'RED') {
|
|
619
|
+
sibling.color = 'BLACK';
|
|
620
|
+
if (parent) parent.color = 'RED';
|
|
621
621
|
this._rightRotate(parent);
|
|
622
622
|
if (parent) sibling = parent.left;
|
|
623
623
|
}
|
|
624
624
|
|
|
625
625
|
// Case 3: Sibling's left child is black
|
|
626
|
-
if ((sibling?.right?.color ??
|
|
627
|
-
if (sibling) sibling.color =
|
|
626
|
+
if ((sibling?.right?.color ?? 'BLACK') === 'BLACK') {
|
|
627
|
+
if (sibling) sibling.color = 'RED';
|
|
628
628
|
node = parent;
|
|
629
629
|
} else {
|
|
630
630
|
// Case 4: Adjust colors and perform a left rotation
|
|
631
|
-
if (sibling?.right) sibling.right.color =
|
|
631
|
+
if (sibling?.right) sibling.right.color = 'BLACK';
|
|
632
632
|
if (sibling) sibling.color = parent.color;
|
|
633
|
-
if (parent) parent.color =
|
|
633
|
+
if (parent) parent.color = 'BLACK';
|
|
634
634
|
this._leftRotate(parent);
|
|
635
635
|
node = this.root;
|
|
636
636
|
}
|
|
@@ -639,7 +639,7 @@ export class RedBlackTree<
|
|
|
639
639
|
|
|
640
640
|
// Ensure that the final node (possibly the root) is black
|
|
641
641
|
if (node) {
|
|
642
|
-
node.color =
|
|
642
|
+
node.color = 'BLACK';
|
|
643
643
|
}
|
|
644
644
|
}
|
|
645
645
|
|