11. 红黑树

 11. 红黑树

红黑树也是一种自平衡的二叉搜索树,较之 AVL,插入和删除时旋转次数更少
红黑树特性
        1.所有节点都有两种颜色:红与黑
        2.所有 null 视为黑色
        3.红色节点不能相邻
        4.根节点是黑色
        5.从根到任意一个叶子节点,路径中的黑色节点数一样(黑色完美平衡)

补充:黑色叶子结点一般是成对出现,单独出现必定不平衡

11.1 node内部类

private static class Node {
        int key;
        Object value;
        Node left;
        Node right;
        Node parent;//父节点
        Color color = RED;//颜色

        //是否是左孩子,左未true,右为false
        boolean isLeftChild() {
            return parent != null && this == parent.left;
        }
        //获取叔叔节点
        Node uncle() {
            //有父节点,和父节点的父节点才能有叔叔节点
            if (parent == null || parent.parent == null) {
                return null;
            }
            if (parent.isLeftChild()) {
                //如果父亲为左子节点则返回右子节点,
                return parent.parent.right;
            } else {
                //如果父亲为右子节点则返回左子节点
                return parent.parent.left;
            }
        }
        //获取兄弟节点
        Node sibling() {
            if(parent==null){
                return null;
            }
            if(this.isLeftChild()){
                return parent.right;
            }else {
                return parent.left;
            }
        }

    }

11.2 判断颜色

//判断颜色
    boolean isRed(Node node){
       return node!=null&&node.color==RED;
    }
    boolean isBlack(Node node){
        return node==null||node.color==BLACK;
    }

11.3 左旋和右旋

//和AVL树的不同
    // 右旋1.父(Parent)的处理2.旋转后新根的父子关系方法内处理
    void rotateRight(Node pink) {
        //获取pink的父级几点
        Node parent = pink.parent;
        //旋转
        Node yellow = pink.left;
        Node gree = yellow.right;
        //右旋之后换色节点的右子结点变为Pink
        yellow.right = pink;

        //之前黄色节点的左子结点赋值给pink,完成右旋
        pink.left = gree;
        if (gree != null) {
            //处理父子关系
            gree.parent = pink;
        }
        //处理父子关系
        yellow.parent = parent;
        pink.parent = yellow;
        //如果parent为空则根节点为yellow
        if (parent == null) {
            root = yellow;
        } else if (parent.left == pink) {
            //处理父子关系,yellow代替pink
            parent.left = yellow;
        } else {
            parent.right = yellow;
        }

    }
    void rotateLeft(Node pink) {
        //获取pink的父级几点
        Node parent = pink.parent;
        //旋转
        Node yellow = pink.right;
        Node gree = yellow.left;
        //右旋之后换色节点的右子结点变为Pink
        yellow.left = pink;

        //之前黄色节点的左子结点赋值给pink,完成右旋
        pink.right = gree;
        if (gree != null) {
            //处理父子关系
            gree.parent = pink;
        }
        //处理父子关系
        yellow.parent = parent;
        pink.parent = yellow;
        //如果parent为空则根节点为yellow
        if (parent == null) {
            root = yellow;
        } else if (parent.right == pink) {
            //处理父子关系,yellow代替pink
            parent.right = yellow;
        } else {
            parent.left = yellow;
        }
    }

11.4 新增或更新

