红黑树

红黑树

红黑树的查找、插入和删除时间复杂度都为O(log2N)

/**
 * 1. 定义颜色
 * 2. 创建BRNode 结点
 * 3. 辅助方法:parentOf(node)、isRed(node)、isBlack(node)、
 *              setRed(node)、setBlack(node)、isOrderPrint()
 * 4. 左旋 leftRotate(node)、右旋 rightRotate(node)
 * 5. 公开插入 insert(K key,V value)
 * 6. 内部插入 insert(RBNode node)
 * 7. 修正插入导致的失衡 insertFixUp(RBNode node)
 * 8. 测试
 */
public class RBTree<K extends Comparable<K>, V> {
    //1
    private static final boolean RED = true;
    private static final boolean BLACK = false;

    //树根
    private RBNode root;
    public RBNode getRoot() {
        return root;
    }
    public void setRoot(RBNode root) {
        this.root = root;
    }

    //3.1 获取父结点 parentOf(node)
    private RBNode parentOf(RBNode node){
        if(node != null){
            return node.parent;
        }
        return null;
    }

    //3.2 是否为红结点 isRed(node)
    private boolean isRed(RBNode node){
        if(node != null){
            return node.color==RED;
        }
        return false;
    }
    //3.3 是否为黑结点 isBlack(node)
    private boolean isBlack(RBNode node){
        if(node != null){
            return node.color==BLACK;
        }
        return false;
    }

    //3.4 设置结点为红 setRed(node)
    private void setRed(RBNode node){
        if(node != null){
            node.color = RED;
        }
    }
    //3.5 设置结点为黑 setBlack(node)
    private void setBlack(RBNode node){
        if(node != null){
            node.color = BLACK;
        }
    }

    //3.6 中序打印  isOrderPrint()
    public void isOrderPrint(){
        isOrderPrint(this.root);  // 重载+递归
    }
    private void isOrderPrint(RBNode node){
        if(node != null){
            isOrderPrint(node.left);    //先遍历左边 如果没有 就回来 输出中结点
            System.out.println("key: "+node.key+" ,value: "+node.value);
            isOrderPrint(node.right);
        }
    }

    /**
     * 4.1 左旋
     *      p             p
     *      |             |
     *      x             y
     *     /\    -->     /\
     *   lx  y          x  ry
     *      /\         /\
     *    ly  ry     lx  ly
     *
     * 1. 将ly转为x的右节点;  ly的父结点为x
     * 2. 将x的父结点p(若有)赋值成y的父节点;  父节点p的子结点为y(看是左是右)
     * 3. x的父节点变成了y;  y的左子结点变成x
     */
    private void leftRotate(RBNode x){
        if(x != null){
            //先设左旋后的父节点为y
            RBNode y = x.right;
            //1. 将 ly转为x的右节点
            x.right = y.left;         //(x的右结点 -> ly)
            //1. ly的父结点为x
            if(y.left!=null) {
                y.left.parent = x;    //(ly的父节点 -> x)
            }

            //2.1 将x的父结点p(若有)赋值给y的父节点
            if(x.parent!=null) {
                y.parent = x.parent;     //(y的父结点 -> p)

                //2.2 父节点p的子结点为y   //(p的子节点- >y)
                if (x == x.parent.left) { //如果x是父节点的左结点
                    x.parent.left = y;
                } else {
                    x.parent.right = y;
                }
            }else{  //x就是根结点
                this.root = y;  //y为根结点
                y.parent = null;
            }

            //3.1 x的父节点变成y
            x.parent = y;           // (x的父结点 -> y)
            //3.2 y的左子结点变成x
            y.left = x;             // (y的左结点 -> x)
        }
    }
    /**
     * 4.2 右旋
     *      p             p
     *      |             |
     *      x             y
     *     /\    -->     /\
     *    y  rx        ly  x
     *   /\               /\
     * ly  ry           ry  rx
     *
     **/
    private void rightRotate(RBNode x){
        if(x != null){
            //先设右旋后的父节点为y
            RBNode y = x.left;
            //1. 将 ry转为x的左节点
            x.left = y.right;         //(x的右结点 -> ly)
            //1. ly的父结点为x
            if(y.right!=null) {
                y.right.parent = x;    //(ly的父节点 -> x)
            }

            //2.1 将x的父结点p(若有)赋值给y的父节点
            if(x.parent!=null) {
                y.parent = x.parent;     //(y的父结点 -> p)

                //2.2 父节点p的子结点为y   //(p的子节点- >y)
                if (x == x.parent.left) { //如果x是父节点的左结点
                    x.parent.left = y;
                } else {
                    x.parent.right = y;
                }
            }else{  //x就是根结点
                this.root = y;  //y为根结点
                y.parent = null;
            }

            //3.1 x的父节点变成y
            x.parent = y;           // (x的父结点 -> y)
            //3.2 y的左子结点变成x
            y.right = x;             // (y的左结点 -> x)
        }
    }

    //5. 公开插入 insert(K key,V value)
    public void insert(K key,V value){
        RBNode node = new RBNode();
        node.setKey(key);
        node.setValue(value);
        //新结点 一定是红色
        node.setColor(RED);
        insert(node);
    }

    //6. 内部插入 insert(RBNode node)
    private void insert(RBNode node){
        //查找父结点
        RBNode parent = null;
        RBNode p = this.root;
        while(p!=null){
            parent = p;
            int cmp = node.key.compareTo(p.key);
            if(cmp>0){
                p = p.right;
            }else if(cmp<0){
                p = p.left;
            }else{
                p.setValue(node.getValue());
                //不用说这个,因为是直接替换,所以这个key还是相同 他的父关系并没有变
                //虽然parent改变了  但是他并没有将这个parent设置成自己的parent
                //依旧是之前的parent
//                node.parent = p.parent;
                return;
                //break;
            }
        }
        //如果不是替换,而是添加到空白区域
        node.parent = parent;
        if(parent!=null){
            int cmp = node.key.compareTo(parent.key);
            if(cmp>0){
                parent.right = node;
            }else{
                parent.left = node;
            }
        }else {
            this.root = node;
        }
        //修复插入导致的平衡
        insertFixUp(node);

    }

