红黑树插入实验

一、题目 

题目:红黑树插入算法          实验目的:实现有效的红黑树插入算法

二、算法思想

① 第一步和一般的搜索二叉树没什么区别。从树根开始搜索,如果插入值比节点大,就向右子树搜索,比节点小则向左子树搜索。直到走到叶节点位置,将插入值放在这个节点上。并标记它为红色。

② 之后,红黑树可能需要调整平衡。

对第4条性质的恢复,根据Z的父节点是Z的祖节点的左子节点还是右子节点,分为两组对称的情况,每组有3种情况。下面我们只对其中一组进行说明,以Z的父节点是Z祖节点的左子节点为例:

[第一种:Z的“叔父”节点是红色]:

在这种情况下,将父、叔节点都着为黑色,再将子树根节点着为红色,那么子树的黑高度没有发生改变,而且红黑性质得得到了调整。此时,再将Z指向子树的根节点,向上递归恢复红黑特性。

[第二种:Z的“叔父”节点是黑色的,Z是父节点的左子节点]

将Z的 父节点与祖节点进行一次右旋,并把父节点着黑色,原来的祖节点着红色。这些子树的红黑特性得到了恢复,而且子树的黑高度没有变化。另外,由于子树根节点已 经是黑色了(这个节点不会出现父子同为红色的问题了),所以不必再向上递归了,此时整个树的红黑特性都已经是正确的了。

[第三种:Z的“叔父”节点是黑色的,Z是父节点的右子节点]

将Z本身与其父节点进行一次左旋,让Z指向原来的父节点,就可以调整为情况二,而情况二已经得到解决。

这样,红黑树的节点插入问题就得到了解决。

三、实验结果

四、结果分析

实验结果的输入来自课堂作业的题目,经验证,结果正确,表明程序有效。

五、总结

l 红黑树是一种自平衡二叉查找树,典型的用途是实现关联数组。它的操作有着良好的最坏情况运行时间,并且在实践中是高效的它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。

l 插入实际上是原地算法,因为上述所有调用都使用了尾部递归。

附件:

源程序:RBTreeExperiment.java

/** 
 * @author 
 * Email: 
 * 创建时间:2012-11-09 下午6:44:52
 * 类说明  :红黑树插入算法
 * @version 
 */
public class RBTreeExperiment
{
    
    public static void main(String args[]) {
    	RBTree rb = new RBTree();
    	RBTree.rb_insert(rb,new RBTreeNode(41));
    	RBTree.rb_insert(rb,new RBTreeNode(38));
    	RBTree.rb_insert(rb,new RBTreeNode(31));
    	RBTree.rb_insert(rb,new RBTreeNode(12));
    	RBTree.rb_insert(rb,new RBTreeNode(19));
    	RBTree.rb_insert(rb,new RBTreeNode(8));
    	System.out.println("依次插入值为41,38,31,12,19,8的节点后,中序遍历红黑树各节点:");
        RBTree.inOrderTraverse(rb.root);
    }
}

class RBTree{
    public int number;
    public RBTreeNode root;
    public final static int RED=0;
    public final static int BLACK=1;
    
    public static void left_rotate(RBTree rb,RBTreeNode x) {//对x节点左旋转
        if((rb==null) || (x==null))return;
        //set y
        RBTreeNode y = x.right;
        //turn y's left subtree into x's right subtree
        x.right = y.left;
        if(y.left != null) {
            y.left.p = x;
        }
        //link x's parent to y
        y.p=x.p;
        if(x.p == null) {
            rb.root = y;
        }
        else if(x == x.p.left){
            x.p.left=y;
        }
        else {
            x.p.right=y;
        }
        //put x on y's left
        y.left=x;
        x.p=y;
    }
    public static void right_rotate(RBTree rb,RBTreeNode y) {//对y节点右旋转
        if((rb==null) || (y==null))return;
        //set x
        RBTreeNode x = y.left;
        //turn x's right subtree into y's left subtree
        y.left=x.right;
        if(x.right != null) {
            x.right.p = y;
        }
        //link y's parent to x
        x.p=y.p;
        if(y.p == null) {
            rb.root = x;
        }
        else if(y == y.p.left){
            y.p.left=x;
        }
        else {
            y.p.right=x;
        }
        //put y on x's right
        x.right=y;
        y.p=x;
    }
    public static void rb_insert(RBTree rb,RBTreeNode z){//在rb中插入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;
        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.number++;
        rb_insert_fixup(rb,z);
    }
    public static void rb_insert_fixup(RBTree rb,RBTreeNode z) {//调整插入后的树
        while((z.p != null) && (z.p.color == RED)){
            if((z.p.p != null) && (z.p == z.p.p.left)) { //父亲节点是祖先节点的左孩子
                RBTreeNode y=z.p.p.right;//uncle y
                if((y != null) && (y.color==RED)) {
                    z.p.color=BLACK;
                    y.color=BLACK;
                    z.p.p.color=RED;
                    z=z.p.p;//important
                }
                else {
                    if(z==z.p.right) {
                        z=z.p;
                        left_rotate(rb,z);
                    }
                    z.p.color=BLACK;
                    z.p.p.color=RED;
                    right_rotate(rb,z.p.p);
                }
            }
            else if(z.p.p != null){//父亲节点是祖先节点的右孩子
                RBTreeNode y=z.p.p.left;//uncle y
                if((y != null) && (y.color==RED)) {
                    z.p.color=BLACK;
                    y.color=BLACK;
                    z.p.p.color=RED;
                    z=z.p.p;//important
                }
                else {
                    if(z==z.p.left) {
                        z=z.p;
                        right_rotate(rb,z);
                    }
                    z.p.color=BLACK;
                    z.p.p.color=RED;
                    left_rotate(rb,z.p.p);
                }
            }
            
        }
        rb.root.color=BLACK;
    }
    
    public static void inOrderTraverse(RBTreeNode root) {
        if(root==null)return;
        inOrderTraverse(root.left);
        if(root.color==RBTree.BLACK) {
            System.out.println("black\t"+root.key);
        }
        else {
            System.out.println("red\t"+root.key);
        }
        inOrderTraverse(root.right);
    }
}

class RBTreeNode{
    public RBTreeNode p;
    public RBTreeNode left;
    public RBTreeNode right;
    public int key;
    public int color;
    public RBTreeNode() {} //提供无参构造器。以后可能会用到继承
    public RBTreeNode(int key) {
    	this.key=key;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值