330 lines
6.6 KiB
Java
330 lines
6.6 KiB
Java
/**
|
|
*
|
|
* @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);
|
|
}
|
|
} |