//新增或更新
    void put(int key, Object value) {
        Node p = root;
        Node parent = null;
        while (p != null) {
            parent = p;
            if (key < p.key) {
                //向左找
                p = p.left;
            } else if (key > p.key) {
                p = p.right;
            } else {
                //更新
                p.value = value;
                return;
            }
        }
        //插入
        Node interestNode = new Node(key, value);
        //如果parent为空
        if (parent == null) {
            root = interestNode;
        } else if (key < parent.key) {
            parent.left = interestNode;
            interestNode.parent = parent;
        } else {
            parent.right = interestNode;
            interestNode.parent = parent;
        }
        fixRedRed(interestNode);
    }

    /*
     * 1.所有节点都有两种颜色:红与黑
     * 2.所有 null 视为黑色
     * 3.红色节点不能相邻
     * 4.根节点是黑色
     * 5.从根到任意一个叶子节点,路径中的黑色节点数一样(黑色完美平衡)
     * */
    //修复红红不平衡
    void fixRedRed(Node x) {
        /*
         * 插入节点均视为红色
         * 插入节点的父亲为红色
         * 触发红红相邻
         * case 3:叔叔为红色
         * case 4:叔叔为黑色
         * */
        //case 1:插入节点为根节点,将根节点变黑
        if (x == root) {
            x.color = BLACK;
            return;
        }
        //case 2:插入节点的父亲若为黑色树的红黑性质不变,无需调整
        if (isBlack(x.parent)) {
            return;
        }

        Node parent = x.parent;
        Node uncle = x.uncle();
        Node grandParent = parent.parent;
        //插入节点的父亲为红色
        if (isRed(uncle)) {
            //红红相邻叔叔为红色时(仅通过变色即可)
            /*
             * 为了保证黑色平衡,连带的叔叔也变为黑色·
             * 祖父如果是黑色不变,会造成这颗子树黑色过多,因此祖父节点变为红色祖父如果变成红色,
             * 可能会接着触发红红相邻,因此对将祖父进行递归调整,祖父的父亲变为黑色
             * */
            parent.color = BLACK;
            uncle.color = BLACK;
            grandParent.color = RED;
            fixRedRed(grandParent);
            return;
        } else {
            //触发红红相邻叔叔为黑色
            /*
             * 1.父亲为左孩子,插入节点也是左孩子,此时即 LL不平衡(右旋一次)
             * 2.父亲为左孩子,插入节点是右孩子,此时即 LR不平衡(父亲左旋,祖父右旋)
             * 3.父亲为右孩子,插入节点也是右孩子,此时即 RR不平衡(左旋一次)
             * 4.父亲为右孩子,插入节点是左孩子,此时即 RL不平衡(父亲右旋,祖父左旋)
             *
             */
            if (parent.isLeftChild() && x.isLeftChild()) {
                //如果父亲为左子节点,查询节点也为左子结点即为LL(祖父右旋处理)
                //父节点变黑(和叔叔节点同为黑色)
                parent.color = BLACK;
                //祖父节点变红
                grandParent.color = RED;
                rotateRight(grandParent);
            } else if (parent.isLeftChild() && !x.isLeftChild()) {
                //parent为左子节点,插入节点为右子节点,LR(父亲左旋,祖父右旋)
                rotateLeft(parent);
                //插入节点变为黑色
                x.color=BLACK;
                //祖父变为红色
                grandParent.color=RED;
                rotateRight(grandParent);
            } else if (!parent.isLeftChild()&&!x.isLeftChild()) {
                //父节点变黑(和叔叔节点同为黑色)
                parent.color = BLACK;
                //祖父节点变红
                grandParent.color = RED;
                rotateLeft(grandParent);
            }else if(!parent.isLeftChild()&&x.isLeftChild()){
                rotateRight(parent);
                //插入节点变为黑色
                x.color=BLACK;
                //祖父变为红色
                grandParent.color=RED;
                rotateLeft(grandParent);
            }
        }

    }

