红黑树实现

说明

是参考算法导论第三版第十三章写出来的,如果有不正确的地方欢迎指正,写的时候产生了将双向链表和红黑树相结合的想法。所以写出来后插入和查找的时间复杂度和红黑树相同,而且链表中的数据是有序的,里面的迭代器也是根据链表来的,还能以O(1)的时间复杂度找到其中的最大值和最小值。
源码地址:https://github.com/ConfuseCat/IntroductionToAlgorithms

树的结点源码

package RedBlackTree;

public class TreeNode{
    int value;
    //父结点
    TreeNode parent;
    //左孩子
    TreeNode left;
    //右孩子
    TreeNode right;
    //在红黑树中的结点排列顺序中排在这个结点前的结点
    TreeNode last;
    //在红黑树中的结点排列顺序中排在这个结点后的结点
    TreeNode next;
    int color;
    public TreeNode(){
        color=0;
    }
    public TreeNode(int color){
        this.color=color;
    }
    public TreeNode(int value,TreeNode parent,TreeNode left,TreeNode right,int color){
        this.value=value;
        this.parent=parent;
        this.left=left;
        this.right=right;
        this.color=color;
    }

    @Override
    public String toString() {
        return "value:"+this.value+"  color:"+this.color;
    }
}

红黑树实现源码

package RedBlackTree;

import java.util.Iterator;

/**
 * Creat by ConfusedCat
 * 2019.8.5
 * 红黑树的性质
 * 1.每个结点或是红色的,或是黑色的
 * 2.根结点是黑色的
 * 3.每个叶节结点(null)是黑色的
 * 4.如果一个结点是红色的,则它的两个子节点都是黑色的
 * 5.对每个结点,从该结点到其所有的后代叶结点的简单路径上,均包含相同数目的黑色结点
 */

public class RBTree {
    //1表示红色结点
    private final static int RED=1;
    //0表示蓝色结点
    private final static int BLACK=0;
    //树的叶节点
    private final static TreeNode T_NULL=new TreeNode(BLACK);
    //红黑树中结点的数量
    private int size=0;
    //红黑树的根节点
    private TreeNode root;
    //红黑树中值最靠前的结点
    private TreeNode firstNode;

    public RBTree(){
        root=T_NULL;
    }
    public void add(int value){
        TreeNode x=new TreeNode(value,null,T_NULL,T_NULL,RED);
        insert(x);
    }
    public TreeNode getNode(int value){
        TreeNode node=root;
        while(node!=T_NULL){
            if(node.value==value)
                return node;
            if(node.value>value){
                node=node.right;
            }else node=node.left;
        }
        return null;
    }
    public void delete(TreeNode z){RBDelete(z);}
    public Iterator iterator(){return new Iter();}
    public TreeNode getMinNode(){return firstNode;}
    public TreeNode getMaxNode(){return firstNode.last;}
    /**
     * 左旋
     * @param x
     */
    private void leftRotate(TreeNode x){
        TreeNode y=x.right;
        x.right=y.left;
        if(y.left!=T_NULL){
            y.left.parent=x;
        }
        y.parent=x.parent;
        if(x==root){
            root=y;
        }else if(x==x.parent.left){
            x.parent.left=y;
        }else{
            x.parent.right=y;
        }
        y.left=x;
        x.parent=y;
    }

    /**
     * 右旋
     * @param x
     */
    private void rightRotate(TreeNode x){
        TreeNode y=x.left;
        x.left=y.right;
        if(y.right!=T_NULL){
            y.right.parent=x;
        }
        y.parent=x.parent;
        if(x==root){
            root=y;
        }else if(x==x.parent.left){
            x.parent.left=y;
        }else{
            x.parent.right=y;
        }
        y.right=x;
        x.parent=y;
    }

    /**
     * 将结点z插入到红黑树中
     * @param z
     */
    private void insert(TreeNode z){
        size++;
        TreeNode y=T_NULL;
        TreeNode x=root;
        while(x!=T_NULL){
            y=x;
            if(z.value<=x.value){
                x=x.left;
            }else x=x.right;
        }
        z.parent=y;
        if(y==T_NULL){
            root=z;
            firstNode=root;
            root.last=root;
            root.next=root;
        }else if(z.value<=y.value){
            y.left=z;
            z.next=y;
            z.last=y.last;
            y.last.next=z;
            y.last=z;
            //如果y.last的值比z的值大,说明y.last这个结点的值在红黑树中是最大的
            if(z.last.value>z.value)
                firstNode=z;
        }else {
            y.right=z;
            z.next=y.next;
            z.last=y;
            y.next.last=z;
            y.next=z;
        }
        insertFixup(z);
    }

    /**
     * 插入结点后平衡红黑树结构
     * @param z
     */
    private void insertFixup(TreeNode z){
        while (T_NULL!=z.parent&&T_NULL!=z.parent.parent&&z.parent.color==RED){
            //z的父结点为左孩子时
            if(z.parent==z.parent.parent.left){
                TreeNode y=z.parent.parent.right;
                //情况一:z的叔结点的颜色为红色
                if(y.color==RED){
                    z.parent.color=BLACK;
                    y.color=BLACK;
                    z.parent.parent.color=RED;
                    z=z.parent.parent;
                } else{
                    //情况二:z的叔结点的颜色为黑色其z为左孩子
                    if(z==z.parent.right) {
                        z = z.parent;
                        leftRotate(z);
                    }
                    //情况三:情况二之后一定为情况三,z的叔结点的颜色为黑色其z为右孩子
                    z.parent.color=BLACK;
                    z.parent.parent.color=RED;
                    rightRotate(z.parent.parent);
                }
            //z的父结点为右孩子
            }else{
                TreeNode y=z.parent.parent.left;
                //情况一:z的叔结点的颜色为红色
                if(y.color==RED){
                    z.parent.color=BLACK;
                    y.color=BLACK;
                    z.parent.parent.color=RED;
                    z=z.parent.parent;
                } else{
                    //情况二:z的叔结点的颜色为黑色其z为右孩子
                    if(z==z.parent.left) {
                        z = z.parent;
                        rightRotate(z);
                    }
                    //情况三:情况二之后一定为情况三,z的叔结点的颜色为黑色其z为左孩子
                    z.parent.color=BLACK;
                    z.parent.parent.color=RED;
                    leftRotate(z.parent.parent);
                }
            }
        }
        root.color=BLACK;
    }
    /**
     * 使用v结点替换u结点
     * @param u
     * @param v
     */
    private void transplant(TreeNode u,TreeNode v){
        if(u.parent==T_NULL){
            root=v;
        }else if(u==u.parent.left){
            u.parent.left=v;
        }else u.parent.right=v;
        v.parent=u.parent;
    }

    /**
     * 找到以node结点为根结点的子树中的结点的值最小的结点
     * @param node
     * @return
     */
    private TreeNode getMiniMum(TreeNode node){
        while(node.left!=T_NULL){
            node=node.left;
        }
        return node;
    }

