算法步骤:
(1).第一步按BST树规则将结点z插入红黑树中。即从树根开始搜索,如果插入值比节点大,就向右子树搜索,比节点小则向左子树搜索。直到走到叶节点位置,将插入值放在这个节点上。此节点为叶子节点。并将他标记为红色。
(2)插入z后可能违反红黑树性质2和4。对于违反性质2只需将根节点涂黑即可。对于违反性质4,可以分成6中情况。其中根据z的父节点是z的祖节点的左子节点还是右子节点,分为两组对称的情况,每组有3种情况。因为两组是对称的,我们讨论z的父节点是z的祖节点的左子节点的三种情况。
Case1:z的叔叔节点y是红色:
将z的父、叔节点都着为黑色,再z的祖父节点着为红色,再将z指向子树的根节点,向上递归恢复红黑特性。
Case2:z的叔叔节点y是黑色,其z是双亲的右孩子:
将z指向其父节点,再将左旋z节点,则情况转化为case3。
Case3:z的叔叔节点y是黑色,其z是双亲的左孩子:
将z的父节点与祖节点进行一次右旋,并把父节点着黑色,原来的祖节点着红色。这些子树的红黑特性得到了恢复,而且子树的黑高度没有变化。
这样,红黑树的节点插入问题就得到了解决。
实验随机插入1000个节点,并将树高打印出来。
其代码:
package rb;
public class RBTreeNode {
public RBTreeNode p;
public RBTreeNode left;
public RBTreeNode right;
public int key;
public String color;
public RBTreeNode() {}
public RBTreeNode(int key)
{
this.key = key;
}
}
package rb;
public class RBTree {
public RBTreeNode root;
/*对x节点左旋转 */
public static void Left_Rotate(RBTree rb,RBTreeNode x)
{
RBTreeNode y = x.right; //set y
x.right = y.left; //turn y's left subtree into x's right subtree
if(y.left!=null)
{
y.left.p = x;
}
y.p = x.p; //link x's parent to y
if(x.p == null)
rb.root = y;
else if (x == x.p.left )
{
x.p.left = y;
}
else
x.p.right = y;
y.left = x; //put x on y's left
x.p = y;
}
/*对y节点右旋转 */
public static void Right_Rotate(RBTree rb,RBTreeNode y)
{
RBTreeNode x = y.left; //set x
y.left = x.right; //turn x's left subtree into y's right subtree
if(x.right!=null)
{
x.right.p = y;
}
x.p = y.p; //link y's parent to x
if(y.p == null)
rb.root = x;
else if (y == y.p.left )
{
y.p.left = x;
}
else
y.p.right = x;
x.right = y; //put y on x's right
y.p = x;
}
/*在rb中插入z节点 */
public static void rb_insert(RBTree rb,RBTreeNode z){
if(z==null)return;
RBTreeNode y= null; //用于记录当前扫描节点的双亲节点
RBTreeNode x= rb.root;//从根节点开始查找
/*查找插入位置*/
while(x != null){
y=x;
if(z.key < x.key)
x = x.left;
else
x = x.right;
}
z.p = y;// 将z插入y之后,即y是z的双亲
if(y == null)
{
rb.root = z;
}
else if(z.key < y.key)
{
y.left = z;
}
else
{
y.right = z;
}
z.left = null;
z.right = null;
z.color = "RED";
rb_insert_fixup(rb,z);
}
public static void rb_insert_fixup(RBTree rb, RBTreeNode z) {
// TODO Auto-generated method stub
while(z.p != null && z.p.color.equals("RED"))
{
if((z.p.p != null) && (z.p == z.p.p.left)) //case1-case3 z的父节点是其祖父节点的左孩子
{
RBTreeNode y = z.p.p.right; //y是z的叔叔节点
if((y != null) && y.color.equals("RED")) //case1
{
z.p.color = "BLACK";
y.color = "BLACK";
z.p.p.color = "RED";
z = z.p.p;
}
else{
if(z == z.p.right)//case2
{
z = z.p;
Left_Rotate(rb, z);
}
z.p.color = "BLACK";//case3
z.p.p.color = "RED";
Right_Rotate(rb, z.p.p);
}
}
else if((z.p.p != null) && (z.p == z.p.p.right)) //case4-case6 z的父节点是其祖父节点的右孩子
{
RBTreeNode y = z.p.p.left; //y是z的叔叔节点
if((y != null) && y.color.equals("RED")) //case4
{
z.p.color = "BLACK";
y.color = "BLACK";
z.p.p.color = "RED";
z = z.p.p;
}
else{
if(z == z.p.left)//case5
{
z = z.p;
Right_Rotate(rb, z);
}
z.p.color = "BLACK";//case6
z.p.p.color = "RED";
Left_Rotate(rb, z.p.p);
}
}
}
rb.root.color = "BLACK";
}
/*红黑树高*/
public static int High(RBTreeNode root)
{
int left_h ;
int right_h ;
if(root == null)
{
return 0;
}
else{
left_h = High(root.left);
right_h=High(root.right);
return (left_h>right_h?left_h+1:right_h+1);
}
}
}
package rb;
import java.util.Random;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int height = 0;
Random rd = new Random();
RBTree rb = new RBTree();
for(int i = 0; i < 1000; i++)
{
RBTree.rb_insert(rb,new RBTreeNode(rd.nextInt(1000)));
}
height=RBTree.High(rb.root);
System.out.println("红黑树高:"+height);
}
}