mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
refactor: rename NIL of RedBlackTree to Sentinel
This commit is contained in:
parent
54c74f9af6
commit
01b969edca
|
@ -34,14 +34,14 @@ export class RedBlackTreeNode<V = any, N extends RedBlackTreeNode<V, N> = RedBla
|
|||
/**
|
||||
* 1. Each node is either red or black.
|
||||
* 2. The root node is always black.
|
||||
* 3. Leaf nodes are typically NIL nodes and are considered black.
|
||||
* 3. Leaf nodes are typically Sentinel nodes and are considered black.
|
||||
* 4. Red nodes must have black children.
|
||||
* 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.
|
||||
*/
|
||||
export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTreeNode<V, RedBlackTreeNodeNested<V>>>
|
||||
extends BST<V, N>
|
||||
implements IBinaryTree<V, N> {
|
||||
NIL: N = new RedBlackTreeNode<V>(NaN) as unknown as N;
|
||||
Sentinel: N = new RedBlackTreeNode<V>(NaN) as unknown as N;
|
||||
|
||||
/**
|
||||
* The constructor function initializes a Red-Black Tree with an optional set of options.
|
||||
|
@ -50,7 +50,7 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
*/
|
||||
constructor(options?: RBTreeOptions) {
|
||||
super(options);
|
||||
this._root = this.NIL;
|
||||
this._root = this.Sentinel;
|
||||
}
|
||||
|
||||
protected _root: N;
|
||||
|
@ -95,13 +95,13 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
return;
|
||||
}
|
||||
|
||||
node.left = this.NIL;
|
||||
node.right = this.NIL;
|
||||
node.left = this.Sentinel;
|
||||
node.right = this.Sentinel;
|
||||
|
||||
let y: N | undefined = undefined;
|
||||
let x: N | undefined = this.root;
|
||||
|
||||
while (x !== this.NIL) {
|
||||
while (x !== this.Sentinel) {
|
||||
y = x;
|
||||
if (x) {
|
||||
if (node.key < x.key) {
|
||||
|
@ -170,9 +170,9 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
const ans: BiTreeDeleteResult<N>[] = [];
|
||||
if (identifier === null) return ans;
|
||||
const helper = (node: N | undefined): void => {
|
||||
let z: N = this.NIL;
|
||||
let z: N = this.Sentinel;
|
||||
let x: N | undefined, y: N;
|
||||
while (node !== this.NIL) {
|
||||
while (node !== this.Sentinel) {
|
||||
if (node && callback(node) === identifier) {
|
||||
z = node;
|
||||
}
|
||||
|
@ -184,17 +184,17 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
}
|
||||
}
|
||||
|
||||
if (z === this.NIL) {
|
||||
if (z === this.Sentinel) {
|
||||
this._size--;
|
||||
return;
|
||||
}
|
||||
|
||||
y = z;
|
||||
let yOriginalColor: number = y.color;
|
||||
if (z.left === this.NIL) {
|
||||
if (z.left === this.Sentinel) {
|
||||
x = z.right;
|
||||
this._rbTransplant(z, z.right!);
|
||||
} else if (z.right === this.NIL) {
|
||||
} else if (z.right === this.Sentinel) {
|
||||
x = z.left;
|
||||
this._rbTransplant(z, z.left!);
|
||||
} else {
|
||||
|
@ -225,7 +225,7 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
}
|
||||
|
||||
override isRealNode(node: N | undefined): node is N {
|
||||
return node !== this.NIL && node !== undefined;
|
||||
return node !== this.Sentinel && node !== undefined;
|
||||
}
|
||||
|
||||
getNode<C extends BTNCallback<N, BTNKey>>(
|
||||
|
@ -300,12 +300,12 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
* @returns the successor of the given RedBlackTreeNode.
|
||||
*/
|
||||
override getSuccessor(x: N): N | undefined {
|
||||
if (x.right !== this.NIL) {
|
||||
if (x.right !== this.Sentinel) {
|
||||
return this.getLeftMost(x.right) ?? undefined;
|
||||
}
|
||||
|
||||
let y: N | undefined = x.parent;
|
||||
while (y !== this.NIL && y !== undefined && x === y.right) {
|
||||
while (y !== this.Sentinel && y !== undefined && x === y.right) {
|
||||
x = y;
|
||||
y = y.parent;
|
||||
}
|
||||
|
@ -327,12 +327,12 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
* @returns the predecessor of the given RedBlackTreeNode 'x'.
|
||||
*/
|
||||
override getPredecessor(x: N): N {
|
||||
if (x.left !== this.NIL) {
|
||||
if (x.left !== this.Sentinel) {
|
||||
return this.getRightMost(x.left!)!;
|
||||
}
|
||||
|
||||
let y: N | undefined = x.parent;
|
||||
while (y !== this.NIL && x === y!.left) {
|
||||
while (y !== this.Sentinel && x === y!.left) {
|
||||
x = y!;
|
||||
y = y!.parent;
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
}
|
||||
|
||||
override clear() {
|
||||
this._root = this.NIL;
|
||||
this._root = this.Sentinel;
|
||||
this._size = 0;
|
||||
}
|
||||
|
||||
|
@ -368,7 +368,7 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
if (x.right) {
|
||||
const y: N = x.right;
|
||||
x.right = y.left;
|
||||
if (y.left !== this.NIL) {
|
||||
if (y.left !== this.Sentinel) {
|
||||
if (y.left) y.left.parent = x;
|
||||
}
|
||||
y.parent = x.parent;
|
||||
|
@ -401,7 +401,7 @@ export class RedBlackTree<V = any, N extends RedBlackTreeNode<V, N> = RedBlackTr
|
|||
if (x.left) {
|
||||
const y: N = x.left;
|
||||
x.left = y.right;
|
||||
if (y.right !== this.NIL) {
|
||||
if (y.right !== this.Sentinel) {
|
||||
if (y.right) y.right.parent = x;
|
||||
}
|
||||
y.parent = x.parent;
|
||||
|
|
|
@ -67,7 +67,7 @@ describe('RedBlackTree', () => {
|
|||
|
||||
it('should handle an empty tree', () => {
|
||||
const minNode = tree.getLeftMost(tree.root);
|
||||
expect(minNode).toBe(tree.NIL);
|
||||
expect(minNode).toBe(tree.Sentinel);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -85,7 +85,7 @@ describe('RedBlackTree', () => {
|
|||
|
||||
it('should handle an empty tree', () => {
|
||||
const maxNode = tree.getRightMost(tree.root);
|
||||
expect(maxNode).toBe(tree.NIL);
|
||||
expect(maxNode).toBe(tree.Sentinel);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -109,7 +109,7 @@ describe('RedBlackTree', () => {
|
|||
|
||||
const node = tree.getNode(10);
|
||||
const successorNode = tree.getSuccessor(node!);
|
||||
// TODO not sure if it should be undefined or tree.NIL
|
||||
// TODO not sure if it should be undefined or tree.Sentinel
|
||||
expect(successorNode).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
@ -134,7 +134,7 @@ describe('RedBlackTree', () => {
|
|||
|
||||
const node = tree.getNode(20);
|
||||
const predecessorNode = tree.getPredecessor(node!);
|
||||
// TODO not sure if it should be tree.NIL or something else.
|
||||
// TODO not sure if it should be tree.Sentinel or something else.
|
||||
expect(predecessorNode).toBe(tree.getNode(10));
|
||||
});
|
||||
});
|
||||
|
@ -235,28 +235,28 @@ describe('RedBlackTree', () => {
|
|||
expect(node5F?.parent).toBe(node10F);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(tree.NIL);
|
||||
expect(node15F?.right).toBe(tree.NIL);
|
||||
expect(node15F?.left).toBe(tree.Sentinel);
|
||||
expect(node15F?.right).toBe(tree.Sentinel);
|
||||
expect(node15F?.parent).toBe(node20F);
|
||||
expect(node21F?.key).toBe(21);
|
||||
expect(node21F?.color).toBe(RBTNColor.RED);
|
||||
expect(node21F?.left).toBe(tree.NIL);
|
||||
expect(node21F?.right).toBe(tree.NIL);
|
||||
expect(node21F?.left).toBe(tree.Sentinel);
|
||||
expect(node21F?.right).toBe(tree.Sentinel);
|
||||
expect(node21F?.parent).toBe(node20F);
|
||||
expect(node6F?.key).toBe(6);
|
||||
expect(node6F?.color).toBe(RBTNColor.RED);
|
||||
expect(node6F?.left).toBe(tree.NIL);
|
||||
expect(node6F?.right).toBe(tree.NIL);
|
||||
expect(node6F?.left).toBe(tree.Sentinel);
|
||||
expect(node6F?.right).toBe(tree.Sentinel);
|
||||
expect(node6F?.parent).toBe(node5F);
|
||||
expect(node2F?.key).toBe(2);
|
||||
expect(node2F?.color).toBe(RBTNColor.RED);
|
||||
expect(node2F?.left).toBe(tree.NIL);
|
||||
expect(node2F?.right).toBe(tree.NIL);
|
||||
expect(node2F?.left).toBe(tree.Sentinel);
|
||||
expect(node2F?.right).toBe(tree.Sentinel);
|
||||
expect(node2F?.parent).toBe(node5F);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(tree.NIL);
|
||||
expect(node15F?.right).toBe(tree.NIL);
|
||||
expect(node15F?.left).toBe(tree.Sentinel);
|
||||
expect(node15F?.right).toBe(tree.Sentinel);
|
||||
expect(node15F?.parent).toBe(node20F);
|
||||
tree.delete(5);
|
||||
node10F = tree.getNode(10);
|
||||
|
@ -279,28 +279,28 @@ describe('RedBlackTree', () => {
|
|||
expect(node5F).toBe(undefined);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(tree.NIL);
|
||||
expect(node15F?.right).toBe(tree.NIL);
|
||||
expect(node15F?.left).toBe(tree.Sentinel);
|
||||
expect(node15F?.right).toBe(tree.Sentinel);
|
||||
expect(node15F?.parent).toBe(node20F);
|
||||
expect(node21F?.key).toBe(21);
|
||||
expect(node21F?.color).toBe(RBTNColor.RED);
|
||||
expect(node21F?.left).toBe(tree.NIL);
|
||||
expect(node21F?.right).toBe(tree.NIL);
|
||||
expect(node21F?.left).toBe(tree.Sentinel);
|
||||
expect(node21F?.right).toBe(tree.Sentinel);
|
||||
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(tree.NIL);
|
||||
expect(node6F?.right).toBe(tree.Sentinel);
|
||||
expect(node6F?.parent).toBe(node10F);
|
||||
expect(node2F?.key).toBe(2);
|
||||
expect(node2F?.color).toBe(RBTNColor.RED);
|
||||
expect(node2F?.left).toBe(tree.NIL);
|
||||
expect(node2F?.right).toBe(tree.NIL);
|
||||
expect(node2F?.left).toBe(tree.Sentinel);
|
||||
expect(node2F?.right).toBe(tree.Sentinel);
|
||||
expect(node2F?.parent).toBe(node6F);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(tree.NIL);
|
||||
expect(node15F?.right).toBe(tree.NIL);
|
||||
expect(node15F?.left).toBe(tree.Sentinel);
|
||||
expect(node15F?.right).toBe(tree.Sentinel);
|
||||
expect(node15F?.parent).toBe(node20F);
|
||||
tree.delete(20);
|
||||
node10F = tree.getNode(10);
|
||||
|
@ -319,28 +319,28 @@ describe('RedBlackTree', () => {
|
|||
expect(node5F).toBe(undefined);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(tree.NIL);
|
||||
expect(node15F?.right).toBe(tree.NIL);
|
||||
expect(node15F?.left).toBe(tree.Sentinel);
|
||||
expect(node15F?.right).toBe(tree.Sentinel);
|
||||
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(tree.NIL);
|
||||
expect(node21F?.right).toBe(tree.Sentinel);
|
||||
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(tree.NIL);
|
||||
expect(node6F?.right).toBe(tree.Sentinel);
|
||||
expect(node6F?.parent).toBe(node10F);
|
||||
expect(node2F?.key).toBe(2);
|
||||
expect(node2F?.color).toBe(RBTNColor.RED);
|
||||
expect(node2F?.left).toBe(tree.NIL);
|
||||
expect(node2F?.right).toBe(tree.NIL);
|
||||
expect(node2F?.left).toBe(tree.Sentinel);
|
||||
expect(node2F?.right).toBe(tree.Sentinel);
|
||||
expect(node2F?.parent).toBe(node6F);
|
||||
expect(node15F?.key).toBe(15);
|
||||
expect(node15F?.color).toBe(RBTNColor.RED);
|
||||
expect(node15F?.left).toBe(tree.NIL);
|
||||
expect(node15F?.right).toBe(tree.NIL);
|
||||
expect(node15F?.left).toBe(tree.Sentinel);
|
||||
expect(node15F?.right).toBe(tree.Sentinel);
|
||||
expect(node15F?.parent).toBe(node21F);
|
||||
});
|
||||
|
||||
|
@ -350,8 +350,8 @@ describe('RedBlackTree', () => {
|
|||
tree.add(5);
|
||||
tree.add(15);
|
||||
const node15F = tree.getNode(15);
|
||||
expect(node15F?.left).toBe(tree.NIL);
|
||||
expect(node15F?.right).toBe(tree.NIL);
|
||||
expect(node15F?.left).toBe(tree.Sentinel);
|
||||
expect(node15F?.right).toBe(tree.Sentinel);
|
||||
expect(node15F?.parent).toBe(tree.getNode(5));
|
||||
|
||||
tree.add(25);
|
||||
|
@ -366,8 +366,8 @@ describe('RedBlackTree', () => {
|
|||
tree.add(155);
|
||||
tree.add(225);
|
||||
const node225F = tree.getNode(225);
|
||||
expect(node225F?.left).toBe(tree.NIL);
|
||||
expect(node225F?.right).toBe(tree.NIL);
|
||||
expect(node225F?.left).toBe(tree.Sentinel);
|
||||
expect(node225F?.right).toBe(tree.Sentinel);
|
||||
expect(node225F?.parent?.key).toBe(155);
|
||||
tree.add(7);
|
||||
|
||||
|
@ -393,14 +393,14 @@ describe('RedBlackTree', () => {
|
|||
const node50 = tree.getNode(50);
|
||||
expect(node50?.key).toBe(50);
|
||||
expect(node50?.left?.key).toBe(33);
|
||||
expect(node50?.right).toBe(tree.NIL);
|
||||
expect(node50?.right).toBe(tree.Sentinel);
|
||||
const node15Fo = tree.getNode(15);
|
||||
|
||||
expect(node15Fo?.key).toBe(15);
|
||||
expect(node15Fo?.left).toBe(tree.NIL);
|
||||
expect(node15Fo?.left).toBe(tree.Sentinel);
|
||||
const node225S = tree.getNode(225);
|
||||
expect(node225S?.left).toBe(tree.NIL);
|
||||
expect(node225S?.right).toBe(tree.NIL);
|
||||
expect(node225S?.left).toBe(tree.Sentinel);
|
||||
expect(node225S?.right).toBe(tree.Sentinel);
|
||||
expect(node225S?.parent?.key).toBe(155);
|
||||
// TODO
|
||||
// expect(tree.getNode(0)).toBe(undefined);
|
||||
|
@ -465,7 +465,7 @@ describe('RedBlackTree', () => {
|
|||
tree.delete(getRandomInt(-100, 1000));
|
||||
}
|
||||
|
||||
// TODO there is a bug when dfs the tree with NIL node
|
||||
// TODO there is a bug when dfs the tree with Sentinel node
|
||||
// expect(tree.isBST()).toBe(true);
|
||||
});
|
||||
const { HUNDRED_THOUSAND } = magnitude;
|
||||
|
|
Loading…
Reference in a new issue