zoukankan      html  css  js  c++  java
  • 红黑树

    红黑树的性质

    • 性质1:每个节点要么是黑色,要么是红色。
    • 性质2:根节点是黑色。
    • 性质3:每个叶子节点(NIL)是黑色。
    • 性质4:每个红色结点的两个子结点一定都是黑色。
    • 性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。


    红黑树的添加

    我们可以把红黑树看成是一个四阶b树来理解。对于添加来说,最后的节点一定

    红 红黑 黑黑 这四种,

    如果添加到黑节点的话,不用操作

    添加到红色节点的话,又分为添加到 黑红 红黑 和 红黑红两种

    如果添加到红黑红的话,把黑色节点提到父节点上,然后递归调用add方法

    如果是添加到红黑上面的话,就可通过旋转来完成

    protected void afterAdd(Node<E> node) {
            
            Node<E> parent = node.parent;
    
            if(parent == null){ //如果父节点是空的话,说明此节点是根节点
                black(node);
                return;
            }
    
            if(isBlack(parent)) return;//这是只有黑的请况,不需要处理
    
            Node<E> uncle = node.sibling();
            Node<E> grand = parent.parent;
            
            if(isRed(uncle)){//这是红黑红的情况,此时节点已有3个元素,再添加一个就上溢了,把黑节点变成红色提到父节点上去
                //然后把其他节点拆开,红色节点都变成红色。父节点上有可能又会发生上溢,所以需要递归
                black(parent);
                black(uncle);
                red(grand);
                afterAdd(grand);
                return;
            }
            
            //这是红黑 或者黑红的情况,根据添加顺序的不同,分别进行旋转调节.
            //分为左左 , 右右 , 左右 , 右左
            //分别进行右旋转 , 左旋转 , 左右旋转 , 右左旋转
            if(parent.isLeftChild()){
                if(node.isLeftChild()){
                    rotateRight(grand);
                    red(grand);
                    black(parent);
                }else{
                    rotateLeft(parent);
                    rotateRight(grand);
                    black(node);
                    red(grand);
                }
            }else{
                if(node.isLeftChild()){
                    rotateRight(parent);
                    rotateLeft(grand);
                    red(grand);
                    black(node);
                }else{
                    rotateLeft(grand);
                    red(grand);
                    black(parent);
                }
            }
        }

    红黑树的删除

    删除分为3种情况,

    当删除含有两个子节点的节点时,其实删的是这个节点的前驱或后继节点,所以被删除的元素一定是在4阶b树的最后一层上,也就是 红黑红 黑红 红黑 黑四种情况

    当删除的是红色元素时,不会影响红黑树的结构,

    当删除的是红黑红的黑色节点时,其实删除的是它的两个红色子节点中的一个。

    当删除的 红黑 或黑红的黑色节点时,只需要把红色节点变成黑色就行.

    当删除的是黑色节点时,就需要分多种情况了:

      1.如果这个黑色叶子节点的兄弟节点是黑色的话

        1.如果这个节点有红色子节点的话,通过旋转达到

        2.如果没有红色子节点的话,就把父节点下溢.

      2.如果兄弟节点时红色的话,就把红色节点的子节点当做是被删节点的兄弟节点,因此又回到了情况1.

        public void afterRemove(Node<E> node, Node<E> replacement) {
            Node<E> parent = node.parent;
            
            if(isRed(node)) return; //如果删除的是红色子节点,直接返回
    
            if(isRed(replacement)){//如果删除的是 红黑 和 黑红的情况 , 直接把红色子节点变成黑色
                black(replacement);
                return;
            }
    
            if(parent == null) return; //如果此节点是根节点,直接返回
    
            boolean left = parent.left == null || node.isLeftChild(); //判断删除的是左节点还是有节点
            
            Node<E> sibling = left ? parent.right : parent.left; //被删除节点的兄弟节点
            if(left){
                //被删除的是左边节点
                //操作与被删除右边是对称的
            }else{
                //被删除的是右边节点
                if(isRed(sibling)){//如果它的兄弟节点是红色的话,通过右旋转父节点让红色节点的子节点变成被删的兄弟节点
                    black(sibling);
                    red(parent);
                    rotateRight(parent);
                    //更新兄弟节点
                    sibling = parent.left;
                }
    
                //如果兄弟节点没有红色子节点的话,把父节点下移,如果父节点是黑色的话,需要递归
                if(isBlack(sibling.left) && isBlack(sibling.right)) {
                    boolean parentBlack = isBlack(parent);
                    black(parent);
                    red(sibling);
                    if (parentBlack) {
                        afterRemove(parent, null);
                    }
    
                }else{//兄弟节点至少有一个红色子节点通过旋转达到目的,需要把sibling的颜色变成父节点的颜色
                    if(isBlack(sibling.left)){
                        rotateLeft(sibling);
                        sibling = parent.left;
                    }
    
                    color(sibling,colorOf(parent));
                    black(parent);
                    black(sibling.left);
                    rotateRight(parent);
                }
            }
    
        }
  • 相关阅读:
    开始Flask项目
    夜间模式的开启与关闭,父模板的制作
    从首页问答标题到问答详情页
    首页列表显示全部问答,完成问答详情页布局
    制作首页的显示列表
    发布功能完成
    登录之后更新导航
    完成登录功能,用session记住用户名
    完成注册功能
    通过用户模型,对数据库进行增删改查操作
  • 原文地址:https://www.cnblogs.com/lzh66/p/12976482.html
Copyright © 2011-2022 走看看