mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
[rb-tree] The red-black tree has been perfectly implemented and inherits from a BST. It has also passed a certain level of testing. [binary-tree] All traversal methods are compatible with sentinel nodes in the red-black tree.
This commit is contained in:
parent
b78d92fcd1
commit
57a95e94db
|
@ -896,11 +896,11 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
if (cur !== undefined) {
|
||||
ans.push(callback(cur));
|
||||
if (includeNull) {
|
||||
cur !== null && cur.left !== undefined && _traverse(cur.left);
|
||||
cur !== null && cur.right !== undefined && _traverse(cur.right);
|
||||
cur && this.isNodeOrNull(cur.left) && _traverse(cur.left);
|
||||
cur && this.isNodeOrNull(cur.right) && _traverse(cur.right);
|
||||
} else {
|
||||
cur !== null && cur.left && _traverse(cur.left);
|
||||
cur !== null && cur.right && _traverse(cur.right);
|
||||
cur && cur.left && _traverse(cur.left);
|
||||
cur && cur.right && _traverse(cur.right);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -914,17 +914,29 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
if (cur !== undefined) {
|
||||
ans.push(callback(cur));
|
||||
if (includeNull) {
|
||||
cur !== null && cur.right !== undefined && stack.push(cur.right);
|
||||
cur !== null && cur.left !== undefined && stack.push(cur.left);
|
||||
cur && this.isNodeOrNull(cur.right) && stack.push(cur.right);
|
||||
cur && this.isNodeOrNull(cur.left) && stack.push(cur.left);
|
||||
} else {
|
||||
cur !== null && cur.right && stack.push(cur.right);
|
||||
cur !== null && cur.left && stack.push(cur.left);
|
||||
cur && cur.right && stack.push(cur.right);
|
||||
cur && cur.left && stack.push(cur.left);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
isNode(node: any): node is N {
|
||||
return node instanceof BinaryTreeNode && node.key.toString() !== 'NaN';
|
||||
}
|
||||
|
||||
isNIL(node: any) {
|
||||
return node instanceof BinaryTreeNode && node.key.toString() === 'NaN';
|
||||
}
|
||||
|
||||
isNodeOrNull(node: any): node is (N | null){
|
||||
return this.isNode(node) || node === null;
|
||||
}
|
||||
|
||||
dfs<C extends BTNCallback<N>>(
|
||||
callback?: C,
|
||||
|
@ -980,35 +992,35 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
switch (pattern) {
|
||||
case 'in':
|
||||
if (includeNull) {
|
||||
if (node && node.left !== undefined) _traverse(node.left);
|
||||
ans.push(callback(node));
|
||||
if (node && node.right !== undefined) _traverse(node.right);
|
||||
if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
|
||||
this.isNodeOrNull(node) && ans.push(callback(node));
|
||||
if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
|
||||
} else {
|
||||
if (node && node.left) _traverse(node.left);
|
||||
ans.push(callback(node));
|
||||
this.isNode(node) && ans.push(callback(node));
|
||||
if (node && node.right) _traverse(node.right);
|
||||
}
|
||||
break;
|
||||
case 'pre':
|
||||
if (includeNull) {
|
||||
ans.push(callback(node));
|
||||
if (node && node.left !== undefined) _traverse(node.left);
|
||||
if (node && node.right !== undefined) _traverse(node.right);
|
||||
this.isNodeOrNull(node) && ans.push(callback(node));
|
||||
if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
|
||||
if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
|
||||
} else {
|
||||
ans.push(callback(node));
|
||||
this.isNode(node) && ans.push(callback(node));
|
||||
if (node && node.left) _traverse(node.left);
|
||||
if (node && node.right) _traverse(node.right);
|
||||
}
|
||||
break;
|
||||
case 'post':
|
||||
if (includeNull) {
|
||||
if (node && node.left !== undefined) _traverse(node.left);
|
||||
if (node && node.right !== undefined) _traverse(node.right);
|
||||
ans.push(callback(node));
|
||||
if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
|
||||
if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
|
||||
this.isNodeOrNull(node) && ans.push(callback(node));
|
||||
} else {
|
||||
if (node && node.left) _traverse(node.left);
|
||||
if (node && node.right) _traverse(node.right);
|
||||
ans.push(callback(node));
|
||||
this.isNode(node) && ans.push(callback(node));
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1022,7 +1034,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
|
||||
while (stack.length > 0) {
|
||||
const cur = stack.pop();
|
||||
if (cur === undefined) continue;
|
||||
if (cur === undefined || this.isNIL(cur.node)) continue;
|
||||
if (includeNull) {
|
||||
if (cur.node === undefined) continue;
|
||||
} else {
|
||||
|
@ -1115,8 +1127,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
ans.push(callback(current));
|
||||
|
||||
if (includeNull) {
|
||||
if (current && current.left !== undefined) queue.push(current.left);
|
||||
if (current && current.right !== undefined) queue.push(current.right);
|
||||
if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
|
||||
if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
|
||||
} else {
|
||||
if (current.left) queue.push(current.left);
|
||||
if (current.right) queue.push(current.right);
|
||||
|
@ -1136,8 +1148,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
ans.push(callback(current));
|
||||
|
||||
if (includeNull) {
|
||||
if (current !== null && current.left !== undefined) queue.push(current.left);
|
||||
if (current !== null && current.right !== undefined) queue.push(current.right);
|
||||
if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
|
||||
if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
|
||||
} else {
|
||||
if (current.left) queue.push(current.left);
|
||||
if (current.right) queue.push(current.right);
|
||||
|
@ -1199,8 +1211,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
if (!levelsNodes[level]) levelsNodes[level] = [];
|
||||
levelsNodes[level].push(callback(node));
|
||||
if (includeNull) {
|
||||
if (node && node.left !== undefined) _recursive(node.left, level + 1);
|
||||
if (node && node.right !== undefined) _recursive(node.right, level + 1);
|
||||
if (node && this.isNodeOrNull(node.left)) _recursive(node.left, level + 1);
|
||||
if (node && this.isNodeOrNull(node.right)) _recursive(node.right, level + 1);
|
||||
} else {
|
||||
if (node && node.left) _recursive(node.left, level + 1);
|
||||
if (node && node.right) _recursive(node.right, level + 1);
|
||||
|
@ -1219,8 +1231,8 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
levelsNodes[level].push(callback(node));
|
||||
|
||||
if (includeNull) {
|
||||
if (node && node.right !== undefined) stack.push([node.right, level + 1]);
|
||||
if (node && node.left !== undefined) stack.push([node.left, level + 1]);
|
||||
if (node && this.isNodeOrNull(node.right)) stack.push([node.right, level + 1]);
|
||||
if (node && this.isNodeOrNull(node.left)) stack.push([node.left, level + 1]);
|
||||
} else {
|
||||
if (node && node.right) stack.push([node.right, level + 1]);
|
||||
if (node && node.left) stack.push([node.left, level + 1]);
|
||||
|
|
|
@ -177,7 +177,7 @@ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RB
|
|||
return ans;
|
||||
}
|
||||
|
||||
isRealNode(node: N | undefined): node is N {
|
||||
isNode(node: N | undefined): node is N {
|
||||
return node !== this.NIL && node !== undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -403,21 +403,14 @@ describe('RedBlackTree', () => {
|
|||
expect(node225S?.parent?.key).toBe(155);
|
||||
// TODO
|
||||
// expect(tree.getNode(0)).toBe(undefined);
|
||||
tree.add(1);
|
||||
tree.add(2);
|
||||
tree.add(3);
|
||||
tree.add(4);
|
||||
tree.add(5);
|
||||
tree.add(6);
|
||||
tree.add(7);
|
||||
tree.add(8);
|
||||
tree.add(9);
|
||||
tree.add(10);
|
||||
tree.add(11);
|
||||
tree.add(12);
|
||||
tree.add(13);
|
||||
tree.add(14);
|
||||
tree.add(15);
|
||||
tree.add(16);
|
||||
tree.add(17);
|
||||
tree.add(18);
|
||||
|
@ -425,22 +418,48 @@ describe('RedBlackTree', () => {
|
|||
tree.add(110);
|
||||
|
||||
isDebug && tree.print();
|
||||
// console.log(tree.dfs())
|
||||
// console.log(tree.isBST())
|
||||
|
||||
expect(tree.dfs()).toEqual([
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18,
|
||||
19, 22, 23, 25, 28, 33, 50, 110, 111,
|
||||
155, 225
|
||||
])
|
||||
|
||||
expect(tree.isBST()).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
it('should fix the tree after insertion and deletion', () => {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
tree.add(getRandomInt(-100, 1000));
|
||||
for (let i = 0; i < 100; i++) {
|
||||
tree.add(i);
|
||||
}
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
tree.delete(getRandomInt(-100, 1000));
|
||||
for (let i = 0; i < 49; i++) {
|
||||
tree.delete(i);
|
||||
}
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
tree.add(getRandomInt(-100, 1000));
|
||||
tree.delete(getRandomInt(-100, 1000));
|
||||
}
|
||||
// console.log(tree.dfs( n => n.key, "in", tree.root, IterationType.RECURSIVE))
|
||||
|
||||
expect(tree.size).toBe(51);
|
||||
expect(tree.isBST()).toBe(true);
|
||||
expect(tree.dfs( n => n.key, "in", tree.root, IterationType.ITERATIVE)).toEqual([
|
||||
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
|
||||
71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
|
||||
82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
|
||||
93, 94, 95, 96, 97, 98, 99
|
||||
])
|
||||
});
|
||||
|
||||
it('should fix the tree after large scale insertion and deletion', () => {
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
tree.add(i);
|
||||
}
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
tree.delete(i);
|
||||
}
|
||||
|
||||
expect(tree.size).toBe(0);
|
||||
expect(tree.isBST()).toBe(true);
|
||||
expect(tree.dfs( n => n.key, "in", tree.root, IterationType.ITERATIVE)).toEqual([])
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue