mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
[rb-tree] Change the default type of home nodes to 'undefined' and pass the test of adding and deleting 100,000 data records.
This commit is contained in:
parent
996fd128ed
commit
120b5e6bc2
|
@ -10,17 +10,14 @@ import {RBTNColor} from '../../types';
|
|||
|
||||
export class RBTreeNode {
|
||||
key: number;
|
||||
parent: RBTreeNode;
|
||||
left: RBTreeNode;
|
||||
right: RBTreeNode;
|
||||
color: number = RBTNColor.BLACK;
|
||||
parent?: RBTreeNode;
|
||||
left?: RBTreeNode;
|
||||
right?: RBTreeNode;
|
||||
color: number;
|
||||
|
||||
constructor(key: number, color: RBTNColor = RBTNColor.BLACK) {
|
||||
this.key = key;
|
||||
this.color = color;
|
||||
this.parent = null as unknown as RBTreeNode;
|
||||
this.left = null as unknown as RBTreeNode;
|
||||
this.right = null as unknown as RBTreeNode;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,20 +59,20 @@ export class RedBlackTree {
|
|||
node.left = NIL;
|
||||
node.right = NIL;
|
||||
|
||||
let y: RBTreeNode = null as unknown as RBTreeNode;
|
||||
let x: RBTreeNode = this.root;
|
||||
let y: RBTreeNode | undefined = undefined;
|
||||
let x: RBTreeNode | undefined = this.root;
|
||||
|
||||
while (x !== NIL) {
|
||||
y = x;
|
||||
if (node.key < x.key) {
|
||||
if (x && node.key < x.key) {
|
||||
x = x.left;
|
||||
} else {
|
||||
x = x.right;
|
||||
x = x?.right;
|
||||
}
|
||||
}
|
||||
|
||||
node.parent = y;
|
||||
if (y === null) {
|
||||
if (y === undefined) {
|
||||
this._root = node;
|
||||
} else if (node.key < y.key) {
|
||||
y.left = node;
|
||||
|
@ -83,13 +80,13 @@ export class RedBlackTree {
|
|||
y.right = node;
|
||||
}
|
||||
|
||||
if (node.parent === null) {
|
||||
if (node.parent === undefined) {
|
||||
node.color = RBTNColor.BLACK;
|
||||
this._size++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.parent.parent === null) {
|
||||
if (node.parent.parent === undefined) {
|
||||
this._size++;
|
||||
return;
|
||||
}
|
||||
|
@ -106,18 +103,18 @@ export class RedBlackTree {
|
|||
* @returns The `delete` function does not return anything. It has a return type of `void`.
|
||||
*/
|
||||
delete(key: number): void {
|
||||
const helper = (node: RBTreeNode): void => {
|
||||
const helper = (node: RBTreeNode | undefined): void => {
|
||||
let z: RBTreeNode = NIL;
|
||||
let x: RBTreeNode, y: RBTreeNode;
|
||||
let x: RBTreeNode | undefined, y: RBTreeNode;
|
||||
while (node !== NIL) {
|
||||
if (node.key === key) {
|
||||
if (node && node.key === key) {
|
||||
z = node;
|
||||
}
|
||||
|
||||
if (node.key <= key) {
|
||||
if (node && node.key <= key) {
|
||||
node = node.right;
|
||||
} else {
|
||||
node = node.left;
|
||||
node = node?.left;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,37 +127,37 @@ export class RedBlackTree {
|
|||
let yOriginalColor: number = y.color;
|
||||
if (z.left === NIL) {
|
||||
x = z.right;
|
||||
this._rbTransplant(z, z.right);
|
||||
this._rbTransplant(z, z.right!);
|
||||
} else if (z.right === NIL) {
|
||||
x = z.left;
|
||||
this._rbTransplant(z, z.left);
|
||||
this._rbTransplant(z, z.left!);
|
||||
} else {
|
||||
y = this.getLeftMost(z.right);
|
||||
yOriginalColor = y.color;
|
||||
x = y.right;
|
||||
if (y.parent === z) {
|
||||
x.parent = y;
|
||||
x!.parent = y;
|
||||
} else {
|
||||
this._rbTransplant(y, y.right);
|
||||
this._rbTransplant(y, y.right!);
|
||||
y.right = z.right;
|
||||
y.right.parent = y;
|
||||
y.right!.parent = y;
|
||||
}
|
||||
|
||||
this._rbTransplant(z, y);
|
||||
y.left = z.left;
|
||||
y.left.parent = y;
|
||||
y.left!.parent = y;
|
||||
y.color = z.color;
|
||||
}
|
||||
if (yOriginalColor === RBTNColor.BLACK) {
|
||||
this._fixDelete(x);
|
||||
this._fixDelete(x!);
|
||||
}
|
||||
this._size--;
|
||||
};
|
||||
helper(this.root);
|
||||
}
|
||||
|
||||
isRealNode(node: RBTreeNode | null | undefined): node is RBTreeNode {
|
||||
return node !== NIL && node !== null;
|
||||
isRealNode(node: RBTreeNode | undefined): node is RBTreeNode {
|
||||
return node !== NIL && node !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -173,17 +170,17 @@ export class RedBlackTree {
|
|||
* defaults to the root of the binary search tree (`this.root`).
|
||||
* @returns a RBTreeNode.
|
||||
*/
|
||||
getNode(key: number, beginRoot = this.root): RBTreeNode {
|
||||
const dfs = (node: RBTreeNode): RBTreeNode => {
|
||||
getNode(key: number, beginRoot = this.root): RBTreeNode | undefined {
|
||||
const dfs = (node: RBTreeNode): RBTreeNode | undefined => {
|
||||
if (this.isRealNode(node)) {
|
||||
if (key === node.key) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (key < node.key) return dfs(node.left);
|
||||
return dfs(node.right);
|
||||
if (key < node.key) return dfs(node.left!);
|
||||
return dfs(node.right!);
|
||||
} else {
|
||||
return null as unknown as RBTreeNode;
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
return dfs(beginRoot);
|
||||
|
@ -196,7 +193,7 @@ export class RedBlackTree {
|
|||
* @returns The leftmost node in the given RBTreeNode.
|
||||
*/
|
||||
getLeftMost(node: RBTreeNode = this.root): RBTreeNode {
|
||||
while (node.left !== null && node.left !== NIL) {
|
||||
while (node.left !== undefined && node.left !== NIL) {
|
||||
node = node.left;
|
||||
}
|
||||
return node;
|
||||
|
@ -208,7 +205,7 @@ export class RedBlackTree {
|
|||
* @returns the rightmost node in a red-black tree.
|
||||
*/
|
||||
getRightMost(node: RBTreeNode): RBTreeNode {
|
||||
while (node.right !== null && node.right !== NIL) {
|
||||
while (node.right !== undefined && node.right !== NIL) {
|
||||
node = node.right;
|
||||
}
|
||||
return node;
|
||||
|
@ -219,13 +216,13 @@ export class RedBlackTree {
|
|||
* @param {RBTreeNode} x - RBTreeNode - The node for which we want to find the successor.
|
||||
* @returns the successor of the given RBTreeNode.
|
||||
*/
|
||||
getSuccessor(x: RBTreeNode): RBTreeNode {
|
||||
getSuccessor(x: RBTreeNode): RBTreeNode | undefined {
|
||||
if (x.right !== NIL) {
|
||||
return this.getLeftMost(x.right);
|
||||
}
|
||||
|
||||
let y: RBTreeNode = x.parent;
|
||||
while (y !== NIL && y !== null && x === y.right) {
|
||||
let y: RBTreeNode | undefined = x.parent;
|
||||
while (y !== NIL && y !== undefined && x === y.right) {
|
||||
x = y;
|
||||
y = y.parent;
|
||||
}
|
||||
|
@ -240,16 +237,16 @@ export class RedBlackTree {
|
|||
*/
|
||||
getPredecessor(x: RBTreeNode): RBTreeNode {
|
||||
if (x.left !== NIL) {
|
||||
return this.getRightMost(x.left);
|
||||
return this.getRightMost(x.left!);
|
||||
}
|
||||
|
||||
let y: RBTreeNode = x.parent;
|
||||
while (y !== NIL && x === y.left) {
|
||||
x = y;
|
||||
y = y.parent;
|
||||
let y: RBTreeNode | undefined = x.parent;
|
||||
while (y !== NIL && x === y!.left) {
|
||||
x = y!;
|
||||
y = y!.parent;
|
||||
}
|
||||
|
||||
return y;
|
||||
return y!;
|
||||
}
|
||||
|
||||
clear() {
|
||||
|
@ -258,19 +255,19 @@ export class RedBlackTree {
|
|||
}
|
||||
|
||||
print(beginRoot: RBTreeNode = this.root) {
|
||||
const display = (root: RBTreeNode | null): void => {
|
||||
const display = (root: RBTreeNode | undefined): void => {
|
||||
const [lines, , ,] = _displayAux(root);
|
||||
for (const line of lines) {
|
||||
console.log(line);
|
||||
}
|
||||
};
|
||||
|
||||
const _displayAux = (node: RBTreeNode | null): [string[], number, number, number] => {
|
||||
if (node === null) {
|
||||
const _displayAux = (node: RBTreeNode | undefined): [string[], number, number, number] => {
|
||||
if (node === undefined) {
|
||||
return [[], 0, 0, 0];
|
||||
}
|
||||
|
||||
if (node.right === null && node.left === null) {
|
||||
if (node.right === undefined && node.left === undefined) {
|
||||
const line = `${node.key}`;
|
||||
const width = line.length;
|
||||
const height = 1;
|
||||
|
@ -278,7 +275,7 @@ export class RedBlackTree {
|
|||
return [[line], width, height, middle];
|
||||
}
|
||||
|
||||
if (node.right === null) {
|
||||
if (node.right === undefined) {
|
||||
const [lines, n, p, x] = _displayAux(node.left);
|
||||
const s = `${node.key}`;
|
||||
const u = s.length;
|
||||
|
@ -288,7 +285,7 @@ export class RedBlackTree {
|
|||
return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];
|
||||
}
|
||||
|
||||
if (node.left === null) {
|
||||
if (node.left === undefined) {
|
||||
const [lines, n, p, u] = _displayAux(node.right);
|
||||
const s = `${node.key}`;
|
||||
const x = s.length;
|
||||
|
@ -321,21 +318,23 @@ export class RedBlackTree {
|
|||
* @param {RBTreeNode} x - The parameter `x` is a RBTreeNode object.
|
||||
*/
|
||||
protected _leftRotate(x: RBTreeNode): void {
|
||||
const y: RBTreeNode = x.right;
|
||||
x.right = y.left;
|
||||
if (y.left !== NIL) {
|
||||
y.left.parent = x;
|
||||
if (x.right) {
|
||||
const y: RBTreeNode = x.right;
|
||||
x.right = y.left;
|
||||
if (y.left !== NIL) {
|
||||
if (y.left) y.left.parent = x;
|
||||
}
|
||||
y.parent = x.parent;
|
||||
if (x.parent === undefined) {
|
||||
this._root = y;
|
||||
} else if (x === x.parent.left) {
|
||||
x.parent.left = y;
|
||||
} else {
|
||||
x.parent.right = y;
|
||||
}
|
||||
y.left = x;
|
||||
x.parent = y;
|
||||
}
|
||||
y.parent = x.parent;
|
||||
if (x.parent === null) {
|
||||
this._root = y;
|
||||
} else if (x === x.parent.left) {
|
||||
x.parent.left = y;
|
||||
} else {
|
||||
x.parent.right = y;
|
||||
}
|
||||
y.left = x;
|
||||
x.parent = y;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -344,21 +343,23 @@ export class RedBlackTree {
|
|||
* rotated.
|
||||
*/
|
||||
protected _rightRotate(x: RBTreeNode): void {
|
||||
const y: RBTreeNode = x.left;
|
||||
x.left = y.right;
|
||||
if (y.right !== NIL) {
|
||||
y.right.parent = x;
|
||||
if (x.left) {
|
||||
const y: RBTreeNode = x.left;
|
||||
x.left = y.right;
|
||||
if (y.right !== NIL) {
|
||||
if (y.right) y.right.parent = x;
|
||||
}
|
||||
y.parent = x.parent;
|
||||
if (x.parent === undefined) {
|
||||
this._root = y;
|
||||
} else if (x === x.parent.right) {
|
||||
x.parent.right = y;
|
||||
} else {
|
||||
x.parent.left = y;
|
||||
}
|
||||
y.right = x;
|
||||
x.parent = y;
|
||||
}
|
||||
y.parent = x.parent;
|
||||
if (x.parent === null) {
|
||||
this._root = y;
|
||||
} else if (x === x.parent.right) {
|
||||
x.parent.right = y;
|
||||
} else {
|
||||
x.parent.left = y;
|
||||
}
|
||||
y.right = x;
|
||||
x.parent = y;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -367,58 +368,58 @@ export class RedBlackTree {
|
|||
* red-black tree.
|
||||
*/
|
||||
protected _fixDelete(x: RBTreeNode): void {
|
||||
let s: RBTreeNode;
|
||||
let s: RBTreeNode | undefined;
|
||||
while (x !== this.root && x.color === RBTNColor.BLACK) {
|
||||
if (x === x.parent.left) {
|
||||
s = x.parent.right;
|
||||
if (x.parent && x === x.parent.left) {
|
||||
s = x.parent.right!;
|
||||
if (s.color === 1) {
|
||||
s.color = RBTNColor.BLACK;
|
||||
x.parent.color = RBTNColor.RED;
|
||||
this._leftRotate(x.parent);
|
||||
s = x.parent.right;
|
||||
s = x.parent.right!;
|
||||
}
|
||||
|
||||
if (s.left !== null && s.left.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
||||
if (s.left !== undefined && s.left.color === RBTNColor.BLACK && s.right && s.right.color === RBTNColor.BLACK) {
|
||||
s.color = RBTNColor.RED;
|
||||
x = x.parent;
|
||||
} else {
|
||||
if (s.right.color === RBTNColor.BLACK) {
|
||||
s.left.color = RBTNColor.BLACK;
|
||||
if (s.right && s.right.color === RBTNColor.BLACK) {
|
||||
if (s.left) s.left.color = RBTNColor.BLACK;
|
||||
s.color = RBTNColor.RED;
|
||||
this._rightRotate(s);
|
||||
s = x.parent.right;
|
||||
}
|
||||
|
||||
s.color = x.parent.color;
|
||||
if (s) s.color = x.parent.color;
|
||||
x.parent.color = RBTNColor.BLACK;
|
||||
s.right.color = RBTNColor.BLACK;
|
||||
if (s && s.right) s.right.color = RBTNColor.BLACK;
|
||||
this._leftRotate(x.parent);
|
||||
x = this.root;
|
||||
}
|
||||
} else {
|
||||
s = x.parent.left;
|
||||
s = x.parent!.left!;
|
||||
if (s.color === 1) {
|
||||
s.color = RBTNColor.BLACK;
|
||||
x.parent.color = RBTNColor.RED;
|
||||
this._rightRotate(x.parent);
|
||||
s = x.parent.left;
|
||||
x.parent!.color = RBTNColor.RED;
|
||||
this._rightRotate(x.parent!);
|
||||
s = x.parent!.left;
|
||||
}
|
||||
|
||||
if (s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
||||
if (s && s.right && s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
||||
s.color = RBTNColor.RED;
|
||||
x = x.parent;
|
||||
x = x.parent!;
|
||||
} else {
|
||||
if (s.left.color === RBTNColor.BLACK) {
|
||||
s.right.color = RBTNColor.BLACK;
|
||||
if (s && s.left && s.left.color === RBTNColor.BLACK) {
|
||||
if (s.right) s.right.color = RBTNColor.BLACK;
|
||||
s.color = RBTNColor.RED;
|
||||
this._leftRotate(s);
|
||||
s = x.parent.left;
|
||||
s = x.parent!.left;
|
||||
}
|
||||
|
||||
s.color = x.parent.color;
|
||||
x.parent.color = RBTNColor.BLACK;
|
||||
s.left.color = RBTNColor.BLACK;
|
||||
this._rightRotate(x.parent);
|
||||
if (s) s.color = x.parent!.color;
|
||||
x.parent!.color = RBTNColor.BLACK;
|
||||
if (s && s.left) s.left.color = RBTNColor.BLACK;
|
||||
this._rightRotate(x.parent!);
|
||||
x = this.root;
|
||||
}
|
||||
}
|
||||
|
@ -432,7 +433,7 @@ export class RedBlackTree {
|
|||
* @param {RBTreeNode} v - The parameter "v" is a RBTreeNode object.
|
||||
*/
|
||||
protected _rbTransplant(u: RBTreeNode, v: RBTreeNode): void {
|
||||
if (u.parent === null) {
|
||||
if (u.parent === undefined) {
|
||||
this._root = v;
|
||||
} else if (u === u.parent.left) {
|
||||
u.parent.left = v;
|
||||
|
@ -448,11 +449,11 @@ export class RedBlackTree {
|
|||
* red-black tree.
|
||||
*/
|
||||
protected _fixInsert(k: RBTreeNode): void {
|
||||
let u: RBTreeNode;
|
||||
while (k.parent.color === 1) {
|
||||
if (k.parent === k.parent.parent.right) {
|
||||
let u: RBTreeNode | undefined;
|
||||
while (k.parent && k.parent.color === 1) {
|
||||
if (k.parent.parent && k.parent === k.parent.parent.right) {
|
||||
u = k.parent.parent.left;
|
||||
if (u.color === 1) {
|
||||
if (u && u.color === 1) {
|
||||
u.color = RBTNColor.BLACK;
|
||||
k.parent.color = RBTNColor.BLACK;
|
||||
k.parent.parent.color = RBTNColor.RED;
|
||||
|
@ -463,27 +464,27 @@ export class RedBlackTree {
|
|||
this._rightRotate(k);
|
||||
}
|
||||
|
||||
k.parent.color = RBTNColor.BLACK;
|
||||
k.parent.parent.color = RBTNColor.RED;
|
||||
this._leftRotate(k.parent.parent);
|
||||
k.parent!.color = RBTNColor.BLACK;
|
||||
k.parent!.parent!.color = RBTNColor.RED;
|
||||
this._leftRotate(k.parent!.parent!);
|
||||
}
|
||||
} else {
|
||||
u = k.parent.parent.right;
|
||||
u = k.parent.parent!.right;
|
||||
|
||||
if (u.color === 1) {
|
||||
if (u && u.color === 1) {
|
||||
u.color = RBTNColor.BLACK;
|
||||
k.parent.color = RBTNColor.BLACK;
|
||||
k.parent.parent.color = RBTNColor.RED;
|
||||
k = k.parent.parent;
|
||||
k.parent.parent!.color = RBTNColor.RED;
|
||||
k = k.parent.parent!;
|
||||
} else {
|
||||
if (k === k.parent.right) {
|
||||
k = k.parent;
|
||||
this._leftRotate(k);
|
||||
}
|
||||
|
||||
k.parent.color = RBTNColor.BLACK;
|
||||
k.parent.parent.color = RBTNColor.RED;
|
||||
this._rightRotate(k.parent.parent);
|
||||
k.parent!.color = RBTNColor.BLACK;
|
||||
k.parent!.parent!.color = RBTNColor.RED;
|
||||
this._rightRotate(k.parent!.parent!);
|
||||
}
|
||||
}
|
||||
if (k === this.root) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {NIL, RBTNColor, RBTreeNode, RedBlackTree} from '../../../../src';
|
||||
import {getRandomInt} from '../../../utils';
|
||||
import {isDebugTest} from '../../../config';
|
||||
import * as console from "console";
|
||||
|
||||
const isDebug = isDebugTest;
|
||||
|
||||
|
@ -20,7 +21,7 @@ describe('RedBlackTree', () => {
|
|||
expect(tree.getNode(10)).toBeInstanceOf(RBTreeNode);
|
||||
expect(tree.getNode(20)).toBeInstanceOf(RBTreeNode);
|
||||
expect(tree.getNode(5)).toBeInstanceOf(RBTreeNode);
|
||||
expect(tree.getNode(15)).toBe(null);
|
||||
expect(tree.getNode(15)).toBe(undefined);
|
||||
});
|
||||
|
||||
test('should add and find nodes with negative keys', () => {
|
||||
|
@ -39,7 +40,7 @@ describe('RedBlackTree', () => {
|
|||
tree.add(5);
|
||||
tree.delete(20);
|
||||
|
||||
expect(tree.getNode(20)).toBe(null);
|
||||
expect(tree.getNode(20)).toBe(undefined);
|
||||
});
|
||||
|
||||
test('should handle deleting a non-existent node', () => {
|
||||
|
@ -48,7 +49,7 @@ describe('RedBlackTree', () => {
|
|||
tree.add(5);
|
||||
tree.delete(15);
|
||||
|
||||
expect(tree.getNode(15)).toBe(null);
|
||||
expect(tree.getNode(15)).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -97,9 +98,9 @@ describe('RedBlackTree', () => {
|
|||
tree.add(25);
|
||||
|
||||
const node = tree.getNode(15);
|
||||
const successorNode = tree.getSuccessor(node);
|
||||
const successorNode = tree.getSuccessor(node!);
|
||||
|
||||
expect(successorNode.key).toBe(20);
|
||||
expect(successorNode?.key).toBe(20);
|
||||
});
|
||||
|
||||
test('should handle a node with no getSuccessor', () => {
|
||||
|
@ -107,9 +108,9 @@ describe('RedBlackTree', () => {
|
|||
tree.add(5);
|
||||
|
||||
const node = tree.getNode(10);
|
||||
const successorNode = tree.getSuccessor(node);
|
||||
// TODO not sure if it should be null or NIL
|
||||
expect(successorNode).toBe(null);
|
||||
const successorNode = tree.getSuccessor(node!);
|
||||
// TODO not sure if it should be undefined or NIL
|
||||
expect(successorNode).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -122,9 +123,9 @@ describe('RedBlackTree', () => {
|
|||
tree.add(25);
|
||||
|
||||
const node = tree.getNode(20);
|
||||
const predecessorNode = tree.getPredecessor(node);
|
||||
const predecessorNode = tree.getPredecessor(node!);
|
||||
|
||||
expect(predecessorNode.key).toBe(15);
|
||||
expect(predecessorNode?.key).toBe(15);
|
||||
});
|
||||
|
||||
test('should handle a node with no getPredecessor', () => {
|
||||
|
@ -132,7 +133,7 @@ describe('RedBlackTree', () => {
|
|||
tree.add(20);
|
||||
|
||||
const node = tree.getNode(20);
|
||||
const predecessorNode = tree.getPredecessor(node);
|
||||
const predecessorNode = tree.getPredecessor(node!);
|
||||
// TODO not sure if it should be NIL or something else.
|
||||
expect(predecessorNode).toBe(tree.getNode(10));
|
||||
});
|
||||
|
@ -160,14 +161,14 @@ describe('RedBlackTree', () => {
|
|||
tree.add(20);
|
||||
tree.add(5);
|
||||
tree.delete(20);
|
||||
expect(tree.getNode(20)).toBe(null);
|
||||
expect(tree.getNode(20)).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should get the successor of a node', () => {
|
||||
tree.add(10);
|
||||
tree.add(20);
|
||||
const node = tree.getNode(10);
|
||||
const successor = tree.getSuccessor(node);
|
||||
const successor = tree.getSuccessor(node!);
|
||||
expect(successor?.key).toBe(20);
|
||||
});
|
||||
|
||||
|
@ -175,7 +176,7 @@ describe('RedBlackTree', () => {
|
|||
tree.add(10);
|
||||
tree.add(20);
|
||||
const node = tree.getNode(20);
|
||||
const predecessor = tree.getPredecessor(node);
|
||||
const predecessor = tree.getPredecessor(node!);
|
||||
expect(predecessor?.key).toBe(10);
|
||||
});
|
||||
|
||||
|
@ -186,8 +187,8 @@ describe('RedBlackTree', () => {
|
|||
const node = tree.getNode(10);
|
||||
tree.add(15);
|
||||
// Verify that rotation has occurred
|
||||
expect(node.left.key).toBe(5);
|
||||
expect(node.right.key).toBe(20);
|
||||
expect(node?.left?.key).toBe(5);
|
||||
expect(node?.right?.key).toBe(20);
|
||||
});
|
||||
|
||||
it('should rotate nodes to the right', () => {
|
||||
|
@ -197,8 +198,8 @@ describe('RedBlackTree', () => {
|
|||
const node = tree.getNode(20);
|
||||
tree.add(25);
|
||||
// Verify that rotation has occurred
|
||||
expect(node.left.key).toBe(0);
|
||||
expect(node.right.key).toBe(25);
|
||||
expect(node?.left?.key).toBe(0);
|
||||
expect(node?.right?.key).toBe(25);
|
||||
});
|
||||
|
||||
it('should all node attributes fully conform to the red-black tree standards.', () => {
|
||||
|
@ -217,46 +218,46 @@ describe('RedBlackTree', () => {
|
|||
let node21F = tree.getNode(21);
|
||||
let node6F = tree.getNode(6);
|
||||
let node2F = tree.getNode(2);
|
||||
expect(node10F.key).toBe(10);
|
||||
expect(node10F.color).toBe(RBTNColor.BLACK);
|
||||
expect(node10F.left).toBe(node5F);
|
||||
expect(node10F.right).toBe(node20F);
|
||||
expect(node10F.parent).toBe(null);
|
||||
expect(node20F.key).toBe(20);
|
||||
expect(node20F.color).toBe(RBTNColor.BLACK);
|
||||
expect(node20F.left).toBe(node15F);
|
||||
expect(node20F.right).toBe(node21F);
|
||||
expect(node20F.parent).toBe(node10F);
|
||||
expect(node5F.key).toBe(5);
|
||||
expect(node5F.color).toBe(RBTNColor.BLACK);
|
||||
expect(node5F.left).toBe(node2F);
|
||||
expect(node5F.right).toBe(node6F);
|
||||
expect(node5F.parent).toBe(node10F);
|
||||
expect(node15F.key).toBe(15);
|
||||
expect(node15F.color).toBe(RBTNColor.RED);
|
||||
expect(node15F.left).toBe(NIL);
|
||||
expect(node15F.right).toBe(NIL);
|
||||
expect(node15F.parent).toBe(node20F);
|
||||
expect(node21F.key).toBe(21);
|
||||
expect(node21F.color).toBe(RBTNColor.RED);
|
||||
expect(node21F.left).toBe(NIL);
|
||||
expect(node21F.right).toBe(NIL);
|
||||
expect(node21F.parent).toBe(node20F);
|
||||
expect(node6F.key).toBe(6);
|
||||
expect(node6F.color).toBe(RBTNColor.RED);
|
||||
expect(node6F.left).toBe(NIL);
|
||||
expect(node6F.right).toBe(NIL);
|
||||
expect(node6F.parent).toBe(node5F);
|
||||
expect(node2F.key).toBe(2);
|
||||
expect(node2F.color).toBe(RBTNColor.RED);
|
||||
expect(node2F.left).toBe(NIL);
|
||||
expect(node2F.right).toBe(NIL);
|
||||
expect(node2F.parent).toBe(node5F);
|
||||
expect(node15F.key).toBe(15);
|
||||
expect(node15F.color).toBe(RBTNColor.RED);
|
||||
expect(node15F.left).toBe(NIL);
|
||||
expect(node15F.right).toBe(NIL);
|
||||
expect(node15F.parent).toBe(node20F);
|
||||
expect(node10F?.key).toBe(10);
|
||||
expect(node10F?.color).toBe(RBTNColor.BLACK);
|
||||
expect(node10F?.left).toBe(node5F);
|
||||
expect(node10F?.right).toBe(node20F);
|
||||
expect(node10F?.parent).toBe(undefined);
|
||||
expect(node20F?.key).toBe(20);
|
||||
expect(node20F?.color).toBe(RBTNColor.BLACK);
|
||||
expect(node20F?.left).toBe(node15F);
|
||||
expect(node20F?.right).toBe(node21F);
|
||||
expect(node20F?.parent).toBe(node10F);
|
||||
expect(node5F?.key).toBe(5);
|
||||
expect(node5F?.color).toBe(RBTNColor.BLACK);
|
||||
expect(node5F?.left).toBe(node2F);
|
||||
expect(node5F?.right).toBe(node6F);
|
||||
expect(node5F?.parent).toBe(node10F);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(NIL);
|
||||
expect(node15F?.right).toBe(NIL);
|
||||
expect(node15F?.parent).toBe(node20F);
|
||||
expect(node21F?.key).toBe(21);
|
||||
expect(node21F?.color).toBe(RBTNColor.RED);
|
||||
expect(node21F?.left).toBe(NIL);
|
||||
expect(node21F?.right).toBe(NIL);
|
||||
expect(node21F?.parent).toBe(node20F);
|
||||
expect(node6F?.key).toBe(6);
|
||||
expect(node6F?.color).toBe(RBTNColor.RED);
|
||||
expect(node6F?.left).toBe(NIL);
|
||||
expect(node6F?.right).toBe(NIL);
|
||||
expect(node6F?.parent).toBe(node5F);
|
||||
expect(node2F?.key).toBe(2);
|
||||
expect(node2F?.color).toBe(RBTNColor.RED);
|
||||
expect(node2F?.left).toBe(NIL);
|
||||
expect(node2F?.right).toBe(NIL);
|
||||
expect(node2F?.parent).toBe(node5F);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(NIL);
|
||||
expect(node15F?.right).toBe(NIL);
|
||||
expect(node15F?.parent).toBe(node20F);
|
||||
tree.delete(5);
|
||||
node10F = tree.getNode(10);
|
||||
node20F = tree.getNode(20);
|
||||
|
@ -265,42 +266,42 @@ describe('RedBlackTree', () => {
|
|||
node21F = tree.getNode(21);
|
||||
node6F = tree.getNode(6);
|
||||
node2F = tree.getNode(2);
|
||||
expect(node10F.key).toBe(10);
|
||||
expect(node10F.color).toBe(RBTNColor.BLACK);
|
||||
expect(node10F.left).toBe(node6F);
|
||||
expect(node10F.right).toBe(node20F);
|
||||
expect(node10F.parent).toBe(null);
|
||||
expect(node20F.key).toBe(20);
|
||||
expect(node20F.color).toBe(RBTNColor.BLACK);
|
||||
expect(node20F.left).toBe(node15F);
|
||||
expect(node20F.right).toBe(node21F);
|
||||
expect(node20F.parent).toBe(node10F);
|
||||
expect(node5F).toBe(null);
|
||||
expect(node15F.key).toBe(15);
|
||||
expect(node15F.color).toBe(RBTNColor.RED);
|
||||
expect(node15F.left).toBe(NIL);
|
||||
expect(node15F.right).toBe(NIL);
|
||||
expect(node15F.parent).toBe(node20F);
|
||||
expect(node21F.key).toBe(21);
|
||||
expect(node21F.color).toBe(RBTNColor.RED);
|
||||
expect(node21F.left).toBe(NIL);
|
||||
expect(node21F.right).toBe(NIL);
|
||||
expect(node21F.parent).toBe(node20F);
|
||||
expect(node6F.key).toBe(6);
|
||||
expect(node6F.color).toBe(RBTNColor.BLACK);
|
||||
expect(node6F.left).toBe(node2F);
|
||||
expect(node6F.right).toBe(NIL);
|
||||
expect(node6F.parent).toBe(node10F);
|
||||
expect(node2F.key).toBe(2);
|
||||
expect(node2F.color).toBe(RBTNColor.RED);
|
||||
expect(node2F.left).toBe(NIL);
|
||||
expect(node2F.right).toBe(NIL);
|
||||
expect(node2F.parent).toBe(node6F);
|
||||
expect(node15F.key).toBe(15);
|
||||
expect(node15F.color).toBe(RBTNColor.RED);
|
||||
expect(node15F.left).toBe(NIL);
|
||||
expect(node15F.right).toBe(NIL);
|
||||
expect(node15F.parent).toBe(node20F);
|
||||
expect(node10F?.key).toBe(10);
|
||||
expect(node10F?.color).toBe(RBTNColor.BLACK);
|
||||
expect(node10F?.left).toBe(node6F);
|
||||
expect(node10F?.right).toBe(node20F);
|
||||
expect(node10F?.parent).toBe(undefined);
|
||||
expect(node20F?.key).toBe(20);
|
||||
expect(node20F?.color).toBe(RBTNColor.BLACK);
|
||||
expect(node20F?.left).toBe(node15F);
|
||||
expect(node20F?.right).toBe(node21F);
|
||||
expect(node20F?.parent).toBe(node10F);
|
||||
expect(node5F).toBe(undefined);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(NIL);
|
||||
expect(node15F?.right).toBe(NIL);
|
||||
expect(node15F?.parent).toBe(node20F);
|
||||
expect(node21F?.key).toBe(21);
|
||||
expect(node21F?.color).toBe(RBTNColor.RED);
|
||||
expect(node21F?.left).toBe(NIL);
|
||||
expect(node21F?.right).toBe(NIL);
|
||||
expect(node21F?.parent).toBe(node20F);
|
||||
expect(node6F?.key).toBe(6);
|
||||
expect(node6F?.color).toBe(RBTNColor.BLACK);
|
||||
expect(node6F?.left).toBe(node2F);
|
||||
expect(node6F?.right).toBe(NIL);
|
||||
expect(node6F?.parent).toBe(node10F);
|
||||
expect(node2F?.key).toBe(2);
|
||||
expect(node2F?.color).toBe(RBTNColor.RED);
|
||||
expect(node2F?.left).toBe(NIL);
|
||||
expect(node2F?.right).toBe(NIL);
|
||||
expect(node2F?.parent).toBe(node6F);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(NIL);
|
||||
expect(node15F?.right).toBe(NIL);
|
||||
expect(node15F?.parent).toBe(node20F);
|
||||
tree.delete(20);
|
||||
node10F = tree.getNode(10);
|
||||
node20F = tree.getNode(20);
|
||||
|
@ -309,38 +310,38 @@ describe('RedBlackTree', () => {
|
|||
node21F = tree.getNode(21);
|
||||
node6F = tree.getNode(6);
|
||||
node2F = tree.getNode(2);
|
||||
expect(node10F.key).toBe(10);
|
||||
expect(node10F.color).toBe(RBTNColor.BLACK);
|
||||
expect(node10F.left).toBe(node6F);
|
||||
expect(node10F.right).toBe(node21F);
|
||||
expect(node10F.parent).toBe(null);
|
||||
expect(node20F).toBe(null);
|
||||
expect(node5F).toBe(null);
|
||||
expect(node15F.key).toBe(15);
|
||||
expect(node15F.color).toBe(RBTNColor.RED);
|
||||
expect(node15F.left).toBe(NIL);
|
||||
expect(node15F.right).toBe(NIL);
|
||||
expect(node15F.parent).toBe(node21F);
|
||||
expect(node21F.key).toBe(21);
|
||||
expect(node21F.color).toBe(RBTNColor.BLACK);
|
||||
expect(node21F.left).toBe(node15F);
|
||||
expect(node21F.right).toBe(NIL);
|
||||
expect(node21F.parent).toBe(node10F);
|
||||
expect(node6F.key).toBe(6);
|
||||
expect(node6F.color).toBe(RBTNColor.BLACK);
|
||||
expect(node6F.left).toBe(node2F);
|
||||
expect(node6F.right).toBe(NIL);
|
||||
expect(node6F.parent).toBe(node10F);
|
||||
expect(node2F.key).toBe(2);
|
||||
expect(node2F.color).toBe(RBTNColor.RED);
|
||||
expect(node2F.left).toBe(NIL);
|
||||
expect(node2F.right).toBe(NIL);
|
||||
expect(node2F.parent).toBe(node6F);
|
||||
expect(node15F.key).toBe(15);
|
||||
expect(node15F.color).toBe(RBTNColor.RED);
|
||||
expect(node15F.left).toBe(NIL);
|
||||
expect(node15F.right).toBe(NIL);
|
||||
expect(node15F.parent).toBe(node21F);
|
||||
expect(node10F?.key).toBe(10);
|
||||
expect(node10F?.color).toBe(RBTNColor.BLACK);
|
||||
expect(node10F?.left).toBe(node6F);
|
||||
expect(node10F?.right).toBe(node21F);
|
||||
expect(node10F?.parent).toBe(undefined);
|
||||
expect(node20F).toBe(undefined);
|
||||
expect(node5F).toBe(undefined);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(NIL);
|
||||
expect(node15F?.right).toBe(NIL);
|
||||
expect(node15F?.parent).toBe(node21F);
|
||||
expect(node21F?.key).toBe(21);
|
||||
expect(node21F?.color).toBe(RBTNColor.BLACK);
|
||||
expect(node21F?.left).toBe(node15F);
|
||||
expect(node21F?.right).toBe(NIL);
|
||||
expect(node21F?.parent).toBe(node10F);
|
||||
expect(node6F?.key).toBe(6);
|
||||
expect(node6F?.color).toBe(RBTNColor.BLACK);
|
||||
expect(node6F?.left).toBe(node2F);
|
||||
expect(node6F?.right).toBe(NIL);
|
||||
expect(node6F?.parent).toBe(node10F);
|
||||
expect(node2F?.key).toBe(2);
|
||||
expect(node2F?.color).toBe(RBTNColor.RED);
|
||||
expect(node2F?.left).toBe(NIL);
|
||||
expect(node2F?.right).toBe(NIL);
|
||||
expect(node2F?.parent).toBe(node6F);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(NIL);
|
||||
expect(node15F?.right).toBe(NIL);
|
||||
expect(node15F?.parent).toBe(node21F);
|
||||
});
|
||||
|
||||
it('should fix the tree after insertion', () => {
|
||||
|
@ -349,9 +350,9 @@ describe('RedBlackTree', () => {
|
|||
tree.add(5);
|
||||
tree.add(15);
|
||||
const node15F = tree.getNode(15);
|
||||
expect(node15F.left).toBe(NIL);
|
||||
expect(node15F.right).toBe(NIL);
|
||||
expect(node15F.parent).toBe(tree.getNode(5));
|
||||
expect(node15F?.left).toBe(NIL);
|
||||
expect(node15F?.right).toBe(NIL);
|
||||
expect(node15F?.parent).toBe(tree.getNode(5));
|
||||
|
||||
tree.add(25);
|
||||
tree.add(10);
|
||||
|
@ -365,22 +366,22 @@ describe('RedBlackTree', () => {
|
|||
tree.add(155);
|
||||
tree.add(225);
|
||||
const node225F = tree.getNode(225);
|
||||
expect(node225F.left).toBe(NIL);
|
||||
expect(node225F.right).toBe(NIL);
|
||||
expect(node225F.parent.key).toBe(155);
|
||||
expect(node225F?.left).toBe(NIL);
|
||||
expect(node225F?.right).toBe(NIL);
|
||||
expect(node225F?.parent?.key).toBe(155);
|
||||
tree.add(7);
|
||||
|
||||
const node15S = tree.getNode(15);
|
||||
expect(node15S.left.key).toBe(8);
|
||||
expect(node15S.right.key).toBe(28);
|
||||
expect(node15S?.left?.key).toBe(8);
|
||||
expect(node15S?.right?.key).toBe(28);
|
||||
expect(node15S).toBe(tree.root);
|
||||
expect(node15S.parent).toBe(null);
|
||||
expect(node15S?.parent).toBe(undefined);
|
||||
tree.delete(15);
|
||||
expect(tree.root.key).toBe(22);
|
||||
expect(tree.root.parent).toBe(null);
|
||||
expect(tree.root.parent).toBe(undefined);
|
||||
|
||||
const node15T = tree.getNode(15);
|
||||
expect(node15T).toBe(null);
|
||||
expect(node15T).toBe(undefined);
|
||||
|
||||
tree.add(23);
|
||||
tree.add(33);
|
||||
|
@ -390,18 +391,18 @@ describe('RedBlackTree', () => {
|
|||
expect(nodeLM.key).toBe(1);
|
||||
|
||||
const node50 = tree.getNode(50);
|
||||
expect(node50.key).toBe(50);
|
||||
expect(node50.left.key).toBe(33);
|
||||
expect(node50.right).toBe(NIL);
|
||||
expect(node50?.key).toBe(50);
|
||||
expect(node50?.left?.key).toBe(33);
|
||||
expect(node50?.right).toBe(NIL);
|
||||
const node15Fo = tree.getNode(15);
|
||||
|
||||
expect(node15Fo.key).toBe(15);
|
||||
expect(node15Fo.left).toBe(NIL);
|
||||
expect(node15Fo?.key).toBe(15);
|
||||
expect(node15Fo?.left).toBe(NIL);
|
||||
const node225S = tree.getNode(225);
|
||||
expect(node225S.left).toBe(NIL);
|
||||
expect(node225S.right).toBe(NIL);
|
||||
expect(node225S.parent.key).toBe(155);
|
||||
expect(tree.getNode(0)).toBe(null);
|
||||
expect(node225S?.left).toBe(NIL);
|
||||
expect(node225S?.right).toBe(NIL);
|
||||
expect(node225S?.parent?.key).toBe(155);
|
||||
expect(tree.getNode(0)).toBe(undefined);
|
||||
tree.add(1);
|
||||
tree.add(2);
|
||||
tree.add(3);
|
||||
|
@ -427,7 +428,13 @@ describe('RedBlackTree', () => {
|
|||
});
|
||||
|
||||
it('should fix the tree after insertion and deletion', () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (let i = 0; i < 100000; i++) {
|
||||
tree.add(getRandomInt(-100, 1000));
|
||||
}
|
||||
for (let i = 0; i < 100000; i++) {
|
||||
tree.delete(getRandomInt(-100, 1000));
|
||||
}
|
||||
for (let i = 0; i < 100000; i++) {
|
||||
tree.add(getRandomInt(-100, 1000));
|
||||
tree.delete(getRandomInt(-100, 1000));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue