Java——红黑树

一、什么是红黑树?

        红黑树是一种平衡二叉搜索树,其节点由红、黑两种颜色组成。

二、红黑树的性质

     1、根节点为黑色
     2、节点只有红黑两种颜色
     3、红节点的两个子节点一定为黑色
     4、黑节点 高度 平衡 (黑色完美平衡)
     5、叶子结点为黑色
     6、黑节点一定有两个子节点

三、红黑树的遍历

        具体可自行去看关于二叉树的遍历,这里不细讲。

                1、中序遍历: 根左右 

                2、先序遍历

                3、后序遍历

四、红黑树的插入

/** 左旋
 *       p                          p
 *       |                          |
 *       x                          y
 *     /  \         --->          /  \
 *    lx   y                     x   ry
 *        / \                  /  \
 *       ly  ry               lx   ly
 *
 */y = root

        1、将y的左子节点的父节点更新为x,并将x的右子节点指向y的左子节点

        2、当x的父节点不为空,更新y的父节点为x的父节点,并将x的子树指向y

        3、将x的父节点更新为y,将y的左子节点更新为x

/** 右旋
 *       p                           p
 *       |                           |
 *       y                          x
 *     /  \         --->          /  \
 *    x    ry                    lx   y
 *   / \                            /  \
 *  lx  rx                         rx   ry
 *
 */

五、红黑树的删除

        暂时略。

        主要还是左旋、右旋和变色,以及替换。

        1、删除红色节点

                1.1、删除红色叶子结点

                2.2、删除红色parent节点

        2、删除黑色节点

                1.1、删除黑色叶子结点

                        1.1.1、有兄弟结点

                        1.1.2、无兄弟结点

                2.2、删除黑色parent结点

                        2.2.1、

                        2.2.2、

 

六、Java示例代码

package EverydaySpeach;

/**
 * 红黑树性质:
 *      1、根节点为黑色
 *      2、节点只有红黑两种颜色
 *      3、红节点的两个子节点一定为黑色
 *      4、黑节点 高度 平衡 (黑色完美平衡)
 *      5、叶子结点为黑色
 *      6、黑节点一定有两个子节点
 *
 */

public class RBTree<K extends Comparable<K>,V> {

    private static final Boolean RED = true;
    private static final Boolean BLACK = false;
    private RBNode root;

    public RBNode getRoot() {
        return root;
    }

    /*
     *   获取当前父节点 node
     */
    private RBNode parentOf(RBNode node){
        if (node != null){
            return node.parent;
        }
        return null;
    }

    /**
     * 设置结点颜色
     * @param node
     */
    // 设为红色
    private void setRed(RBNode node){
        if (node != null){
            node.color = RED;
        }
    }
    // 设为黑色
    private void setBlack(RBNode node){
        if (node != null){
            node.color = BLACK;
        }
    }

    // 判断结点颜色
    // 红色
    private boolean isRed(RBNode node){
        if (node != null){
            return node.color = RED;
        }
        return false;
    }
    // 黑色
    private boolean isBlack(RBNode node){
        if (node != null){
            return node.color = BLACK;
        }
        return false;
    }

    // 中序遍历
    private void inOrderPrint(){
        inOrderPrint(this.root);
    }
    private void inOrderPrint(RBNode node){
        if (node != null){
            inOrderPrint(node.left);
            System.out.println("key:" + node.key + ", value:" + node.value);
            inOrderPrint(node.right);
        }
    }

    /**
     *  公开的插入方法
     * @porom key
     * @porom value
     */
    public void insert(K key, V value){
        RBNode node = new RBNode<>();
        node.setKey(key);
        node.setValue(value);
        node.setColor(RED);
        insert(node);
    }

    private void insert(RBNode node){
        // 1、查找当前node父节点
        RBNode parent = null;
        RBNode x = this.root;
        // 这里有问题,x循环进不去
        while (x != null) {
            parent = x;
            // cmp > 0, node.key > x.key, 查找x的右子树
            // cmp == 0, node.key == x.key, 直接替换值
            // cmp < 0, node.key < x.key, 查找x的左子树
            int cmp = node.key.compareTo(x.key);

            if (cmp > 0) {
                x = x.right;
            } else if (cmp < 0) {
                x = x.left;
            } else {
                x.setValue(node.getValue());
                return;
            }

        }

        node.parent = parent;

        // 判断node与parent 的key谁大
        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()
        insertFixUp(node);


    }

    // 修复红黑树
    /**
     *
     *  1、红黑树为空,直接染色为黑色
     *  2、key已经存在
     *  3、插入节点的父节点为黑色
     *  注意:上面2、3两种情况都不用处理
     *  4、插入节点的父节点为红色
     *      4.1、叔叔节点存在,且为红色
     *      4.2、叔叔节点不存在,或为黑色,父节点为爷爷节点的左子树
     *          4.2.1、插入节点为父节点的左子节点     LL
     *          4.2.2、插入节点为父节点的右子节点     LR
     *      4.3、叔叔节点不存在,或为黑色,父节点为爷爷节点的右子树
     *          4.2.1、插入节点为父节点的右子节点     RR
     *          4.2.2、插入节点为父节点的左子节点     RL
     */
    private void insertFixUp(RBNode node){
        this.root.setColor(BLACK);

        RBNode parent = parentOf(node);
        RBNode parentP = parentOf(parent);
        // 父节点为红色
        if (parent != null && isRed(parent)){
            // 爷爷的左子树
            RBNode uncle = null;    // 叔叔节点

            if (parent == parentP.left){

                uncle = parentP.right;
//====================================================================================
                // 4.1
                if (uncle != null && isRed(uncle)){
                    setBlack(parent);
                    setBlack(uncle);
                    setRed(parentP);
                    insertFixUp(parentP);
                    return;
                }
//=====================================================================================
                // 4.2
                if (uncle == null || isBlack(uncle)){
                    // 4.2.1
                    if (node == parentP.left){
                        setBlack(parent);
                        setRed(parentP);
                        rightRotate(parentP);
                        return;
                    }
                    // 4.2.2
                    if (node == parentP.right){
                        leftRotate(parent);
                        insertFixUp(parent);
                        return;
                    }
                }


            } else {
                // 爷爷的右子树
                uncle = parentP.left;

                // 4.1
                if (uncle != null && isRed(uncle)){
                    setBlack(parent);
                    setBlack(uncle);
                    setRed(parentP);
                    insertFixUp(parentP);
                    return;
                }
                // 4.3
                if (uncle == null || isBlack(uncle)){
                    // 4.3.1
                    if (node == parent.right){
                        setBlack(parent);
                        setRed(parentP);
                        leftRotate(parentP);
                        return;
                    }
                    // 4.3.2
                    if (node == parent.left){
                        rightRotate(parent);
                        insertFixUp(parent);
                        return;
                    }
                }

            }
        }
    }
    /** 左旋
     *       p                           p
     *       |                           |
     *       x                          y
     *     /  \         --->          /  \
     *    lx   y                     x   ry
     *        / \                  /  \
     *       ly  ry               lx   ly
     *
     */
    private void leftRotate(RBNode x){
        RBNode y = x.right;
        // 1、将x的右节点指向y的左子节点,将y的左子节点的父节点更新为x
        x.right = y.left;
        if (y.left != null){
            y.left.parent = x;
        }

        // 2、当x的父节点不为空时,更新y的父节点为x的父节点,并将x的父节点 指定 子树(当前x的子树位置) 指定为y
        if (x.parent != null){
            y.parent = x.parent;
            if (x == x.parent.left){
                x.parent.left = y;
            } else {
                x.parent.right = y;
            }
        } else {
            // x为根节点,则将y更新为根节点
            this.root = y;
            this.root.parent = null;
        }
        // 3、将x的父节点更新为y,将y的左子节点更新为x
        x.parent = y;
        y.left = x;
    }

    /** 右旋
     *       p                           p
     *       |                           |
     *       y                          x
     *     /  \         --->          /  \
     *    x    ry                    lx   y
     *   / \                            /  \
     *  lx  rx                         rx   ry
     *
     */
    private void rightRotate(RBNode y){
        RBNode x = y.left;

        y.left = x.right;
        // 1、
        if (x.right != null){
            x.right.parent = y;
        }

        // 2、
        if (y.parent != null){

            x.parent = y.parent;

            if (y == y.parent.left){
                y.parent.left = x;
            } else {
                y.parent.right = x;
            }
        } else {
            this.root = x;
            this.root.parent = null;
        }
        y.parent = x;
        x.right = y;
    }

    // 内部类
    static class RBNode<K extends Comparable<K>, V>{

        private RBNode parent;
        private RBNode left;
        private RBNode right;
        private boolean color;
        private K key;
        private V value;

        public RBNode() {
        }

        public RBNode(RBNode parent, RBNode left, RBNode right, boolean color, K key, V value) {
            this.parent = parent;
            this.left = left;
            this.right = right;
            this.color = color;
            this.key = key;
            this.value = value;
        }


        public RBNode getParent() {
            return parent;
        }

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

        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 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;
        }

    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值