11.5 删除

 //删除
    /*
     * 删除
     * 正常删、会用到李代桃僵技巧、遇到黑黑不平衡进行调整
     * */

    public void remove(int key) {
        Node deleted = find(key);
        if (deleted == null) {
            return;
        }
        doRemove(deleted);
    }

    //检测双黑节点删除
    /*
     *
     * 删除节点和剩下节点都是黑触发双黑,双黑意思是,少了一个黑
     * case 3:删除节点或剩余节点的兄弟为红此时两个侄子定为黑
     * case 4:删除节点或剩余节点的兄弟、和兄弟孩子都为黑
     * case 5:删除节点的兄弟为黑,至少一个红侄子
     *
     * */
    private void fixDoubleBlack(Node x) {
        //把case3处理为case4和case5
        if (x == root) {
            return;
        }
        Node parent = x.parent;
        Node sibling = x.sibling();
        if (sibling.color == RED) {
            //进入case3
            if (x.isLeftChild()) {
                //如果是做孩子就进行左旋
                rotateLeft(parent);
            } else {
                //如果是右孩子就进行右旋
                rotateRight(parent);
            }
            //父亲颜色变为红色(父亲变色前肯定为黑色)
            parent.color = RED;
            //兄弟变为黑色
            sibling.color = BLACK;
            //此时case3 已经被转换为 case4或者case5
            fixDoubleBlack(x);
            return;
        }
        //兄弟为黑
        //两个侄子都为黑
        if (sibling != null) {
            if (isBlack(sibling.left) && isBlack(sibling.right)) {
                /*
                 * case 4:被调整节点的兄弟为黑,两个侄于都为黑
                 * 将兄弟变红, 目的是将删除节点和兄弟那边的黑色高度同时减少1
                 * 如果父亲是红,则需将父亲变为黑,避免红红,此时路径黑节点数目不变
                 * 如果父亲是黑,说明这条路径则少了一个黑,再次让父节点触发双黑
                 * */
                //将兄弟变红, 目的是将删除节点和兄弟那边的黑色高度同时减少1
                sibling.color = RED;
                if (isRed(parent)) {
//                    如果父亲是红,则需将父亲变为黑,避免红红,此时路径黑节点数目不变
                    parent.color = BLACK;
                } else {
                    //如果父亲是黑,说明这条路径则少了一个黑,再次让父节点触发双黑
                    fixDoubleBlack(parent);
                }
            } else {
                //CASE5 至少有一个侄子不是黑色
                /*
                 *
                 * case 5:被调整节点的兄弟为黑
                 * 如果兄弟是左孩子,左侄子是红  LL 不平衡
                 * 如果兄弟是左孩子,右侄子是红  LR 不平衡
                 * 如果兄弟是右孩子,右侄于是红  RR 不平衡
                 * 如果兄弟是右孩子,左侄于是红  RL 不平衡
                 * */
                if(sibling.isLeftChild()&&isRed(sibling.left)){
                    // 如果兄弟是左孩子,左侄子是红  LL 不平衡
                    rotateRight(parent);
                    //兄弟的做孩子变黑
                    sibling.left.color=BLACK;
                    //兄弟变成父亲的颜色
                    sibling.color= parent.color;
                    //父亲变黑
                    parent.color=BLACK;
                }else if(sibling.isLeftChild()&&isRed(sibling.right)){
                    //如果兄弟是左孩子,右侄子是红  LR 不平衡
                    //变色必须在上 否则旋转后会空指针
                    //兄弟的右孩子变为父节点颜色
                    sibling.right.color= parent.color;
                    //父节点变黑
                    parent.color=BLACK;
                    rotateLeft(sibling);
                    rotateRight(parent);
                }
            }
        } else {
            fixDoubleBlack(parent);
        }


    }

    private void doRemove(Node deleted) {
        Node replaced = findReplaced(deleted);
        Node parent = deleted.parent;
        if (replaced == null) {
            //没有子节点
            /* case1:删的是根节点,没有子节点
             * 删完了,直接将 root=null
             * */
            if (deleted == root) {
                root = null;
            } else {
                /*
                 * Case2:删的是黑,剩下的是红剩下这个红节点变黑
                 * */
                if (isBlack(deleted)) {
                    //复杂处理,先调整平衡再删除
                    fixDoubleBlack(deleted);
                } else {
                    //红色不处理
                }

                //删除的不是根节点且没有孩子
                if (deleted.isLeftChild()) {
                    parent.left = null;
                } else {
                    parent.right = null;
                }
                deleted.parent = null;
            }
            return;
        } else if (replaced.left == null || replaced.right == null) {
            //有一个子节点
            /* case1:删的是根节点,有一个子节点
             * 用剩余节点替换了根节点的 key,Value,根节点孩子=null,颜色保持黑色 不变
             * */
            if (deleted == root) {
                root.key = replaced.key;
                root.value = replaced.value;
                root.left = root.right = null;
            } else {
                //删除的不是根节点但是有一个孩子
                if (deleted.isLeftChild()) {
                    parent.left = replaced;
                } else {
                    parent.right = replaced;
                }
                replaced.parent = parent;
                deleted.right = deleted.left = deleted.parent = null;
                if (isBlack(deleted) && isBlack(replaced)) {
                    //如果删除的是黑色剩下的也是黑色,需要复杂处理,先删除再平衡
                    fixDoubleBlack(replaced);
                } else {
                    /*
                     * Case2:删的是黑,剩下的是红剩下这个红节点变黑
                     * */
                    replaced.color = BLACK;
                }

            }
            return;
        } else {
            //两个子节点
            //交换删除节点和删除节点的后几点的key,value,这
            // 样被删除节点就只有一个子节点或没有子节点了
            int t = deleted.key;
            deleted.key = replaced.key;
            replaced.key = t;
            Object v = deleted.value;
            deleted.value = replaced.value;
            replaced.value = v;
            doRemove(replaced);
            return;
        }

    }

    private Node find(int key) {
        Node p = root;
        while (p != null) {
            if (key > p.key) {
                //key更大向右找
                p = p.right;
            } else if (key < p.key) {
                //向左找
                p = p.left;
            } else {
                return p;
            }
        }
        return null;
    }

    //查找删除后的剩余节点
    private Node findReplaced(Node deleted) {
        if (deleted.left == null & deleted.right == null) {
            //没有子节点
            return null;
        } else if (deleted.left == null) {
            return deleted.right;
        } else if (deleted.right == null) {
            return deleted.left;
        } else {
            Node s = deleted.right;
            while (s != null) {
                //右子树的最小值
                s = s.left;
            }
            return s;
        }
    }
}

 11.6 完整代码

package org.alogorithm.tree;

import static org.alogorithm.tree.RedBlackTree.Color.BLACK;
import static org.alogorithm.tree.RedBlackTree.Color.RED;

public class RedBlackTree {
    enum Color {RED, BLACK}

    private Node root;

    private static class Node {
        int key;
        Object value;
        Node left;
        Node right;
        Node parent;//父节点
        Color color = RED;//颜色

        public Node() {
        }

        public Node(int key, Object value) {
            this.key = key;
            this.value = value;
        }

        //是否是左孩子,左未true,右为false
        boolean isLeftChild() {
            return parent != null && this == parent.left;
        }

        //获取叔叔节点
        Node uncle() {
            //有父节点,和父节点的父节点才能有叔叔节点
            if (parent == null || parent.parent == null) {
                return null;
            }
            if (parent.isLeftChild()) {
                //如果父亲为左子节点则返回右子节点,
                return parent.parent.right;
            } else {
                //如果父亲为右子节点则返回左子节点
                return parent.parent.left;
            }
        }

        //获取兄弟节点
        Node sibling() {
            if (parent == null) {
                return null;
            }
            if (this.isLeftChild()) {
                return parent.right;
            } else {
                return parent.left;
            }
        }

    }

    //判断颜色
    boolean isRed(Node node) {
        return node != null && node.color == RED;
    }

    boolean isBlack(Node node) {
        return node == null || node.color == BLACK;
    }

    //和AVL树的不同
    // 右旋1.父(Parent)的处理2.旋转后新根的父子关系方法内处理
    void rotateRight(Node pink) {
        //获取pink的父级几点
        Node parent = pink.parent;
        //旋转
        Node yellow = pink.left;
        Node gree = yellow.right;
        //右旋之后换色节点的右子结点变为Pink
        yellow.right = pink;

        //之前黄色节点的左子结点赋值给pink,完成右旋
        pink.left = gree;
        if (gree != null) {
            //处理父子关系
            gree.parent = pink;
        }
        //处理父子关系
        yellow.parent = parent;
        pink.parent = yellow;
        //如果parent为空则根节点为yellow
        if (parent == null) {
            root = yellow;
        } else if (parent.left == pink) {
            //处理父子关系,yellow代替pink
            parent.left = yellow;
        } else {
            parent.right = yellow;
        }

    }

    void rotateLeft(Node pink) {
        //获取pink的父级几点
        Node parent = pink.parent;
        //旋转
        Node yellow = pink.right;
        Node gree = yellow.left;
        //右旋之后换色节点的右子结点变为Pink
        yellow.left = pink;

        //之前黄色节点的左子结点赋值给pink,完成右旋
        pink.right = gree;
        if (gree != null) {
            //处理父子关系
            gree.parent = pink;
        }
        //处理父子关系
        yellow.parent = parent;
        pink.parent = yellow;
        //如果parent为空则根节点为yellow
        if (parent == null) {
            root = yellow;
        } else if (parent.right == pink) {
            //处理父子关系,yellow代替pink
            parent.right = yellow;
        } else {
            parent.left = yellow;
        }
    }

    //新增或更新
    void put(int key, Object value) {
        Node p = root;
        Node parent = null;
        while (p != null) {
            parent = p;
            if (key < p.key) {
                //向左找
                p = p.left;
            } else if (key > p.key) {
                p = p.right;
            } else {
                //更新
                p.value = value;
                return;
            }
        }
        //插入
        Node interestNode = new Node(key, value);
        //如果parent为空
        if (parent == null) {
            root = interestNode;
        } else if (key < parent.key) {
            parent.left = interestNode;
            interestNode.parent = parent;
        } else {
            parent.right = interestNode;
            interestNode.parent = parent;
        }
        fixRedRed(interestNode);
    }

    /*
     * 1.所有节点都有两种颜色:红与黑
     * 2.所有 null 视为黑色
     * 3.红色节点不能相邻
     * 4.根节点是黑色
     * 5.从根到任意一个叶子节点,路径中的黑色节点数一样(黑色完美平衡)
     * */
    //修复红红不平衡
    void fixRedRed(Node x) {
        /*
         * 插入节点均视为红色
         * 插入节点的父亲为红色
         * 触发红红相邻
         * case 3:叔叔为红色
         * case 4:叔叔为黑色
         * */
        //case 1:插入节点为根节点,将根节点变黑
        if (x == root) {
            x.color = BLACK;
            return;
        }
        //case 2:插入节点的父亲若为黑色树的红黑性质不变,无需调整
        if (isBlack(x.parent)) {
            return;
        }

        Node parent = x.parent;
        Node uncle = x.uncle();
        Node grandParent = parent.parent;
        //插入节点的父亲为红色
        if (isRed(uncle)) {
            //红红相邻叔叔为红色时(仅通过变色即可)
            /*
             * 为了保证黑色平衡,连带的叔叔也变为黑色·
             * 祖父如果是黑色不变,会造成这颗子树黑色过多,因此祖父节点变为红色祖父如果变成红色,
             * 可能会接着触发红红相邻,因此对将祖父进行递归调整,祖父的父亲变为黑色
             * */
            parent.color = BLACK;
            uncle.color = BLACK;
            grandParent.color = RED;
            fixRedRed(grandParent);
            return;
        } else {
            //触发红红相邻叔叔为黑色
            /*
             * 1.父亲为左孩子,插入节点也是左孩子,此时即 LL不平衡(右旋一次)
             * 2.父亲为左孩子,插入节点是右孩子,此时即 LR不平衡(父亲左旋,祖父右旋)
             * 3.父亲为右孩子,插入节点也是右孩子,此时即 RR不平衡(左旋一次)
             * 4.父亲为右孩子,插入节点是左孩子,此时即 RL不平衡(父亲右旋,祖父左旋)
             *
             */
            if (parent.isLeftChild() && x.isLeftChild()) {
                //如果父亲为左子节点,查询节点也为左子结点即为LL(祖父右旋处理)
                //父节点变黑(和叔叔节点同为黑色)
                parent.color = BLACK;
                //祖父节点变红
                grandParent.color = RED;
                rotateRight(grandParent);
            } else if (parent.isLeftChild() && !x.isLeftChild()) {
                //parent为左子节点,插入节点为右子节点,LR(父亲左旋,祖父右旋)
                rotateLeft(parent);
                //插入节点变为黑色
                x.color = BLACK;
                //祖父变为红色
                grandParent.color = RED;
                rotateRight(grandParent);
            } else if (!parent.isLeftChild() && !x.isLeftChild()) {
                //父节点变黑(和叔叔节点同为黑色)
                parent.color = BLACK;
                //祖父节点变红
                grandParent.color = RED;
                rotateLeft(grandParent);
            } else if (!parent.isLeftChild() && x.isLeftChild()) {
                rotateRight(parent);
                //插入节点变为黑色
                x.color = BLACK;
                //祖父变为红色
                grandParent.color = RED;
                rotateLeft(grandParent);
            }
        }

    }
    //删除
    /*
     * 删除
     * 正常删、会用到李代桃僵技巧、遇到黑黑不平衡进行调整
     * */

