手写红黑树

概念:

二叉树:每个节点最多只能有2个子节点。

                叶子节点:没有子节点的节点。

二叉搜索树:左节点小于父节点,父节点小于有节点(便于查找)

        中序遍历:左节点--> 中(根)节点 --> 右节点(结果是从小到大的顺序)

        缺点:极端情况下会变成线性链表,效率底下。

平衡树(AVL树):避免二叉搜索树的致命缺点。

        具有二叉搜索树的全部特点

        每个节点的左子树和右子树的高度相差最多为1

        缺点:会频繁的左右旋。

红黑树:并不是一个完美的平衡二叉搜索树

性质 每个节点要么是黑色要么是红色

        根节点是黑色

        每个叶子节点是黑色

        每个红色节点的两个子节点一定都是黑色

        任意一个节点到每个叶子节点的路径都包含相同数量的黑色节点。

                如果一个节点存在黑子节点,那么该节点肯定有两个子节点

变色:节点的颜色由红变黑,由黑变红。

左旋:以某个节点作为支点(旋转节点),其右子节点变为旋转节点的父节点,右子节点的左子节点变为旋转节点的右子节点,左子节点保持不变。

右旋:以某个节点作为支点(旋转节点),其左子结点变为旋转节点的父节点,左子节点的右子节点变为旋转节点的左子节点,右子节点保持不变。

插入

新插入的节点是红色(根节点是黑节点)。插入相同的值执行覆盖更新操作。

插入节点的父节点是黑色,直接插,不会影响平衡。

插入节点的父节点是红色,且叔叔节点是红色 ---》

父节点和叔叔节点变为黑色,父父节点变为红色,以爷爷为当前节点,继续操作,直到完成平衡

插入节点的的父节点是红色且叔叔节点不存在,或者为黑色,并且插入节点的父节点是父父节点的左子节点,且插入的节点是左子节点(LL双红)---》

将父节点变为黑色,父父节点变为红色并且对父父节点右旋。

插入节点的父节点是红色且叔叔节点不存在,或者为黑色,并且插入节点的父节点是父父节点的左子节点,且插入的节点是右子节点(LR双红)---》

父节点左旋得到LL双红,处理LL双红。

插入节点的父节点是红色且叔叔节点不存在,或者为黑色,并且插入节点的父节点是父父节点的右子节点,且插入的节点是右子节点(RR双红)---》

父节点变黑,父父节点变红,左旋父父节点

插入节点的父节点是红色且叔叔节点不存在,或者为黑色,并且插入节点的父节点是父父节点的右子节点,且插入的节点是左子节点(RL双红)---》

父节点右旋,处理RR双红。

手写红黑树:删除、打印方法后续补充

package RBTree;

public class RBTree {

    // 根节点
    private RBNode root;

    static class RBNode<V extends Comparable> {
        private V value;
        private RBNode<V> parent;
        private RBNode<V> left;
        private RBNode<V> right;
        private boolean isRed;

        public RBNode() {
        }

        public V getValue() {
            return value;
        }

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

        public RBNode<V> getParent() {
            return parent;
        }

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

        public RBNode<V> getLeft() {
            return left;
        }

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

        public RBNode<V> getRight() {
            return right;
        }

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

        public boolean isRed() {
            return isRed;
        }

        public void setRed(boolean red) {
            isRed = red;
        }
    }

    /**
     * 获取当前节点的父节点
     * @param node
     * @return
     */
    public RBNode getParent(RBNode node) {
        if(node != null){
            return node.getParent();
        }
        return null;
    }

    /**
     * 获取当前节点的左子节点
     * @param node
     * @return
     */
    public RBNode getChildLeft(RBNode node){
        if(node != null){
            return node.getLeft();
        }
        return null;
    }

    /**
     * 获取节点的右子节点
     * @param node
     * @return
     */
    public RBNode getChildRight(RBNode node){
        if(node != null){
            return node.getRight();
        }
        return null;
    }

    /**
     * 获取当前节点颜色
     * @param node
     * @return true:红色 false:黑色
     */
    public boolean getColor(RBNode node){
        if (node != null){
            return node.isRed();
        }
        throw new RuntimeException("node is null");
    }

    /**
     * 设置节点颜色
     * @param node
     * @param isRed true:红色 false:黑色
     */
    public void setColor(RBNode node, boolean isRed){
        if (node != null){
            node.setRed(isRed);
        }
    }

    /**
     * 中序遍历
     * @param node
     */
    public void printTree(RBNode node){
        if (node != null){
            printTree(node.getLeft());
            System.out.println(node.getValue());
            printTree(node.getRight());
        }
    }

    // 左旋:该点右子节点变为父节点,该点右子节点的左子节点变为该节点右子节点
    public void leftRotate(RBNode node){
        if (node != null){
            Comparable value = node.getValue();
            RBNode parent = node.getParent();
            RBNode right = node.getRight();
            RBNode rightChildLeft = right.getLeft();
            Comparable parentLeftChildValue = parent.getLeft().getValue();
            Comparable parentRightChildValue = parent.getRight().getValue();

            if(value.compareTo(parentLeftChildValue) == 0){
                parent.setLeft(right);
            }
            if(value.compareTo(parentRightChildValue) == 0){
                parent.setRight(right);
            }
            right.setParent(parent);

            node.setRight(rightChildLeft);
            rightChildLeft.setParent(node);

            right.setLeft(node);
            node.setParent(right);
        }
    }

    // 右旋:该节点左子节点变为父节点,该节点左子节点的右子节点变为该节点左子节点
    public void rightRotate(RBNode node){
        if (node != null){
            Comparable value = node.getValue();
            RBNode parent = node.getParent();
            RBNode left = node.getLeft();
            RBNode leftChildRight = left.getRight();
            Comparable parentLeftChildValue = parent.getLeft().getValue();
            Comparable parentRightChildValue = parent.getRight().getValue();

            if(value.compareTo(parentLeftChildValue) == 0){
                parent.setLeft(left);
            }
            if(value.compareTo(parentRightChildValue) == 0){
                parent.setRight(left);
            }
            left.setParent(parent);

            left.setParent(node);
            node.setParent(left);

            node.setLeft(leftChildRight);
            leftChildRight.setParent(node);
        }
    }

    // 插入:找父节点
    public void insert(RBNode node){
        RBNode parent = null;
        RBNode tempParent = root;

        while (tempParent != null){
            parent = tempParent;
            int cmp = node.getValue().compareTo(parent.getValue());
            if(cmp > 0){
                // node > parent
                tempParent = parent.getRight();
            }else if(cmp > 0){
                // node < parent
                tempParent = parent.getLeft();
            }else{
                tempParent.setValue(node.getValue());
                return;
            }
        }
        if(root == null){
            node.parent = null;
            root = node;
            return;
        }else {
            node.setParent(parent);
        }

        // 判断作为左子节点还是右子节点
        int cmp = node.getValue().compareTo(parent.getValue());
        if(cmp > 0){
            parent.setRight(node);
        }else if(cmp < 0){
            parent.setLeft(node);
        }

        // 修复红黑树的平衡
        fixBalance(node);
    }

    /**
     * 插入后修复红黑树的平衡
     * 情景1: 红黑树为空树,将跟节点染色为黑色
     *  XXX情景2: 插入节点的key已经存在,替换已在插入完成,此处不需要处理
     *  XXX情景3: 插入节点的父节点为黑色,不影响红黑树的特性,所以红黑树依然平衡,所以不需要处理。
     * 情景4需要咱们去处理
     * |---情景4:     插入节点的父节点为红色
     * |---情景4.1:   叔叔节点存在,并且为红色(父-叔 双红)
     * |---情景4.2:   叔叔节点不存在,或者为黑色,父节点为爷爷节点的左子树
     * |---情景4.2.1: 插入节点为其父节点的左子节点(LL情况)
     * |---情景4.2.2: 插入节点为其父节点的右子节点(LR情况)
     * |---情景4.3:   叔叔节点不存在,或者为黑色,父节点为爷爷节点的右子树
     * |---情景4.3.1: 插入节点为其父节点的右子节点( RR情况)
     * |---情景4.3.2: 插入节点为其父节点的左子节点(RL情况)
     */
    public void fixBalance(RBNode node){

        if(node.parent == null){
            // 情景1
            node.setRed(false);
        }else if (node.parent.isRed == false){
            // 情景3
        }else {
            // 情景4
            RBNode parent = node.getParent();
            RBNode grandParent = parent.getParent();
            RBNode uncle;
            if (parent == grandParent.left){
                uncle = grandParent.getRight();
                if(uncle != null && uncle.isRed()){
                    // 情景4.1
                    setColor(parent, false);
                    setColor(uncle, false);
                    setColor(grandParent, true);
                    fixBalance(grandParent);
                    return;
                }else {
                    if(node == parent.left){
                        //  情景4.2.1
                        setColor(parent, false);
                        setColor(grandParent, true);
                        rightRotate(grandParent);
                        return;
                    }else if (node == parent.right){
                        // 情景4.2.2
                        leftRotate(parent);
                        fixBalance(parent);
                        return;
                    }
                }
            }else if (parent == grandParent.right){
                uncle = grandParent.getLeft();
                if(uncle != null && uncle.isRed()){
                    // 情景4.1
                    setColor(parent, false);
                    setColor(uncle, false);
                    setColor(grandParent, true);
                    fixBalance(grandParent);
                    return;
                }else {
                    if(node == parent.right){
                        //  情景4.3.1
                        setColor(parent, false);
                        setColor(grandParent, true);
                        leftRotate(grandParent);
                        return;
                    }
                    if (node == parent.left){
                        // 情景4.3.2
                        rightRotate(parent);
                        fixBalance(parent);
                        return;
                    }
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值