Merge pull request #428 from jack870131/PR-Test
Red Black Tree Implementation (Java)
This commit is contained in:
commit
55c3aacce1
330
Data Structures/Trees/RedBlackBST.java
Normal file
330
Data Structures/Trees/RedBlackBST.java
Normal file
@ -0,0 +1,330 @@
|
||||
/**
|
||||
*
|
||||
* @author jack870131
|
||||
*/
|
||||
public class RedBlackBST {
|
||||
|
||||
private final int R = 0;
|
||||
private final int B = 1;
|
||||
|
||||
private class Node {
|
||||
|
||||
int key = -1, color = B;
|
||||
Node left = nil, right = nil, p = nil;
|
||||
|
||||
Node(int key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
private final Node nil = new Node(-1);
|
||||
private Node root = nil;
|
||||
|
||||
public void printTree(Node node) {
|
||||
if (node == nil) {
|
||||
return;
|
||||
}
|
||||
printTree(node.left);
|
||||
System.out.print(((node.color == R) ? " R " : " B ") + "Key: " + node.key + " Parent: " + node.p.key + "\n");
|
||||
printTree(node.right);
|
||||
}
|
||||
|
||||
public void printTreepre(Node node) {
|
||||
if (node == nil) {
|
||||
return;
|
||||
}
|
||||
System.out.print(((node.color == R) ? " R " : " B ") + "Key: " + node.key + " Parent: " + node.p.key + "\n");
|
||||
printTree(node.left);
|
||||
printTree(node.right);
|
||||
}
|
||||
|
||||
private Node findNode(Node findNode, Node node) {
|
||||
if (root == nil) {
|
||||
return null;
|
||||
}
|
||||
if (findNode.key < node.key) {
|
||||
if (node.left != nil) {
|
||||
return findNode(findNode, node.left);
|
||||
}
|
||||
} else if (findNode.key > node.key) {
|
||||
if (node.right != nil) {
|
||||
return findNode(findNode, node.right);
|
||||
}
|
||||
} else if (findNode.key == node.key) {
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void insert(Node node) {
|
||||
Node temp = root;
|
||||
if (root == nil) {
|
||||
root = node;
|
||||
node.color = B;
|
||||
node.p = nil;
|
||||
} else {
|
||||
node.color = R;
|
||||
while (true) {
|
||||
if (node.key < temp.key) {
|
||||
if (temp.left == nil) {
|
||||
temp.left = node;
|
||||
node.p = temp;
|
||||
break;
|
||||
} else {
|
||||
temp = temp.left;
|
||||
}
|
||||
} else if (node.key >= temp.key) {
|
||||
if (temp.right == nil) {
|
||||
temp.right = node;
|
||||
node.p = temp;
|
||||
break;
|
||||
} else {
|
||||
temp = temp.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
fixTree(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void fixTree(Node node) {
|
||||
while (node.p.color == R) {
|
||||
Node y = nil;
|
||||
if (node.p == node.p.p.left) {
|
||||
y = node.p.p.right;
|
||||
|
||||
if (y != nil && y.color == R) {
|
||||
node.p.color = B;
|
||||
y.color = B;
|
||||
node.p.p.color = R;
|
||||
node = node.p.p;
|
||||
continue;
|
||||
}
|
||||
if (node == node.p.right) {
|
||||
node = node.p;
|
||||
rotateLeft(node);
|
||||
}
|
||||
node.p.color = B;
|
||||
node.p.p.color = R;
|
||||
rotateRight(node.p.p);
|
||||
} else {
|
||||
y = node.p.p.left;
|
||||
if (y != nil && y.color == R) {
|
||||
node.p.color = B;
|
||||
y.color = B;
|
||||
node.p.p.color = R;
|
||||
node = node.p.p;
|
||||
continue;
|
||||
}
|
||||
if (node == node.p.left) {
|
||||
node = node.p;
|
||||
rotateRight(node);
|
||||
}
|
||||
node.p.color = B;
|
||||
node.p.p.color = R;
|
||||
rotateLeft(node.p.p);
|
||||
}
|
||||
}
|
||||
root.color = B;
|
||||
}
|
||||
|
||||
void rotateLeft(Node node) {
|
||||
if (node.p != nil) {
|
||||
if (node == node.p.left) {
|
||||
node.p.left = node.right;
|
||||
} else {
|
||||
node.p.right = node.right;
|
||||
}
|
||||
node.right.p = node.p;
|
||||
node.p = node.right;
|
||||
if (node.right.left != nil) {
|
||||
node.right.left.p = node;
|
||||
}
|
||||
node.right = node.right.left;
|
||||
node.p.left = node;
|
||||
} else {
|
||||
Node right = root.right;
|
||||
root.right = right.left;
|
||||
right.left.p = root;
|
||||
root.p = right;
|
||||
right.left = root;
|
||||
right.p = nil;
|
||||
root = right;
|
||||
}
|
||||
}
|
||||
|
||||
void rotateRight(Node node) {
|
||||
if (node.p != nil) {
|
||||
if (node == node.p.left) {
|
||||
node.p.left = node.left;
|
||||
} else {
|
||||
node.p.right = node.left;
|
||||
}
|
||||
|
||||
node.left.p = node.p;
|
||||
node.p = node.left;
|
||||
if (node.left.right != nil) {
|
||||
node.left.right.p = node;
|
||||
}
|
||||
node.left = node.left.right;
|
||||
node.p.right = node;
|
||||
} else {
|
||||
Node left = root.left;
|
||||
root.left = root.left.right;
|
||||
left.right.p = root;
|
||||
root.p = left;
|
||||
left.right = root;
|
||||
left.p = nil;
|
||||
root = left;
|
||||
}
|
||||
}
|
||||
|
||||
void transplant(Node target, Node with) {
|
||||
if (target.p == nil) {
|
||||
root = with;
|
||||
} else if (target == target.p.left) {
|
||||
target.p.left = with;
|
||||
} else
|
||||
target.p.right = with;
|
||||
with.p = target.p;
|
||||
}
|
||||
|
||||
Node treeMinimum(Node subTreeRoot) {
|
||||
while (subTreeRoot.left != nil) {
|
||||
subTreeRoot = subTreeRoot.left;
|
||||
}
|
||||
return subTreeRoot;
|
||||
}
|
||||
|
||||
boolean delete(Node z) {
|
||||
if ((z = findNode(z, root)) == null)
|
||||
return false;
|
||||
Node x;
|
||||
Node y = z;
|
||||
int yorigcolor = y.color;
|
||||
|
||||
if (z.left == nil) {
|
||||
x = z.right;
|
||||
transplant(z, z.right);
|
||||
} else if (z.right == nil) {
|
||||
x = z.left;
|
||||
transplant(z, z.left);
|
||||
} else {
|
||||
y = treeMinimum(z.right);
|
||||
yorigcolor = y.color;
|
||||
x = y.right;
|
||||
if (y.p == z)
|
||||
x.p = y;
|
||||
else {
|
||||
transplant(y, y.right);
|
||||
y.right = z.right;
|
||||
y.right.p = y;
|
||||
}
|
||||
transplant(z, y);
|
||||
y.left = z.left;
|
||||
y.left.p = y;
|
||||
y.color = z.color;
|
||||
}
|
||||
if (yorigcolor == B)
|
||||
deleteFixup(x);
|
||||
return true;
|
||||
}
|
||||
|
||||
void deleteFixup(Node x) {
|
||||
while (x != root && x.color == B) {
|
||||
if (x == x.p.left) {
|
||||
Node w = x.p.right;
|
||||
if (w.color == R) {
|
||||
w.color = B;
|
||||
x.p.color = R;
|
||||
rotateLeft(x.p);
|
||||
w = x.p.right;
|
||||
}
|
||||
if (w.left.color == B && w.right.color == B) {
|
||||
w.color = R;
|
||||
x = x.p;
|
||||
continue;
|
||||
} else if (w.right.color == B) {
|
||||
w.left.color = B;
|
||||
w.color = R;
|
||||
rotateRight(w);
|
||||
w = x.p.right;
|
||||
}
|
||||
if (w.right.color == R) {
|
||||
w.color = x.p.color;
|
||||
x.p.color = B;
|
||||
w.right.color = B;
|
||||
rotateLeft(x.p);
|
||||
x = root;
|
||||
}
|
||||
} else {
|
||||
Node w = x.p.left;
|
||||
if (w.color == R) {
|
||||
w.color = B;
|
||||
x.p.color = R;
|
||||
rotateRight(x.p);
|
||||
w = x.p.left;
|
||||
}
|
||||
if (w.right.color == B && w.left.color == B) {
|
||||
w.color = R;
|
||||
x = x.p;
|
||||
continue;
|
||||
} else if (w.left.color == B) {
|
||||
w.right.color = B;
|
||||
w.color = R;
|
||||
rotateLeft(w);
|
||||
w = x.p.left;
|
||||
}
|
||||
if (w.left.color == R) {
|
||||
w.color = x.p.color;
|
||||
x.p.color = B;
|
||||
w.left.color = B;
|
||||
rotateRight(x.p);
|
||||
x = root;
|
||||
}
|
||||
}
|
||||
}
|
||||
x.color = B;
|
||||
}
|
||||
|
||||
public void insertDemo() {
|
||||
Scanner scan = new Scanner(System.in);
|
||||
while (true) {
|
||||
System.out.println("Add items");
|
||||
|
||||
int item;
|
||||
Node node;
|
||||
|
||||
item = scan.nextInt();
|
||||
while (item != -999) {
|
||||
node = new Node(item);
|
||||
insert(node);
|
||||
item = scan.nextInt();
|
||||
}
|
||||
printTree(root);
|
||||
System.out.println("Pre order");
|
||||
printTreepre(root);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteDemo() {
|
||||
Scanner scan = new Scanner(System.in);
|
||||
System.out.println("Delete items");
|
||||
int item;
|
||||
Node node;
|
||||
item = scan.nextInt();
|
||||
node = new Node(item);
|
||||
System.out.print("Deleting item " + item);
|
||||
if (delete(node)) {
|
||||
System.out.print(": deleted!");
|
||||
} else {
|
||||
System.out.print(": does not exist!");
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
printTree(root);
|
||||
System.out.println("Pre order");
|
||||
printTreepre(root);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user