    /**
     * 删除红黑树中的结点
     * @param z 需要删除的结点
     */
    private void RBDelete(TreeNode z){
        size--;
        if(size==0) {
            firstNode = T_NULL;
        }else{
            if(firstNode==z)
                firstNode=z.next;
            z.next.last=z.last;
            z.last.next=z.next;
        }
        TreeNode y=z;
        int originalColor=y.color;
        TreeNode x;
        //x的父结点,x为T_NULL时,从红黑树中得不到父结点,所以需要记录
        TreeNode parent;
        //删除结点的左孩子为 T_NULL 时,直接用删除结点的右孩子代替
        if(z.left==T_NULL){
            x=z.right;
            parent=z.parent;
            transplant(z,x);
        //删除结点的右孩子为 T_NULL 时,直接用删除结点的左孩子代替
        }else if(z.right==T_NULL){
            x=z.left;
            parent=z.parent;
            transplant(z,x);
        //删除结点的左右孩子都不为 T_NULL 时,使用删除结点右子树上最小的结点代替
        }else{
            y=getMiniMum(z.right);
            originalColor=y.color;
            //由y的左结点为T_NULL可知,y的右结点为T_NULL或者结点颜色为红色,否则不满足红黑树性质
            x=y.right;
            if(y.parent==z){
                parent=y;
            }else{
                parent=y.parent;
                transplant(y,y.right);
                y.right=z.right;
                y.right.parent=y;
            }
            transplant(z,y);
            y.left=z.left;
            y.left.parent=y;
            y.color=z.color;
        }
        //如果x的结点颜色为BLACK,那么x==T_NULL
        if(originalColor==BLACK)
            deleteFixup(x,parent);
    }

    /**
     * 删除树中的结点后,使树重新具有红黑树的性质
     * @param x 删除的结点的左孩子
     * @param parent 删除结点后,x在树中的父结点
     */
    private void deleteFixup(TreeNode x,TreeNode parent){
        while(x!=root && x.color==BLACK){
            if(x==parent.left){
                TreeNode w=parent.right;
                //情况一:x的兄弟结点w是红色
                if(w.color==RED){
                    parent.color=RED;
                    w.color=BLACK;
                    leftRotate(x.parent);
                    w=parent.right;
                }
                //情况二:x的兄弟结点是黑色的,x的两个孩子也是黑色的
                if(w.left.color==BLACK&&w.right.color==BLACK){
                    w.color=RED;
                    x=parent;
                    parent=parent.parent;
                }else{
                    //情况三:x的兄弟w是黑色的,w的左孩子是红色的,w的右孩子是黑色的
                    if(w.right.color==BLACK){
                        w.left.color=BLACK;
                        w.color=RED;
                        rightRotate(w);
                        w=parent.right;
                    }
                    //情况四:x的兄弟w是黑色的,w的右孩子是红色的
                    w.color=parent.color;
                    parent.color=BLACK;
                    w.right.color=BLACK;
                    leftRotate(x.parent);
                    x=root;
                }
            }else{
                TreeNode w=parent.left;
                //情况一:x的兄弟结点w是红色
                if(w.color==RED){
                    w.color=BLACK;
                    parent.color=RED;
                    rightRotate(parent);
                    w=parent.left;
                }
                //情况二:x的兄弟结点是黑色的,x的两个孩子也是黑色的
                if(w.left.color==BLACK&&w.right.color==BLACK){
                    w.color=RED;
                    x=parent;
                    parent=parent.parent;
                }else{
                    //情况三:x的兄弟w是黑色的,w的右孩子是红色的,w的左孩子是黑色的
                    if(x.left.color==BLACK){
                        w.right.color=BLACK;
                        w.color=RED;
                        leftRotate(w);
                        w=parent.left;
                    }
                    //情况四:x的兄弟w是黑色的,w的左孩子是红色的
                    w.color=parent.color;
                    parent.color=BLACK;
                    w.left.color=BLACK;
                    rightRotate(parent);
                    x=root;
                }
            }
        }
        if(x!=T_NULL)
            x.color=BLACK;
    }
    class Iter implements Iterator<TreeNode>{
        //记录当前遍历的位置
        int loca=0;
        //记录当前遍历的结点
        TreeNode nowNode=firstNode;
        //标识是否调用了next()方法
        boolean mark=false;

        Iter(){}

        @Override
        public boolean hasNext() {
            if(loca<size)
                return true;
            return false;
        }
        @Override
        public TreeNode next() {
            loca++;
            nowNode=nowNode.next;
            mark=true;
            return nowNode.last;
        }
        @Override
        public void remove() {
            if(mark) {
                mark=false;
                RBDelete(nowNode.last);
            }else{
                System.out.println("错误的操作");
            }
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值