    public void remove(int key) {
        Node deleted = find(key);
        if (deleted == null) {
            return;
        }
        doRemove(deleted);
    }

    //检测双黑节点删除
    /*
     *
     * 删除节点和剩下节点都是黑触发双黑,双黑意思是,少了一个黑
     * case 3:删除节点或剩余节点的兄弟为红此时两个侄子定为黑
     * case 4:删除节点或剩余节点的兄弟、和兄弟孩子都为黑
     * case 5:删除节点的兄弟为黑,至少一个红侄子
     *
     * */
    private void fixDoubleBlack(Node x) {
        //把case3处理为case4和case5
        if (x == root) {
            return;
        }
        Node parent = x.parent;
        Node sibling = x.sibling();
        if (sibling.color == RED) {
            //进入case3
            if (x.isLeftChild()) {
                //如果是做孩子就进行左旋
                rotateLeft(parent);
            } else {
                //如果是右孩子就进行右旋
                rotateRight(parent);
            }
            //父亲颜色变为红色(父亲变色前肯定为黑色)
            parent.color = RED;
            //兄弟变为黑色
            sibling.color = BLACK;
            //此时case3 已经被转换为 case4或者case5
            fixDoubleBlack(x);
            return;
        }
        //兄弟为黑
        //两个侄子都为黑
        if (sibling != null) {
            if (isBlack(sibling.left) && isBlack(sibling.right)) {
                /*
                 * case 4:被调整节点的兄弟为黑,两个侄于都为黑
                 * 将兄弟变红, 目的是将删除节点和兄弟那边的黑色高度同时减少1
                 * 如果父亲是红,则需将父亲变为黑,避免红红,此时路径黑节点数目不变
                 * 如果父亲是黑,说明这条路径则少了一个黑,再次让父节点触发双黑
                 * */
                //将兄弟变红, 目的是将删除节点和兄弟那边的黑色高度同时减少1
                sibling.color = RED;
                if (isRed(parent)) {
//                    如果父亲是红,则需将父亲变为黑,避免红红,此时路径黑节点数目不变
                    parent.color = BLACK;
                } else {
                    //如果父亲是黑,说明这条路径则少了一个黑,再次让父节点触发双黑
                    fixDoubleBlack(parent);
                }
            } else {
                //CASE5 至少有一个侄子不是黑色
                /*
                 *
                 * case 5:被调整节点的兄弟为黑
                 * 如果兄弟是左孩子,左侄子是红  LL 不平衡
                 * 如果兄弟是左孩子,右侄子是红  LR 不平衡
                 * 如果兄弟是右孩子,右侄于是红  RR 不平衡
                 * 如果兄弟是右孩子,左侄于是红  RL 不平衡
                 * */
                if(sibling.isLeftChild()&&isRed(sibling.left)){
                    // 如果兄弟是左孩子,左侄子是红  LL 不平衡
                    rotateRight(parent);
                    //兄弟的做孩子变黑
                    sibling.left.color=BLACK;
                    //兄弟变成父亲的颜色
                    sibling.color= parent.color;
                    //父亲变黑
                    parent.color=BLACK;
                }else if(sibling.isLeftChild()&&isRed(sibling.right)){
                    //如果兄弟是左孩子,右侄子是红  LR 不平衡
                    //变色必须在上 否则旋转后会空指针
                    //兄弟的右孩子变为父节点颜色
                    sibling.right.color= parent.color;
                    //父节点变黑
                    parent.color=BLACK;
                    rotateLeft(sibling);
                    rotateRight(parent);
                }
            }
        } else {
            fixDoubleBlack(parent);
        }


    }

