data-structure-typed 1.41.1 → 1.41.2
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/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +9 -9
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +2 -5
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +17 -2
- package/dist/cjs/data-structures/binary-tree/rb-tree.js +87 -20
- package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +9 -9
- package/dist/mjs/data-structures/binary-tree/binary-tree.js +1 -4
- package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +17 -2
- package/dist/mjs/data-structures/binary-tree/rb-tree.js +87 -20
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +5 -5
- package/src/data-structures/binary-tree/binary-tree.ts +13 -13
- package/src/data-structures/binary-tree/rb-tree.ts +94 -20
- package/test/integration/avl-tree.test.ts +3 -3
- package/test/integration/bst.test.ts +7 -7
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +174 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-structure-typed",
|
|
3
|
-
"version": "1.41.
|
|
3
|
+
"version": "1.41.2",
|
|
4
4
|
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/mjs/index.js",
|
|
@@ -61,17 +61,17 @@
|
|
|
61
61
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
62
62
|
"@typescript-eslint/parser": "^6.7.4",
|
|
63
63
|
"auto-changelog": "^2.4.0",
|
|
64
|
-
"avl-tree-typed": "^1.41.
|
|
64
|
+
"avl-tree-typed": "^1.41.1",
|
|
65
65
|
"benchmark": "^2.1.4",
|
|
66
|
-
"binary-tree-typed": "^1.41.
|
|
67
|
-
"bst-typed": "^1.41.
|
|
66
|
+
"binary-tree-typed": "^1.41.1",
|
|
67
|
+
"bst-typed": "^1.41.1",
|
|
68
68
|
"dependency-cruiser": "^14.1.0",
|
|
69
69
|
"eslint": "^8.50.0",
|
|
70
70
|
"eslint-config-prettier": "^9.0.0",
|
|
71
71
|
"eslint-import-resolver-alias": "^1.1.2",
|
|
72
72
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
73
73
|
"eslint-plugin-import": "^2.28.1",
|
|
74
|
-
"heap-typed": "^1.41.
|
|
74
|
+
"heap-typed": "^1.41.1",
|
|
75
75
|
"istanbul-badges-readme": "^1.8.5",
|
|
76
76
|
"jest": "^29.7.0",
|
|
77
77
|
"prettier": "^3.0.3",
|
|
@@ -559,21 +559,21 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
559
559
|
has<C extends BTNCallback<N, BTNKey>>(
|
|
560
560
|
identifier: BTNKey,
|
|
561
561
|
callback?: C,
|
|
562
|
-
beginRoot?: N,
|
|
562
|
+
beginRoot?: N | null,
|
|
563
563
|
iterationType?: IterationType
|
|
564
564
|
): boolean;
|
|
565
565
|
|
|
566
566
|
has<C extends BTNCallback<N, N>>(
|
|
567
567
|
identifier: N | null,
|
|
568
568
|
callback?: C,
|
|
569
|
-
beginRoot?: N,
|
|
569
|
+
beginRoot?: N | null,
|
|
570
570
|
iterationType?: IterationType
|
|
571
571
|
): boolean;
|
|
572
572
|
|
|
573
573
|
has<C extends BTNCallback<N>>(
|
|
574
574
|
identifier: ReturnType<C> | null,
|
|
575
575
|
callback: C,
|
|
576
|
-
beginRoot?: N,
|
|
576
|
+
beginRoot?: N | null,
|
|
577
577
|
iterationType?: IterationType
|
|
578
578
|
): boolean;
|
|
579
579
|
|
|
@@ -601,28 +601,28 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
601
601
|
iterationType = this.iterationType
|
|
602
602
|
): boolean {
|
|
603
603
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
604
|
-
|
|
604
|
+
|
|
605
605
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
|
|
606
606
|
}
|
|
607
607
|
|
|
608
608
|
getNode<C extends BTNCallback<N, BTNKey>>(
|
|
609
609
|
identifier: BTNKey,
|
|
610
610
|
callback?: C,
|
|
611
|
-
beginRoot?: N,
|
|
611
|
+
beginRoot?: N | null,
|
|
612
612
|
iterationType?: IterationType
|
|
613
613
|
): N | null;
|
|
614
614
|
|
|
615
615
|
getNode<C extends BTNCallback<N, N>>(
|
|
616
616
|
identifier: N | null,
|
|
617
617
|
callback?: C,
|
|
618
|
-
beginRoot?: N,
|
|
618
|
+
beginRoot?: N | null,
|
|
619
619
|
iterationType?: IterationType
|
|
620
620
|
): N | null;
|
|
621
621
|
|
|
622
622
|
getNode<C extends BTNCallback<N>>(
|
|
623
623
|
identifier: ReturnType<C>,
|
|
624
624
|
callback: C,
|
|
625
|
-
beginRoot?: N,
|
|
625
|
+
beginRoot?: N | null,
|
|
626
626
|
iterationType?: IterationType
|
|
627
627
|
): N | null;
|
|
628
628
|
|
|
@@ -648,28 +648,28 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
648
648
|
iterationType = this.iterationType
|
|
649
649
|
): N | null {
|
|
650
650
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
651
|
-
|
|
651
|
+
|
|
652
652
|
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
|
|
653
653
|
}
|
|
654
654
|
|
|
655
655
|
get<C extends BTNCallback<N, BTNKey>>(
|
|
656
656
|
identifier: BTNKey,
|
|
657
657
|
callback?: C,
|
|
658
|
-
beginRoot?: N,
|
|
658
|
+
beginRoot?: N | null,
|
|
659
659
|
iterationType?: IterationType
|
|
660
660
|
): V | undefined;
|
|
661
661
|
|
|
662
662
|
get<C extends BTNCallback<N, N>>(
|
|
663
663
|
identifier: N | null,
|
|
664
664
|
callback?: C,
|
|
665
|
-
beginRoot?: N,
|
|
665
|
+
beginRoot?: N | null,
|
|
666
666
|
iterationType?: IterationType
|
|
667
667
|
): V | undefined;
|
|
668
668
|
|
|
669
669
|
get<C extends BTNCallback<N>>(
|
|
670
670
|
identifier: ReturnType<C>,
|
|
671
671
|
callback: C,
|
|
672
|
-
beginRoot?: N,
|
|
672
|
+
beginRoot?: N | null,
|
|
673
673
|
iterationType?: IterationType
|
|
674
674
|
): V | undefined;
|
|
675
675
|
|
|
@@ -695,8 +695,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|
|
695
695
|
iterationType = this.iterationType
|
|
696
696
|
): V | undefined {
|
|
697
697
|
if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
|
|
698
|
-
|
|
699
|
-
return this.
|
|
698
|
+
|
|
699
|
+
return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;
|
|
700
700
|
}
|
|
701
701
|
|
|
702
702
|
/**
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* data-structure-typed
|
|
3
|
+
*
|
|
4
|
+
* @author Tyler Zeng
|
|
5
|
+
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
|
+
* @license MIT License
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
import {RBTNColor} from '../../types';
|
|
2
10
|
|
|
3
11
|
export class RBTreeNode {
|
|
@@ -16,11 +24,18 @@ export class RBTreeNode {
|
|
|
16
24
|
}
|
|
17
25
|
}
|
|
18
26
|
|
|
19
|
-
export const
|
|
27
|
+
export const NIL = new RBTreeNode(0);
|
|
20
28
|
|
|
29
|
+
/**
|
|
30
|
+
* 1. Each node is either red or black.
|
|
31
|
+
* 2. The root node is always black.
|
|
32
|
+
* 3. Leaf nodes are typically NIL nodes and are considered black.
|
|
33
|
+
* 4. Red nodes must have black children.
|
|
34
|
+
* 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.
|
|
35
|
+
*/
|
|
21
36
|
export class RedBlackTree {
|
|
22
37
|
constructor() {
|
|
23
|
-
this._root =
|
|
38
|
+
this._root = NIL;
|
|
24
39
|
}
|
|
25
40
|
|
|
26
41
|
protected _root: RBTreeNode;
|
|
@@ -38,13 +53,13 @@ export class RedBlackTree {
|
|
|
38
53
|
*/
|
|
39
54
|
insert(key: number): void {
|
|
40
55
|
const node: RBTreeNode = new RBTreeNode(key, RBTNColor.RED);
|
|
41
|
-
node.left =
|
|
42
|
-
node.right =
|
|
56
|
+
node.left = NIL;
|
|
57
|
+
node.right = NIL;
|
|
43
58
|
|
|
44
59
|
let y: RBTreeNode = null as unknown as RBTreeNode;
|
|
45
60
|
let x: RBTreeNode = this.root;
|
|
46
61
|
|
|
47
|
-
while (x !==
|
|
62
|
+
while (x !== NIL) {
|
|
48
63
|
y = x;
|
|
49
64
|
if (node.key < x.key) {
|
|
50
65
|
x = x.left;
|
|
@@ -83,9 +98,9 @@ export class RedBlackTree {
|
|
|
83
98
|
*/
|
|
84
99
|
delete(key: number): void {
|
|
85
100
|
const helper = (node: RBTreeNode): void => {
|
|
86
|
-
let z: RBTreeNode =
|
|
101
|
+
let z: RBTreeNode = NIL;
|
|
87
102
|
let x: RBTreeNode, y: RBTreeNode;
|
|
88
|
-
while (node !==
|
|
103
|
+
while (node !== NIL) {
|
|
89
104
|
if (node.key === key) {
|
|
90
105
|
z = node;
|
|
91
106
|
}
|
|
@@ -97,16 +112,16 @@ export class RedBlackTree {
|
|
|
97
112
|
}
|
|
98
113
|
}
|
|
99
114
|
|
|
100
|
-
if (z ===
|
|
115
|
+
if (z === NIL) {
|
|
101
116
|
return;
|
|
102
117
|
}
|
|
103
118
|
|
|
104
119
|
y = z;
|
|
105
120
|
let yOriginalColor: number = y.color;
|
|
106
|
-
if (z.left ===
|
|
121
|
+
if (z.left === NIL) {
|
|
107
122
|
x = z.right;
|
|
108
123
|
this._rbTransplant(z, z.right);
|
|
109
|
-
} else if (z.right ===
|
|
124
|
+
} else if (z.right === NIL) {
|
|
110
125
|
x = z.left;
|
|
111
126
|
this._rbTransplant(z, z.left);
|
|
112
127
|
} else {
|
|
@@ -133,8 +148,8 @@ export class RedBlackTree {
|
|
|
133
148
|
helper(this.root);
|
|
134
149
|
}
|
|
135
150
|
|
|
136
|
-
isRealNode(node: RBTreeNode): node is RBTreeNode {
|
|
137
|
-
return node !==
|
|
151
|
+
isRealNode(node: RBTreeNode | null | undefined): node is RBTreeNode {
|
|
152
|
+
return node !== NIL && node !== null;
|
|
138
153
|
}
|
|
139
154
|
|
|
140
155
|
/**
|
|
@@ -170,7 +185,7 @@ export class RedBlackTree {
|
|
|
170
185
|
* @returns The leftmost node in the given RBTreeNode.
|
|
171
186
|
*/
|
|
172
187
|
getLeftMost(node: RBTreeNode = this.root): RBTreeNode {
|
|
173
|
-
while (node.left !== null && node.left !==
|
|
188
|
+
while (node.left !== null && node.left !== NIL) {
|
|
174
189
|
node = node.left;
|
|
175
190
|
}
|
|
176
191
|
return node;
|
|
@@ -182,7 +197,7 @@ export class RedBlackTree {
|
|
|
182
197
|
* @returns the rightmost node in a red-black tree.
|
|
183
198
|
*/
|
|
184
199
|
getRightMost(node: RBTreeNode): RBTreeNode {
|
|
185
|
-
while (node.right !== null && node.right !==
|
|
200
|
+
while (node.right !== null && node.right !== NIL) {
|
|
186
201
|
node = node.right;
|
|
187
202
|
}
|
|
188
203
|
return node;
|
|
@@ -194,12 +209,12 @@ export class RedBlackTree {
|
|
|
194
209
|
* @returns the successor of the given RBTreeNode.
|
|
195
210
|
*/
|
|
196
211
|
getSuccessor(x: RBTreeNode): RBTreeNode {
|
|
197
|
-
if (x.right !==
|
|
212
|
+
if (x.right !== NIL) {
|
|
198
213
|
return this.getLeftMost(x.right);
|
|
199
214
|
}
|
|
200
215
|
|
|
201
216
|
let y: RBTreeNode = x.parent;
|
|
202
|
-
while (y !==
|
|
217
|
+
while (y !== NIL && y !== null && x === y.right) {
|
|
203
218
|
x = y;
|
|
204
219
|
y = y.parent;
|
|
205
220
|
}
|
|
@@ -213,12 +228,12 @@ export class RedBlackTree {
|
|
|
213
228
|
* @returns the predecessor of the given RBTreeNode 'x'.
|
|
214
229
|
*/
|
|
215
230
|
getPredecessor(x: RBTreeNode): RBTreeNode {
|
|
216
|
-
if (x.left !==
|
|
231
|
+
if (x.left !== NIL) {
|
|
217
232
|
return this.getRightMost(x.left);
|
|
218
233
|
}
|
|
219
234
|
|
|
220
235
|
let y: RBTreeNode = x.parent;
|
|
221
|
-
while (y !==
|
|
236
|
+
while (y !== NIL && x === y.left) {
|
|
222
237
|
x = y;
|
|
223
238
|
y = y.parent;
|
|
224
239
|
}
|
|
@@ -226,6 +241,65 @@ export class RedBlackTree {
|
|
|
226
241
|
return y;
|
|
227
242
|
}
|
|
228
243
|
|
|
244
|
+
print(beginRoot: RBTreeNode = this.root) {
|
|
245
|
+
const display = (root: RBTreeNode | null): void => {
|
|
246
|
+
const [lines, , ,] = _displayAux(root);
|
|
247
|
+
for (const line of lines) {
|
|
248
|
+
console.log(line);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const _displayAux = (node: RBTreeNode | null): [string[], number, number, number] => {
|
|
253
|
+
if (node === null) {
|
|
254
|
+
return [[], 0, 0, 0];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (node.right === null && node.left === null) {
|
|
258
|
+
const line = `${node.key}`;
|
|
259
|
+
const width = line.length;
|
|
260
|
+
const height = 1;
|
|
261
|
+
const middle = Math.floor(width / 2);
|
|
262
|
+
return [[line], width, height, middle];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (node.right === null) {
|
|
266
|
+
const [lines, n, p, x] = _displayAux(node.left);
|
|
267
|
+
const s = `${node.key}`;
|
|
268
|
+
const u = s.length;
|
|
269
|
+
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;
|
|
270
|
+
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);
|
|
271
|
+
const shifted_lines = lines.map(line => line + ' '.repeat(u));
|
|
272
|
+
return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (node.left === null) {
|
|
276
|
+
const [lines, n, p, u] = _displayAux(node.right);
|
|
277
|
+
const s = `${node.key}`;
|
|
278
|
+
const x = s.length;
|
|
279
|
+
const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);
|
|
280
|
+
const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1);
|
|
281
|
+
const shifted_lines = lines.map(line => ' '.repeat(u) + line);
|
|
282
|
+
return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const [left, n, p, x] = _displayAux(node.left);
|
|
286
|
+
const [right, m, q, y] = _displayAux(node.right);
|
|
287
|
+
const s = `${node.key}`;
|
|
288
|
+
const u = s.length;
|
|
289
|
+
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);
|
|
290
|
+
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1);
|
|
291
|
+
if (p < q) {
|
|
292
|
+
left.push(...new Array(q - p).fill(' '.repeat(n)));
|
|
293
|
+
} else if (q < p) {
|
|
294
|
+
right.push(...new Array(p - q).fill(' '.repeat(m)));
|
|
295
|
+
}
|
|
296
|
+
const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);
|
|
297
|
+
return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
display(beginRoot);
|
|
301
|
+
}
|
|
302
|
+
|
|
229
303
|
/**
|
|
230
304
|
* The function performs a left rotation on a red-black tree node.
|
|
231
305
|
* @param {RBTreeNode} x - The parameter `x` is a RBTreeNode object.
|
|
@@ -233,7 +307,7 @@ export class RedBlackTree {
|
|
|
233
307
|
protected _leftRotate(x: RBTreeNode): void {
|
|
234
308
|
const y: RBTreeNode = x.right;
|
|
235
309
|
x.right = y.left;
|
|
236
|
-
if (y.left !==
|
|
310
|
+
if (y.left !== NIL) {
|
|
237
311
|
y.left.parent = x;
|
|
238
312
|
}
|
|
239
313
|
y.parent = x.parent;
|
|
@@ -256,7 +330,7 @@ export class RedBlackTree {
|
|
|
256
330
|
protected _rightRotate(x: RBTreeNode): void {
|
|
257
331
|
const y: RBTreeNode = x.left;
|
|
258
332
|
x.left = y.right;
|
|
259
|
-
if (y.right !==
|
|
333
|
+
if (y.right !== NIL) {
|
|
260
334
|
y.right.parent = x;
|
|
261
335
|
}
|
|
262
336
|
y.parent = x.parent;
|
|
@@ -12,13 +12,13 @@ describe('AVL Tree Test', () => {
|
|
|
12
12
|
expect(node6 && tree.getHeight(node6)).toBe(3);
|
|
13
13
|
expect(node6 && tree.getDepth(node6)).toBe(1);
|
|
14
14
|
|
|
15
|
-
const
|
|
16
|
-
expect(
|
|
15
|
+
const getValueById = tree.get(10);
|
|
16
|
+
expect(getValueById).toBe(10);
|
|
17
17
|
|
|
18
18
|
const getMinNodeByRoot = tree.getLeftMost();
|
|
19
19
|
expect(getMinNodeByRoot?.key).toBe(1);
|
|
20
20
|
|
|
21
|
-
const node15 = tree.
|
|
21
|
+
const node15 = tree.getNode(15);
|
|
22
22
|
const getMinNodeBySpecificNode = node15 && tree.getLeftMost(node15);
|
|
23
23
|
expect(getMinNodeBySpecificNode?.key).toBe(12);
|
|
24
24
|
|
|
@@ -20,16 +20,16 @@ describe('Individual package BST operations test', () => {
|
|
|
20
20
|
expect(node6 && bst.getHeight(6)).toBe(2);
|
|
21
21
|
expect(node6 && bst.getDepth(6)).toBe(3);
|
|
22
22
|
|
|
23
|
-
const nodeId10 = bst.
|
|
23
|
+
const nodeId10 = bst.getNode(10);
|
|
24
24
|
expect(nodeId10?.key).toBe(10);
|
|
25
25
|
|
|
26
|
-
const nodeVal9 = bst.
|
|
26
|
+
const nodeVal9 = bst.getNode(9, node => node.value);
|
|
27
27
|
expect(nodeVal9?.key).toBe(9);
|
|
28
28
|
|
|
29
29
|
const leftMost = bst.getLeftMost();
|
|
30
30
|
expect(leftMost?.key).toBe(1);
|
|
31
31
|
|
|
32
|
-
const node15 = bst.
|
|
32
|
+
const node15 = bst.getNode(15);
|
|
33
33
|
const minNodeBySpecificNode = node15 && bst.getLeftMost(node15);
|
|
34
34
|
expect(minNodeBySpecificNode?.key).toBe(12);
|
|
35
35
|
|
|
@@ -43,7 +43,7 @@ describe('Individual package BST operations test', () => {
|
|
|
43
43
|
|
|
44
44
|
expect(node15).toBeInstanceOf(BSTNode);
|
|
45
45
|
|
|
46
|
-
const node11 = bst.
|
|
46
|
+
const node11 = bst.getNode(11);
|
|
47
47
|
expect(node11).toBeInstanceOf(BSTNode);
|
|
48
48
|
|
|
49
49
|
const dfsInorderNodes = bst.dfs(node => node, 'in');
|
|
@@ -216,7 +216,7 @@ describe('Individual package BST operations test', () => {
|
|
|
216
216
|
|
|
217
217
|
expect(objBST.has(6)).toBe(true);
|
|
218
218
|
|
|
219
|
-
const node6 = objBST.
|
|
219
|
+
const node6 = objBST.getNode(6);
|
|
220
220
|
expect(node6 && objBST.getHeight(node6)).toBe(2);
|
|
221
221
|
expect(node6 && objBST.getDepth(node6)).toBe(3);
|
|
222
222
|
|
|
@@ -229,7 +229,7 @@ describe('Individual package BST operations test', () => {
|
|
|
229
229
|
const leftMost = objBST.getLeftMost();
|
|
230
230
|
expect(leftMost?.key).toBe(1);
|
|
231
231
|
|
|
232
|
-
const node15 = objBST.
|
|
232
|
+
const node15 = objBST.getNode(15);
|
|
233
233
|
expect(node15?.value).toEqual({key: 15, keyA: 15});
|
|
234
234
|
const minNodeBySpecificNode = node15 && objBST.getLeftMost(node15);
|
|
235
235
|
expect(minNodeBySpecificNode?.key).toBe(12);
|
|
@@ -244,7 +244,7 @@ describe('Individual package BST operations test', () => {
|
|
|
244
244
|
|
|
245
245
|
expect(node15).toBeInstanceOf(BSTNode);
|
|
246
246
|
|
|
247
|
-
const node11 = objBST.
|
|
247
|
+
const node11 = objBST.getNode(11);
|
|
248
248
|
expect(node11).toBeInstanceOf(BSTNode);
|
|
249
249
|
|
|
250
250
|
const dfsInorderNodes = objBST.dfs(node => node, 'in');
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {RBTreeNode, RedBlackTree,
|
|
1
|
+
import {RBTNColor, RBTreeNode, RedBlackTree, NIL} from '../../../../src';
|
|
2
2
|
import {getRandomInt} from '../../../utils';
|
|
3
|
+
import {isDebugTest} from '../../../config';
|
|
4
|
+
|
|
5
|
+
const isDebug = isDebugTest;
|
|
3
6
|
|
|
4
7
|
describe('RedBlackTree', () => {
|
|
5
8
|
let tree: RedBlackTree;
|
|
@@ -63,7 +66,7 @@ describe('RedBlackTree', () => {
|
|
|
63
66
|
|
|
64
67
|
test('should handle an empty tree', () => {
|
|
65
68
|
const minNode = tree.getLeftMost(tree.root);
|
|
66
|
-
expect(minNode).toBe(
|
|
69
|
+
expect(minNode).toBe(NIL);
|
|
67
70
|
});
|
|
68
71
|
});
|
|
69
72
|
|
|
@@ -81,7 +84,7 @@ describe('RedBlackTree', () => {
|
|
|
81
84
|
|
|
82
85
|
test('should handle an empty tree', () => {
|
|
83
86
|
const maxNode = tree.getRightMost(tree.root);
|
|
84
|
-
expect(maxNode).toBe(
|
|
87
|
+
expect(maxNode).toBe(NIL);
|
|
85
88
|
});
|
|
86
89
|
});
|
|
87
90
|
|
|
@@ -105,7 +108,7 @@ describe('RedBlackTree', () => {
|
|
|
105
108
|
|
|
106
109
|
const node = tree.getNode(10);
|
|
107
110
|
const successorNode = tree.getSuccessor(node);
|
|
108
|
-
// TODO not sure if it should be null or
|
|
111
|
+
// TODO not sure if it should be null or NIL
|
|
109
112
|
expect(successorNode).toBe(null);
|
|
110
113
|
});
|
|
111
114
|
});
|
|
@@ -130,7 +133,7 @@ describe('RedBlackTree', () => {
|
|
|
130
133
|
|
|
131
134
|
const node = tree.getNode(20);
|
|
132
135
|
const predecessorNode = tree.getPredecessor(node);
|
|
133
|
-
// TODO not sure if it should be
|
|
136
|
+
// TODO not sure if it should be NIL or something else.
|
|
134
137
|
expect(predecessorNode).toBe(tree.getNode(10));
|
|
135
138
|
});
|
|
136
139
|
});
|
|
@@ -198,14 +201,146 @@ describe('RedBlackTree', () => {
|
|
|
198
201
|
expect(node.right.key).toBe(25);
|
|
199
202
|
});
|
|
200
203
|
|
|
201
|
-
it('should
|
|
204
|
+
it('should all node attributes fully conform to the red-black tree standards.', () => {
|
|
202
205
|
tree.insert(10);
|
|
203
206
|
tree.insert(20);
|
|
204
207
|
tree.insert(5);
|
|
205
208
|
tree.insert(15);
|
|
206
|
-
tree.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
tree.insert(21);
|
|
210
|
+
tree.insert(6);
|
|
211
|
+
tree.insert(2);
|
|
212
|
+
|
|
213
|
+
let node10F = tree.getNode(10);
|
|
214
|
+
let node20F = tree.getNode(20);
|
|
215
|
+
let node5F = tree.getNode(5);
|
|
216
|
+
let node15F = tree.getNode(15);
|
|
217
|
+
let node21F = tree.getNode(21);
|
|
218
|
+
let node6F = tree.getNode(6);
|
|
219
|
+
let node2F = tree.getNode(2);
|
|
220
|
+
expect(node10F.key).toBe(10);
|
|
221
|
+
expect(node10F.color).toBe(RBTNColor.BLACK);
|
|
222
|
+
expect(node10F.left).toBe(node5F);
|
|
223
|
+
expect(node10F.right).toBe(node20F);
|
|
224
|
+
expect(node10F.parent).toBe(null);
|
|
225
|
+
expect(node20F.key).toBe(20);
|
|
226
|
+
expect(node20F.color).toBe(RBTNColor.BLACK);
|
|
227
|
+
expect(node20F.left).toBe(node15F);
|
|
228
|
+
expect(node20F.right).toBe(node21F);
|
|
229
|
+
expect(node20F.parent).toBe(node10F);
|
|
230
|
+
expect(node5F.key).toBe(5);
|
|
231
|
+
expect(node5F.color).toBe(RBTNColor.BLACK);
|
|
232
|
+
expect(node5F.left).toBe(node2F);
|
|
233
|
+
expect(node5F.right).toBe(node6F);
|
|
234
|
+
expect(node5F.parent).toBe(node10F);
|
|
235
|
+
expect(node15F.key).toBe(15);
|
|
236
|
+
expect(node15F.color).toBe(RBTNColor.RED);
|
|
237
|
+
expect(node15F.left).toBe(NIL);
|
|
238
|
+
expect(node15F.right).toBe(NIL);
|
|
239
|
+
expect(node15F.parent).toBe(node20F);
|
|
240
|
+
expect(node21F.key).toBe(21);
|
|
241
|
+
expect(node21F.color).toBe(RBTNColor.RED);
|
|
242
|
+
expect(node21F.left).toBe(NIL);
|
|
243
|
+
expect(node21F.right).toBe(NIL);
|
|
244
|
+
expect(node21F.parent).toBe(node20F);
|
|
245
|
+
expect(node6F.key).toBe(6);
|
|
246
|
+
expect(node6F.color).toBe(RBTNColor.RED);
|
|
247
|
+
expect(node6F.left).toBe(NIL);
|
|
248
|
+
expect(node6F.right).toBe(NIL);
|
|
249
|
+
expect(node6F.parent).toBe(node5F);
|
|
250
|
+
expect(node2F.key).toBe(2);
|
|
251
|
+
expect(node2F.color).toBe(RBTNColor.RED);
|
|
252
|
+
expect(node2F.left).toBe(NIL);
|
|
253
|
+
expect(node2F.right).toBe(NIL);
|
|
254
|
+
expect(node2F.parent).toBe(node5F);
|
|
255
|
+
expect(node15F.key).toBe(15);
|
|
256
|
+
expect(node15F.color).toBe(RBTNColor.RED);
|
|
257
|
+
expect(node15F.left).toBe(NIL);
|
|
258
|
+
expect(node15F.right).toBe(NIL);
|
|
259
|
+
expect(node15F.parent).toBe(node20F);
|
|
260
|
+
tree.delete(5);
|
|
261
|
+
node10F = tree.getNode(10);
|
|
262
|
+
node20F = tree.getNode(20);
|
|
263
|
+
node5F = tree.getNode(5);
|
|
264
|
+
node15F = tree.getNode(15);
|
|
265
|
+
node21F = tree.getNode(21);
|
|
266
|
+
node6F = tree.getNode(6);
|
|
267
|
+
node2F = tree.getNode(2);
|
|
268
|
+
expect(node10F.key).toBe(10);
|
|
269
|
+
expect(node10F.color).toBe(RBTNColor.BLACK);
|
|
270
|
+
expect(node10F.left).toBe(node6F);
|
|
271
|
+
expect(node10F.right).toBe(node20F);
|
|
272
|
+
expect(node10F.parent).toBe(null);
|
|
273
|
+
expect(node20F.key).toBe(20);
|
|
274
|
+
expect(node20F.color).toBe(RBTNColor.BLACK);
|
|
275
|
+
expect(node20F.left).toBe(node15F);
|
|
276
|
+
expect(node20F.right).toBe(node21F);
|
|
277
|
+
expect(node20F.parent).toBe(node10F);
|
|
278
|
+
expect(node5F).toBe(null);
|
|
279
|
+
expect(node15F.key).toBe(15);
|
|
280
|
+
expect(node15F.color).toBe(RBTNColor.RED);
|
|
281
|
+
expect(node15F.left).toBe(NIL);
|
|
282
|
+
expect(node15F.right).toBe(NIL);
|
|
283
|
+
expect(node15F.parent).toBe(node20F);
|
|
284
|
+
expect(node21F.key).toBe(21);
|
|
285
|
+
expect(node21F.color).toBe(RBTNColor.RED);
|
|
286
|
+
expect(node21F.left).toBe(NIL);
|
|
287
|
+
expect(node21F.right).toBe(NIL);
|
|
288
|
+
expect(node21F.parent).toBe(node20F);
|
|
289
|
+
expect(node6F.key).toBe(6);
|
|
290
|
+
expect(node6F.color).toBe(RBTNColor.BLACK);
|
|
291
|
+
expect(node6F.left).toBe(node2F);
|
|
292
|
+
expect(node6F.right).toBe(NIL);
|
|
293
|
+
expect(node6F.parent).toBe(node10F);
|
|
294
|
+
expect(node2F.key).toBe(2);
|
|
295
|
+
expect(node2F.color).toBe(RBTNColor.RED);
|
|
296
|
+
expect(node2F.left).toBe(NIL);
|
|
297
|
+
expect(node2F.right).toBe(NIL);
|
|
298
|
+
expect(node2F.parent).toBe(node6F);
|
|
299
|
+
expect(node15F.key).toBe(15);
|
|
300
|
+
expect(node15F.color).toBe(RBTNColor.RED);
|
|
301
|
+
expect(node15F.left).toBe(NIL);
|
|
302
|
+
expect(node15F.right).toBe(NIL);
|
|
303
|
+
expect(node15F.parent).toBe(node20F);
|
|
304
|
+
tree.delete(20);
|
|
305
|
+
node10F = tree.getNode(10);
|
|
306
|
+
node20F = tree.getNode(20);
|
|
307
|
+
node5F = tree.getNode(5);
|
|
308
|
+
node15F = tree.getNode(15);
|
|
309
|
+
node21F = tree.getNode(21);
|
|
310
|
+
node6F = tree.getNode(6);
|
|
311
|
+
node2F = tree.getNode(2);
|
|
312
|
+
expect(node10F.key).toBe(10);
|
|
313
|
+
expect(node10F.color).toBe(RBTNColor.BLACK);
|
|
314
|
+
expect(node10F.left).toBe(node6F);
|
|
315
|
+
expect(node10F.right).toBe(node21F);
|
|
316
|
+
expect(node10F.parent).toBe(null);
|
|
317
|
+
expect(node20F).toBe(null);
|
|
318
|
+
expect(node5F).toBe(null);
|
|
319
|
+
expect(node15F.key).toBe(15);
|
|
320
|
+
expect(node15F.color).toBe(RBTNColor.RED);
|
|
321
|
+
expect(node15F.left).toBe(NIL);
|
|
322
|
+
expect(node15F.right).toBe(NIL);
|
|
323
|
+
expect(node15F.parent).toBe(node21F);
|
|
324
|
+
expect(node21F.key).toBe(21);
|
|
325
|
+
expect(node21F.color).toBe(RBTNColor.BLACK);
|
|
326
|
+
expect(node21F.left).toBe(node15F);
|
|
327
|
+
expect(node21F.right).toBe(NIL);
|
|
328
|
+
expect(node21F.parent).toBe(node10F);
|
|
329
|
+
expect(node6F.key).toBe(6);
|
|
330
|
+
expect(node6F.color).toBe(RBTNColor.BLACK);
|
|
331
|
+
expect(node6F.left).toBe(node2F);
|
|
332
|
+
expect(node6F.right).toBe(NIL);
|
|
333
|
+
expect(node6F.parent).toBe(node10F);
|
|
334
|
+
expect(node2F.key).toBe(2);
|
|
335
|
+
expect(node2F.color).toBe(RBTNColor.RED);
|
|
336
|
+
expect(node2F.left).toBe(NIL);
|
|
337
|
+
expect(node2F.right).toBe(NIL);
|
|
338
|
+
expect(node2F.parent).toBe(node6F);
|
|
339
|
+
expect(node15F.key).toBe(15);
|
|
340
|
+
expect(node15F.color).toBe(RBTNColor.RED);
|
|
341
|
+
expect(node15F.left).toBe(NIL);
|
|
342
|
+
expect(node15F.right).toBe(NIL);
|
|
343
|
+
expect(node15F.parent).toBe(node21F);
|
|
209
344
|
});
|
|
210
345
|
|
|
211
346
|
it('should fix the tree after insertion', () => {
|
|
@@ -214,8 +349,8 @@ describe('RedBlackTree', () => {
|
|
|
214
349
|
tree.insert(5);
|
|
215
350
|
tree.insert(15);
|
|
216
351
|
const node15F = tree.getNode(15);
|
|
217
|
-
expect(node15F.left).toBe(
|
|
218
|
-
expect(node15F.right).toBe(
|
|
352
|
+
expect(node15F.left).toBe(NIL);
|
|
353
|
+
expect(node15F.right).toBe(NIL);
|
|
219
354
|
expect(node15F.parent).toBe(tree.getNode(5));
|
|
220
355
|
|
|
221
356
|
tree.insert(25);
|
|
@@ -230,8 +365,8 @@ describe('RedBlackTree', () => {
|
|
|
230
365
|
tree.insert(155);
|
|
231
366
|
tree.insert(225);
|
|
232
367
|
const node225F = tree.getNode(225);
|
|
233
|
-
expect(node225F.left).toBe(
|
|
234
|
-
expect(node225F.right).toBe(
|
|
368
|
+
expect(node225F.left).toBe(NIL);
|
|
369
|
+
expect(node225F.right).toBe(NIL);
|
|
235
370
|
expect(node225F.parent.key).toBe(155);
|
|
236
371
|
tree.insert(7);
|
|
237
372
|
|
|
@@ -257,16 +392,38 @@ describe('RedBlackTree', () => {
|
|
|
257
392
|
const node50 = tree.getNode(50);
|
|
258
393
|
expect(node50.key).toBe(50);
|
|
259
394
|
expect(node50.left.key).toBe(33);
|
|
260
|
-
expect(node50.right).toBe(
|
|
395
|
+
expect(node50.right).toBe(NIL);
|
|
261
396
|
const node15Fo = tree.getNode(15);
|
|
262
397
|
|
|
263
398
|
expect(node15Fo.key).toBe(15);
|
|
264
|
-
expect(node15Fo.left).toBe(
|
|
399
|
+
expect(node15Fo.left).toBe(NIL);
|
|
265
400
|
const node225S = tree.getNode(225);
|
|
266
|
-
expect(node225S.left).toBe(
|
|
267
|
-
expect(node225S.right).toBe(
|
|
401
|
+
expect(node225S.left).toBe(NIL);
|
|
402
|
+
expect(node225S.right).toBe(NIL);
|
|
268
403
|
expect(node225S.parent.key).toBe(155);
|
|
269
404
|
expect(tree.getNode(0)).toBe(null);
|
|
405
|
+
tree.insert(1);
|
|
406
|
+
tree.insert(2);
|
|
407
|
+
tree.insert(3);
|
|
408
|
+
tree.insert(4);
|
|
409
|
+
tree.insert(5);
|
|
410
|
+
tree.insert(6);
|
|
411
|
+
tree.insert(7);
|
|
412
|
+
tree.insert(8);
|
|
413
|
+
tree.insert(9);
|
|
414
|
+
tree.insert(10);
|
|
415
|
+
tree.insert(11);
|
|
416
|
+
tree.insert(12);
|
|
417
|
+
tree.insert(13);
|
|
418
|
+
tree.insert(14);
|
|
419
|
+
tree.insert(15);
|
|
420
|
+
tree.insert(16);
|
|
421
|
+
tree.insert(17);
|
|
422
|
+
tree.insert(18);
|
|
423
|
+
tree.insert(19);
|
|
424
|
+
tree.insert(110);
|
|
425
|
+
|
|
426
|
+
isDebug && tree.print();
|
|
270
427
|
});
|
|
271
428
|
|
|
272
429
|
it('should fix the tree after insertion and deletion', () => {
|