红黑树是一种二叉查找树,在每个结点上增加一个存储位表示结点颜色,可以是RED或者是BLACK,通过对任何一条从根到叶的路径上各个结点着色方式的限制,确保红黑树不会有一条路径会比其他路径长出两倍
public class RBTree, Value> {
private static final boolean RED = true;
private static final boolean BLACK = false;
private final Node nil = new Node(null, null, BLACK);
private Node root = nil;
public Node getRoot() {
return root;
}
private class Node {
Node left = nil;
Node right = nil;
Node Parent = nil;
Key key;
Value val;
boolean color;
Node(Key key, Value val, boolean color) {
this.key = key;
this.val = val;
this.color = color;
}
}
public Node get(Key key) {
Node x = root;
while (x != nil) {
int cmp = key.compareTo(x.key);
if (cmp == 0) {
return x;
}
if (cmp > 0) {
x = x.right;
}
if (cmp < 0) {
x = x.left;
}
}
return null;
}
public Node Tree_Minimun(Node x) {
Node tmp = x;
while (tmp.left != nil) {
tmp = tmp.left;
}
return tmp;
}
public Node Tree_Maximun(Node x) {
Node tmp = x;
while (tmp.right != nil) {
tmp = tmp.right;
}
return tmp;
}
/**
* 找x的后继
*
* @param x
* @return
*/
public Node Tree_Successor(Node x) {
if (x.right != nil) {
return Tree_Minimun(x.right);
}
Node y = x.Parent;
while (y != nil && x.key == y.right.key) {
x = y;
y = x.Parent;
}
return y;
}
/**
* 左旋操作
*
* @param x
*/
public void Left_Rotate(Node x) {
Node y = x.right;
x.right = y.left;
if (y.left != nil) {
y.left.Parent = x;
}
y.Parent = x.Parent;
if (x.Parent != nil) {
if (x == x.Parent.left) {
x.Parent.left = y;
} else {
x.Parent.right = y;
}
} else {
root = y;
}
y.left = x;
x.Parent = y;
}
/**
* 右旋操作
*
* @param x
*/
public void Right_Rotate(Node x) {
Node y = x.left;
x.left = y.right;
if (y.right != nil) {
y.right.Parent = x;
}
y.Parent = x.Parent;
if (x.Parent != nil) {
if (x == x.Parent.left) {
x.Parent.left = y;
} else {
x.Parent.right = y;
}
} else {
root = y;
}
y.right = x;
x.Parent = y;
}
// 插入
public void RB_Insert(Key key, Value val) {
Node z = new Node(key, val, RED);
Node x = root;
Node y = nil;
while (x != nil) {// 找到应该插入位置的父节点,y
y = x;
if (z.key.compareTo(x.key) < 0) {
x = x.left;
} else {
x = x.right;
}
}
z.Parent = y;
if (y == nil) { // y若为null,则插入的点为根节点
root = z;
root.color = BLACK;
return;
} else {// 否则,比较大小,看插入左边还是右边
if (z.key.compareTo(y.key) < 0) {
y.left = z;
} else {
y.right = z;
}
}
z.left = nil;
z.right = nil;
z.color = RED;// 颜色置为红色
RB_Insert_Fixup(z);// 进行插入后的调整,保持红黑性质
}
public void RB_Insert_Fixup(Node z) {
/**
* 三种情况: case1:若插入节点的父节点为红,则需要进行下一步讨论; case2:若插入节点父节点为黑,则无需做调整;
* case3:若插入节点为根,则最后将节点变为黑色
*/
while (z.Parent.color == RED) {// case1 父节点为红,则必有祖父节点
/**
* 两种情况: case1.1 插入节点的父节点为左子树 case1.2 插入节点的父节点为右子树
*/
if (z.Parent == z.Parent.Parent.left) {
Node y = z.Parent.Parent.right;// 获取z的叔父节点
/**
* 三种情况: case1.1.1 叔父节点为红 case1.1.2 叔父节点为黑,且z为右孩子 case1.1.3 叔父节点为黑,且z为左孩子
*/
if (y.color == RED) {// case1.1.1
/**
* 调整z的父节点与叔父节点颜色为黑色 调整z的祖父节点颜色为红色 将z上移两层
*/
z.Parent.color = BLACK;
y.color = BLACK;
z.Parent.Parent.color = RED;
z = z.Parent.Parent;
} else if (z == z.Parent.right) {// case1.1.2
// 左旋操作,左旋后,z变为左孩子,变为case1.1.3情况
z = z.Parent;
Left_Rotate(z);
} else {// case1.1.3
z.Parent.color = BLACK;
z.Parent.Parent.color = RED;
Right_Rotate(z.Parent.Parent);
}
} else {// case1.2
Node y = z.Parent.Parent.left;// 获取z的叔父节点
/**
* 三种情况: case1.2.1 叔父节点为红; case1.2.2 叔父节点为黑,且z为左孩子; case1.2.3 叔父节点为黑,且z为右孩子
*/
if (y.color == RED) {// case1.2.1
/**
* 调整z的父节点与叔父节点颜色为黑色 调整z的祖父节点颜色为红色 将z上移两层
*/
z.Parent.color = BLACK;
y.color = BLACK;
z.Parent.Parent.color = RED;
z = z.Parent.Parent;
} else if (z == z.Parent.left) {// case1.2.2
// 右旋操作,右旋后,z变为右孩子,变为case1.2.3情况
z = z.Parent;
Right_Rotate(z);
} else {// case1.2.3
z.Parent.color = BLACK;
z.Parent.Parent.color = RED;
Left_Rotate(z.Parent.Parent);
}
}
}
// 最后,对根节点进行操作。保证性质2:根节点为黑色成立
root.color = BLACK;
}
public void RB_Delete(Key key) {
Node z = get(key);// 找到key值所在的位置
Node y = null;
// 通过下面的操作,保证y最多只有一个子树
if (z.right == nil || z.left == nil) {// 若z点存在至多一个子树
y = z;
} else {
y = Tree_Successor(z);// 找到后继节点,后继节点为右子树的最左节点,该点最多只有一个右子树
}
Node x = nil;
if (y.left != nil) {
x = y.left;
} else {
x = y.right;
}
x.Parent = y.Parent;
/**
* 三种情况: case1:y为根节点; case2:y为右孩子; case3:y为左孩子
*
*/
if (y.Parent == nil) {// case1
root = x;
} else if (y == y.Parent.right) {// case2
y.Parent.right = x;
} else {// case3
y.Parent.left = x;
}
if (y != z) {// y为后继节点,将z所在点信息替换为y的数据
z.key = y.key;
z.val = y.val;
}
// 若y为红色,则其父节点与子节点均不可能为红,故直接删除无影响
// 若y为黑色,则可能违反红黑树性质,需要进行修正
if (y.color == BLACK) {
RB_Delete_Fixup(x);
}
}
public void RB_Delete_Fixup(Node x) {
while (x != root && x.color == BLACK) {
/**
* 两种情况: case1:x为左子树 case2:x为右子树
*/
if (x == x.Parent.left) {// case1
Node w = x.Parent.right;// 找到兄弟节点
/**
* 四种情况: case1.1:兄弟节点w为红色,则x与w的父节点必为黑色,且w的两个孩子必为黑色 ;
* case1.2:兄弟节点w为黑色,w的两个孩子都是黑色; case1.3:兄弟节点w为黑色,w的左孩子为红,右孩子为黑;
* case1.4:兄弟节点w为黑色,且右孩子为红;
*/
if (w != nil && w.color == RED) {// case1.1
// 修改w与其父节点颜色,对其父节点进行左旋
// 左旋后,变为case1.2/1.3/1.4情况
w.color = BLACK;
x.Parent.color = RED;
Left_Rotate(x.Parent);
} else if (w.left.color == BLACK && w.right.color == BLACK) {// case 1.2
// 将w变红,x上移一层,跳出while循环
w.color = RED;
x = x.Parent;
} else if (w.right.color == BLACK) {// case1.3
// 转化为case1.4
w.left.color = BLACK;
w.color = RED;
Right_Rotate(w);
w = x.Parent.right;
} else {// case 1.4
/**
* w为黑,w的黑色节点路径比x多1; w的左子树黑色节点路径长度与x节点黑色路径长度相等;
* 对x父节点着黑色,并左旋,则x的兄弟节点变为左旋前w的左孩子,黑色路径长度相等; x左旋后父节点为黑,祖父节点为红,增加了一层黑色节点
* x左旋后叔父节点为左旋前w的右子树,并改变颜色从红到黑,增加了一层黑色节点 最后左右平衡
*/
w.color = RED; // 保持父节点为红
w.right.color = BLACK;// 右边加一层黑色
w.Parent.color = BLACK;// 左边加一层黑色
Left_Rotate(w.Parent);
}
} else {// case2
Node w = x.Parent.left;// 找到兄弟节点
/**
* 四种情况: case2.1:兄弟节点w为红色,则x与w的父节点必为黑色,且w的两个孩子必为黑色 ;
* case2.2:兄弟节点w为黑色,w的两个孩子都是黑色; case2.3:兄弟节点w为黑色,w的左孩子为黑,右孩子为红;
* case2.4:兄弟节点w为黑色,且左孩子为红;
*/
if (w.color == RED) {// case2.1
// 修改w与其父节点颜色,对其父节点进行右旋
// 右旋后,变为case2.2/2.3/2.4情况
w.color = BLACK;
x.Parent.color = RED;
Right_Rotate(x.Parent);
} else if (w.left.color == BLACK && w.right.color == BLACK) {// case 2.2
// 将w变红,x上移一层,跳出while循环
w.color = RED;
x = x.Parent;
} else if (w.right.color == BLACK) {// case2.3
// 转化为case2.4
w.right.color = BLACK;
w.color = RED;
Left_Rotate(w);
w = x.Parent.left;
} else {// case 2.4
/**
* w为黑,w的黑色节点路径比x多1; w的右子树黑色节点路径长度与x节点黑色路径长度相等;
* 对x父节点着黑色,并右旋,则x的兄弟节点变为右旋前w的右孩子,黑色路径长度相等; x右旋后父节点为黑,祖父节点为红,增加了一层黑色节点
* x右旋后叔父节点为右旋前w的左子树,并改变颜色从红到黑,增加了一层黑色节点 最后左右平衡
*/
w.color = RED; // 保持父节点为红
w.left.color = BLACK;// 左边加一层黑色
w.Parent.color = BLACK;// 右边加一层黑色
Right_Rotate(w.Parent);
}
}
}
x.color = BLACK;
}
public void Inorder_Tree_Walk(Node x) {
if (x != nil) {
Inorder_Tree_Walk(x.left);
System.out.println(x.key);
Inorder_Tree_Walk(x.right);
}
}
}
int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
RBTree t = new RBTree();
for (int i = 0; i < a.length; i++) {
t.RB_Insert(a[i], a[i]);
}
t.Inorder_Tree_Walk(t.getRoot());
以上代码只是简单做了个测试,如果存在其他问题,请随时指教,谢谢。