    /**
     * 7. 修正插入导致的失衡 insertFixUp(RBNode node)
     *
     * 情景1. 空树: 根结点染黑
     * 情景2. 要插入的结点key已经存在: 不需要处理
     * 情景3. 插入结点的父结点为黑: 不用处理,依然平衡
     * 情景4. 插入结点的父结点为红(爷爷为黑):
     *      4.1 叔叔结点存在 且是红色(父叔双红)
     *              :将父叔染黑,并将爷爷染红,再将爷爷为当前结点,进行下一轮操作
     *      4.2 叔叔为黑或不存在, 父是爷爷的左子树
     *          4.2.1 插入结点是父的左子结点(LL) : 父染黑,爷爷染红,然后以爷爷为中心,右旋
     *          4.2.2 插入结点是父的右子结点(LR) : 以父结点为中心,左旋,得到LL双红的情景(4.2.1),
     *                                              然后以父为当前结点进行下一轮
     *      4.3 叔叔为黑或不存在, 父是爷爷的右子树
     *          4.3.1 插入结点是父的右子结点(RR) : 父染黑,爷爷染红,然后以爷爷为中心,左旋
     *          4.3.2 插入结点是父的左子结点(RL) : 以父结点为中心,右旋,得到RR双红的情景(4.3.1),
     *                                              然后以父为当前结点进行下一轮
     */
    private void insertFixUp(RBNode node){
        //情景1. 空树: 根结点染黑
        this.root.setColor(BLACK);

        RBNode parent = parentOf(node);
        RBNode grandpa = parentOf(parent);
        //情景4. 插入结点的父结点为红(爷爷为黑):爷爷一定不为空
        if(parent!=null && isRed(parent)){
            RBNode uncle = null;
            if (parent == grandpa.left){   //父是左子树
                uncle = grandpa.right;
                //左右共有: 4.1叔叔结点存在 且是红色(父叔双红)
                if(uncle!=null && isRed(uncle)){
                    //将父叔染黑,并将爷爷染红,再将爷爷为当前结点,进行下一轮操作
                    setBlack(parent);
                    setBlack(uncle);
                    setRed(grandpa);
                    insertFixUp(grandpa);
                    return;
                }

                //4.2 叔叔为黑或不存在, 父是爷爷的左子树
                if(uncle==null || isBlack(uncle)){
                    //4.2.1 插入结点是父的左子结点(LL) : 父染黑,爷爷染红,然后以爷爷为中心,右旋
                    if(node==parent.left){
                        setBlack(parent);
                        setRed(grandpa);
                        rightRotate(grandpa);
                        return;
                    }
                    //4.2.2 插入结点是父的右子结点(LR) :
                    //      以父结点为中心,左旋,得到LL双红的情景(4.2.1),然后以父为当前结点进行下一轮
                    if(node==parent.right){
                        leftRotate(parent);
                        insertFixUp(parent);
                        return;
                    }
                }

            }else{      //父是右子树
                uncle = grandpa.left;
                //4.1叔叔结点存在 且是红色(父叔双红)
                if(uncle!=null && isRed(uncle)){
                    //将父叔染黑,并将爷爷染红,再将爷爷为当前结点,进行下一轮操作
                    setBlack(parent);
                    setBlack(uncle);
                    setRed(grandpa);
                    insertFixUp(grandpa);
                    return;
                }
                //4.3 叔叔为黑或不存在, 父是爷爷的右子树
                if(uncle==null || isBlack(uncle)){
                    //4.3.1 插入结点是父的右子结点(RR) : 父染黑,爷爷染红,然后以爷爷为中心,左旋
                    if(node==parent.right){
                        setBlack(parent);
                        setRed(grandpa);
                        leftRotate(grandpa);
                        return;
                    }
                    //4.3.2 插入结点是父的左子结点(RL) :
                    //以父结点为中心,右旋,得到RR双红的情景(4.3.1),然后以父为当前结点进行下一轮
                    if(node==parent.left){
                        rightRotate(parent);
                        insertFixUp(parent);
                        return;
                    }
                }

            }
        }

    }


    //2 结点类
    static class RBNode<K extends Comparable<K>, V>{
        private RBNode left;
        private RBNode right;
        private RBNode parent;
        private boolean color;
        private K key;
        private V value;

        public RBNode getLeft() {
            return left;
        }

        public void setLeft(RBNode left) {
            this.left = left;
        }

        public RBNode getRight() {
            return right;
        }

        public void setRight(RBNode right) {
            this.right = right;
        }

        public RBNode getParent() {
            return parent;
        }

        public void setParent(RBNode parent) {
            this.parent = parent;
        }

        public boolean isColor() {
            return color;
        }

        public void setColor(boolean color) {
            this.color = color;
        }

        public K getKey() {
            return key;
        }

        public void setKey(K key) {
            this.key = key;
        }

        public V getValue() {
            return value;
        }

        public void setValue(V value) {
            this.value = value;
        }

        public RBNode() {
        }

        public RBNode(RBNode left, RBNode right, RBNode parent, boolean color, K key, V value) {
            this.left = left;
            this.right = right;
            this.parent = parent;
            this.color = color;
            this.key = key;
            this.value = value;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值