红黑树Java

建议配合算法导论伪代码一起阅读,便于理解。

package test;

public class BTtree {
    //左旋,右孩子不能为空,因为右孩子要成为cur的父节点
    public void leftRotate(Root T, Node cur){
        Node right = cur.right;
        cur.right = right.left;
        if(right.left!=T.nil)
            right.left.parent=cur;
        Node parent = cur.parent;
        if(parent==null){
            T.root=cur;
        }else if(parent.left==cur){
            parent.left=right;
        }else{
            parent.right = right;
        }
        right.parent = parent;
        cur.parent=right;
        right.left=cur;
    }
    //右旋,左孩子不能为空
    public void rightRotate(Root T, Node cur){
        Node left = cur.left;
        cur.left = left.right;
        if(left.right!=T.nil)
            left.right.parent=cur;
        Node parent = cur.parent;
        if(parent==null){
            T.root = left;
        }else if(parent.left==cur){
            parent.left=left;
        }else{
            parent.right = left;
        }
        left.parent = parent;
        cur.parent=left;
        left.right=cur;
    }
    public void RB_insert(Root T,Node z){
        Node y = null;
        Node x = T.root;
        while (x!=null){
            y=x;
            if(z.val<x.val){
                x=x.left;
            }else{
                x=x.right;
            }
        }
        z.parent = y;
        //判断是否根节点为空
        if(T.root==null){
            T.root = z;
        }else if(z.val<y.val){
            y.left=z;
        }else {
            y.right=z;
        }
        z.left=T.nil;
        z.right=T.nil;
        z.color=1;
        RB_insert_fixup(T,z);
    }
    //旋转时可以推断出左右孩子满足相应的不为空的条件
    public void RB_insert_fixup(Root T,Node z){
        Node cur = z;
        while (cur.parent!=null&&cur.parent.color==1){
            if(cur.parent==cur.parent.parent.left){
//由于cur.parent为红故cur.parent.parent必定不是null所以不需要判断。
//cur.parent是未经过改变颜色前已经是红色,可以证明其父节点必定存在
 //并且叔叔节点一定不为null,如果叔叔为null,红黑树不平衡
                //叔叔节点为红色
                Node uncle = cur.parent.parent.right;
                if(uncle.color==1) {
                    cur.parent.color=0;
                    uncle.color=0;
                    cur.parent.parent.color=1;
                    cur=cur.parent.parent;
                }else {//叔叔节点为黑色,且下面未对叔叔节点进行调整
                    if(cur==cur.parent.right){
                        cur=cur.parent;
                        leftRotate(T,cur);
                    }
                    cur.parent.color=0;
                    cur.parent.parent.color=1;
                    rightRotate(T,cur.parent.parent);
                }
            }else{
                Node uncle = cur.parent.parent.left;
                //叔叔节点为红色
                if(uncle.color==1) {
                    cur.parent.color=0;
                    uncle.color=0;
                    uncle.parent.color=1;
                    cur=cur.parent.parent;
                }else{//叔叔节点为null
                    if(cur==cur.parent.left){
                        cur=cur.parent;
                        rightRotate(T,cur);
                    }
                    cur.parent.color=0;
                    cur.parent.parent.color=1;
                    leftRotate(T,cur.parent.parent);
                }
            }
        }
        T.root.color=0;
    }
    public void RB_TRANSPLANT(Root T,Node u,Node v){
        if(u.parent==null){
            T.root=v;
        }else if(u.parent.left==u){
            u.parent.left=v;
        }else{
            u.parent.right=v;
        }//由于T.nil的存在v不可能为null
        v.parent=u.parent;
    }
    public Node RB_DELETE(Root T,Node z){
       /* ① 被删除节点没有儿子,即为叶节点。那么,直接将该节点删除就OK了。
       ② 被删除节点只有一个儿子。那么,直接删除该节点,并用该节点的唯一子节点顶替它的位置。
       ③ 被删除节点有两个儿子。那么,先找出它的后继节点;然后把“它的后继节点的内容”复制给“该节点的内容”;
       之后,删除“它的后继节点”。在这里,后继节点相当于替身,在将后继节点的内容复制给"被删除节点"之后,再将后继节点删除。
       这样就巧妙的将问题转换为"删除后继节点"的情况了,下面就考虑后继节点。 在"被删除节点"有两个非空子节点的情况下,
       它的后继节点不可能是双子非空。既然"的后继节点"不可能双子都非空,就意味着"该节点的后继节点"要么没有儿子,
       要么只有一个儿子。若没有儿子,则按"情况① "进行处理;若只有一个儿子,则按"情况② "进行处理。
       */
       Node y = null;
        Node x = null;
        //若左右孩子有一个为空,把z赋给y. 则直接删除当前节点
        if(z.left==T.nil||z.right==T.nil){
            y=z;
            //否则把中序遍历z的后继节点赋值给y
        }else{
            y=TREE_SUCCESSOR(T,z);
        }
        //y的左孩子不是空
        if(y.left != T.nil){
            x = y.left;
        }else {
            x=y.right;
        }
        x.parent = y.parent;
        if(y.parent==T.nil){
            T.root=x;
        }else if(y==y.parent.left){
            y.parent.left=x;
        }else{
            y.parent.right=x;
        }
        if(y!=z){
            z.val=y.val;
        }
        if(y.color==0){
            RB_DELETE_FIXUP(T,x);
        }
        return y;
    }
    public Node TREE_SUCCESSOR(Root T,Node z){
        if(z.right!=T.nil){
            return TREE_MINNUM(T,z.right);
        }
        Node y =z.parent;
        while (y!=T.nil&&z==y.right){
            z=y;
            y=y.parent;
        }
        return y;
    }
    public Node TREE_MINNUM(Root T,Node x){
        while (x.left!=T.nil){
            x=x.left;
        }
        return x;
    }
    public void RB_DELETE_FIXUP(Root T,Node x){
        //如果没有T.nil后补的节点可能为null则会出错
        while (x!=T.root&&x.color==0){
            if(x==x.parent.left){
                Node brother = x.parent.right;//broter必定不是空
                //case1兄弟节点为红色。经过case1后兄弟节点必定为黑色。因为兄弟节点变为了原红色节点的子节点。
                if(brother.color==1){
                    x.parent.color=1;
                    brother.color=0;
                    leftRotate(T,x.parent);
                    brother = x.parent.right;
                }
                //case2兄弟子节点都为黑色,由性质推断出brother两个孩子都不为空。
                //若x.p为红色,则结束,因为兄弟节点黑高减一,否则x.p表示两重黑色,
                if(brother.left.color==0&&brother.right.color==0){
                    brother.color=1;
                    x=x.parent;
                }//有一个孩子不为黑色
                else{
                    //case3左孩子为红色,右孩子为黑色,转化为情况四
                    if(brother.right.color==0){
                        brother.color=1;
                        brother.left.color=0;
                        rightRotate(T,brother);
                        brother=x.parent.right;
                    }
                    brother.color=x.parent.color;//如果直接令brother.color=1;会出现黑高与其他分支不等
                    x.parent.color=0;
                    brother.right.color=0;
                    leftRotate(T,x.parent);
                    x=T.root;
                }
            }else {
                Node brother = x.parent.left;
                if(brother.color==1){
                    x.parent.color=1;
                    brother.color=0;
                    rightRotate(T,x.parent);
                    brother=x.parent.left;
                }
                if(brother.left.color==0&&brother.right.color==0){
                    brother.color=1;
                    x=x.parent;
                }
                else{
                    if(brother.left.color==0){
                        brother.color=1;
                        brother.right.color=0;
                        leftRotate(T,brother);
                        brother=x.parent.left;
                    }
                    brother.color=x.parent.color;
                    x.parent.color=0;
                    brother.left.color=0;
                    rightRotate(T,x.parent);
                    x=T.root;
                }
            }
        }
        x.color=0;
    }
}
class Root{
    public Node root;
    public Node nil=new Node();
    public Root(){
        nil.color=0;
    }
}
class Node {
    public int val;
    public Node parent=null;
    public int color;//1为红色0为黑色
    public Node left=null;
    public Node right=null;
    public Node(int val) {
        this.val = val;
    }
    public Node(){}
}



发布了79 篇原创文章 · 获赞 0 · 访问量 2658

猜你喜欢

转载自blog.csdn.net/qq_41017546/article/details/104654854