    private void doRemove(Node deleted) {
        Node replaced = findReplaced(deleted);
        Node parent = deleted.parent;
        if (replaced == null) {
            //没有子节点
            /* case1:删的是根节点,没有子节点
             * 删完了,直接将 root=null
             * */
            if (deleted == root) {
                root = null;
            } else {
                /*
                 * Case2:删的是黑,剩下的是红剩下这个红节点变黑
                 * */
                if (isBlack(deleted)) {
                    //复杂处理,先调整平衡再删除
                    fixDoubleBlack(deleted);
                } else {
                    //红色不处理
                }

                //删除的不是根节点且没有孩子
                if (deleted.isLeftChild()) {
                    parent.left = null;
                } else {
                    parent.right = null;
                }
                deleted.parent = null;
            }
            return;
        } else if (replaced.left == null || replaced.right == null) {
            //有一个子节点
            /* case1:删的是根节点,有一个子节点
             * 用剩余节点替换了根节点的 key,Value,根节点孩子=null,颜色保持黑色 不变
             * */
            if (deleted == root) {
                root.key = replaced.key;
                root.value = replaced.value;
                root.left = root.right = null;
            } else {
                //删除的不是根节点但是有一个孩子
                if (deleted.isLeftChild()) {
                    parent.left = replaced;
                } else {
                    parent.right = replaced;
                }
                replaced.parent = parent;
                deleted.right = deleted.left = deleted.parent = null;
                if (isBlack(deleted) && isBlack(replaced)) {
                    //如果删除的是黑色剩下的也是黑色,需要复杂处理,先删除再平衡
                    fixDoubleBlack(replaced);
                } else {
                    /*
                     * Case2:删的是黑,剩下的是红剩下这个红节点变黑
                     * */
                    replaced.color = BLACK;
                }

            }
            return;
        } else {
            //两个子节点
            //交换删除节点和删除节点的后几点的key,value,这
            // 样被删除节点就只有一个子节点或没有子节点了
            int t = deleted.key;
            deleted.key = replaced.key;
            replaced.key = t;
            Object v = deleted.value;
            deleted.value = replaced.value;
            replaced.value = v;
            doRemove(replaced);
            return;
        }

    }

    private Node find(int key) {
        Node p = root;
        while (p != null) {
            if (key > p.key) {
                //key更大向右找
                p = p.right;
            } else if (key < p.key) {
                //向左找
                p = p.left;
            } else {
                return p;
            }
        }
        return null;
    }

    //查找删除后的剩余节点
    private Node findReplaced(Node deleted) {
        if (deleted.left == null & deleted.right == null) {
            //没有子节点
            return null;
        } else if (deleted.left == null) {
            return deleted.right;
        } else if (deleted.right == null) {
            return deleted.left;
        } else {
            Node s = deleted.right;
            while (s != null) {
                //右子树的最小值
                s = s.left;
            }
            return s;
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值