红黑树的推导过程,从BST二叉查找树->2-3-4树->红黑树

BST二叉查找树

在这里插入图片描述
查找: 查找的值比根节点大,搜索右子树,比根节点小,搜索左子树
插入: 要插入节点,必须先找到插入节点位置。依然是从根节点开始比较,小于根节点的话就和左子树
比较,反之与右子树比较,直到左子树为空或者右子树为空,则插入到相应为空的位置。
遍历(红黑树通用): 根据一定顺序来访问整个树,常见的有前序遍历,中序遍历(用的较多),后序
遍历
前序遍历:左子树-》根节点-》右子树 123 4 567
中序遍历:根节点-》左子树-》右子树 4 213 657
后续遍历:左子树-》右子树-》根节点 132 576 4
**查找最小值(红黑树通用):**沿着根节点的左子树一路查找,直到最后一个不为空的节点,该节点就是
当前这个树的最小节点
查找最大值(红黑树通用): 沿着根节点的右子树一路查找,直到最后一个不为空的节点,该节点就是
当前这个树的最大节点
查找前驱节点(红黑树通用)(红黑树重点): 小于当前节点的最大值
查找后继节点(红黑树通用)(红黑树重点): 大于当前节点的最小值

2-3-4树

2-3-4树是四阶的 B树(Balance Tree),他属于一种多路查找树,它的结构有以下限制:

  • 所有叶子节点都拥有相同的深度。
  • 节点只能是 2-节点、3-节点、4-节点之一。
    2-节点:包含 1 个元素的节点,有 2 个子节点;
    3-节点:包含 2 个元素的节点,有 3 个子节点;
    4-节点:包含 3 个元素的节点,有 4 个子节点;
    所有节点必须至少包含1个元素
  • 元素始终保持排序顺序,整体上保持二叉查找树的性质,即父结点大于左子结点,小于右子结点;
    而且结点有多个元素时,每个元素必须大于它左边的和它的左子树中元素。
    在这里插入图片描述

红色节点的意思就是说,红色是跟父节点(黑色),在2-3-4树的表示下,其实是同一个节点
如图上的值为1的节点和值为2的节点在2-3-4树中就是一个节点有两个值,其他同理
所以为什么红黑树的从任何一个节点到叶子节点,经过的黑色节点是一样的?或者说为什么不能有两个连续的红色节点?
因为黑色才算是真正的节点,红色只是父节点的附庸,红色节点不能附庸在其他红色的节点上面!

红黑树 性质

  • 红黑树的每个节点或是红色或是黑色
  • 根节点是黑色的,红色节点向左倾斜
  • 每个叶子节点都是黑色的
  • 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节
    点。)
  • 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点(黑色平衡)。

TreeMap

插入&插入后调整的3种情况

插入是比较简单的,比较新增的节点与root的值,比root大往右,比root小往左,找到叶子节点,插入;
红黑树上的新增和删除节点一定是2-3-4树上的叶子节点

2-3-4树的4节点插入和红黑树对比

在这里插入图片描述

2-3-4树的3节点插入和红黑树对比

左3情况

在这里插入图片描述

右3情况

在这里插入图片描述

特殊情况(左右)

在这里插入图片描述

2-3-4树的2节点插入和红黑树对比

在这里插入图片描述

看下图,x就是插入的节点,红色箭头的指向是调整之后的局部颜色!
这个图举例了x的父亲节点是爷爷的左孩子的情况下!
x是新插入的节点!
详见fixAfterPut方法
如果x的父亲节点是爷爷的右孩子,情况相反!
在这里插入图片描述

左旋

在这里插入图片描述

什么情况下需要左旋?
当node的右节点是红色并且左节点是黑色(见上图红黑树旋转的情况L)

private void leftRotate(RBNode p) {
        if (p != null) {
            RBNode r = p.right;
            p.right = r.left;
            if (r.left != null) {
                r.left.parent = p;
            }
            r.parent = p.parent;
            if (p.parent == null) {
                root = r;
            } else if (p.parent.left == p) {
                p.parent.left = r;
            } else {
                p.parent.right = r;
            }
            r.left = p;
            p.parent = r;
        }
    }

右旋

什么情况下需要右旋?
当node的左节点是红色并且左节点的左节点是红色(见上图红黑树旋转的情况R)
在这里插入图片描述

    private void rightRotate(RBNode p) {
        if (p != null) {
            RBNode l = p.left;
            p.left = l.right;
            if (l.right != null) {
                l.right.parent = p;
            }
            l.parent = p.parent;
            if (p.parent == null) {
                root = l;
            } else if (p.parent.right == p) {
                p.parent.right = l;
            } else {
                p.parent.left = l;
            }
            l.right = p;
            p.parent = l;
        }
    }

插入&插入后调整

public void put(K key, V value) {
        RBNode t = this.root;
        //如果是根节点
        if (t == null) {
            root = new RBNode<>(key, value == null ? key : value, null);
            return;
        }
        int cmp;
        //寻找插入位置
        //定义一个双亲指针
        RBNode parent;
        if (key == null) {
            throw new NullPointerException();
        }
        //沿着跟节点寻找插入位置
        do {
            parent = t;
            cmp = key.compareTo((K) t.key);
            if (cmp < 0) {
                t = t.left;
            } else if (cmp > 0) {
                t = t.right;
            } else {
                t.setValue(value == null ? key : value);
                return;
            }
        } while (t != null);

        RBNode<K, Object> e = new RBNode<>(key, value == null ? key : value, parent);
        //如果比较最终落在左子树,则直接将父节点左指针指向e
        if (cmp < 0) {
            parent.left = e;
        }
        //如果比较最终落在右子树,则直接将父节点右指针指向e
        else {
            parent.right = e;
        }
        //调整
        fixAfterPut(e);
   }
private void fixAfterPut(RBNode x) {
        x.color = RED;
        //本质上就是父节点是黑色就不需要调整,对应情况就是2,3
        while (x != null && x != root && x.parent.color == RED) {
            //1、x的父节点是爷爷的左孩子(左3)
            if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
                //叔叔节点
                RBNode y = rightOf(parentOf(parentOf(x)));
                //第3种情况
                if (colorOf(y) == RED) {
                    setColor(parentOf(x), BLACK);
                    setColor(y, BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    //爷爷节点递归
                    x=parentOf(parentOf(x));
                }
                //第2种情况
                else {
                    if (x == rightOf(parentOf(x))) {
                        x = parentOf(x);
                        leftRotate(x);
                    }
                    //父亲变黑
                    setColor(parentOf(x), BLACK);
                    //爷爷变红
                    setColor(parentOf(parentOf(x)), RED);
                    //根据爷爷节点右旋转
                    rightRotate(parentOf(parentOf(x)));
                }
            }
            //2、跟第一种情况相反操作
            else {
                //右3
                //叔叔节点
                RBNode y = leftOf(parentOf(parentOf(x)));
                //第3种情况
                if (colorOf(y) == RED) {
                    setColor(parentOf(x), BLACK);
                    setColor(y, BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    //爷爷节点递归
                    x=parentOf(parentOf(x));
                }
                //第2种情况
                else {
                    if (x == leftOf(parentOf(x))) {
                        x = parentOf(x);
                        rightRotate(x);
                    }
                    //父亲变黑
                    setColor(parentOf(x), BLACK);
                    //爷爷变红
                    setColor(parentOf(parentOf(x)), RED);
                    //根据爷爷节点右旋转
                    leftRotate(parentOf(parentOf(x)));
                }
            }
        }
        root.color=BLACK;
    }

删除: 本质上是找前驱或者后继节点来替代

  • 叶子节点直接删除(没有前驱或后继节点)
  • 只有一个子节点的用子节点替代(本质上就是找的前驱节点或者是后继节点,左节点就是前驱节
    点,右节点就是后继节点)
  • 有两个子节点的,需要找到替代节点(替代节点就是前驱节点或者后继节点)
    删除操作和红黑树一样,只不过红黑树多了着色和旋转过程
    红黑树上的删除节点一定是2-3-4树上的叶子节点

红黑树与2-3-4树的等价关系

首先,红黑树删除的节点一定是对应2-3-4树的叶子节点,根据前驱或者后继算法查找出来的节点一定是2-3-4树的叶子节点
在这里插入图片描述

前驱结点&后继节点

在这里插入图片描述
在这里插入图片描述

前驱节点&后继节点(代码)

/**
     * 找到指定节点的前驱节点,即找小于node节点的最大值
     * @param node
     */
    private Node predecessor(Node node){
        if(node==null){
            return null;
        }
        else if(node.left!=null){
            Node p=node.left;
            while(p.right!=null){
                p=p.right;
            }
            return p;
        }else{
            Node p = node.parent;
            Node ch=node;
            while(p!=null&&ch==p.left){
                ch=p;
                p=p.parent;
            }
            return p;
        }
    }
    /**
     * 找后继节点,即大于节点的最小值
     * @param node
     * @return
     */
    private Node successor(Node node){
        if(node==null){
            return null;
        }
        else if(node.right!=null){
            Node p=node.right;
            while(p.left!=null){
                p=p.left;
            }
            return p;
        }else{
            Node p = node.parent;
            Node ch=node;
            while(p!=null&&ch==p.right){
                ch=p;
                p=p.parent;
            }
            return p;
        }
    }

删除&调整

情况一

在这里插入图片描述

情况二&情况三

在这里插入图片描述

删除&调整(代码)

public V remove(K key){
      RBNode node=getNode(key);
      if(node==null){
          return null;
      }
      V oldValue = (V) node.value;
      deleteNode(node);
      return oldValue;
    }
    /**
     * 删除操作:
     * 1、删除叶子节点,直接删除
     * 2、删除的节点有一个子节点,那么用子节点来替代
     * 3、如果删除的节点有2个子节点,此时需要找到前驱节点或者后继节点来替代
     *
     * @param node
     */
    private void deleteNode(RBNode node){
        //3、node节点有2个孩子
        if(node.left!=null&&node.right!=null){
            /**
             *  这里要注意,如果使用下面这个网站演示的话,此网站用的是前驱节点替代
             *  下面代码里我使用的是后继节点替代,删除节点后显示可能会和该网站不一致,
             *  但是这两种方法红黑树删除都是合法的
             *  (可以自行把前驱节点替代方案屏蔽放开,后继节点替代方案注释掉测试下)
             *
             *  https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
             */

            //后继节点替代
            RBNode rep = successor(node);
            //前驱节点替代
//            RBNode rep= predecessor(node);
            node.key = rep.key;
            node.value=rep.value;
            node=rep;
        }

        RBNode replacement=node.left!=null?node.left:node.right;
        //2、替代节点不为空
        if(replacement!=null){
            //替代者的父指针指向的原来node的父亲
            replacement.parent=node.parent;
            //node是根节点
            if(node.parent==null){
                root=replacement;
            }
            //node是左孩子,所以替代者依然是左孩子
            else if(node==node.parent.left){
                node.parent.left=replacement;
            }
            //node是右孩子,所以替代者依然是右孩子
            else{
                node.parent.right=replacement;
            }
            //将node的左右孩子指针和父指针都指向null(此时node处于游离状态,等待垃圾回收)
            node.left=node.right=node.parent=null;

            //替换完之后需要调整平衡
            if(node.color==BLACK){
                //需要调整,这种情况一定是红色(替代节点一定是红色,此时只要变色)
                fixAfterRemove(replacement);
            }
        }
        //删除节点就是根节点 
        else if(node.parent==null){
            root=null;
        }
        //1、node节点是叶子节点,replacement为null
        else{
            //先调整
            if(node.color==BLACK) {
                fixAfterRemove(node);
            }
            //再删除 
            if(node.parent!=null){
                if(node==node.parent.left){
                    node.parent.left=null;
                }
                else if(node==node.parent.right){
                    node.parent.right=null;
                }
                node.parent=null;
            }
        }
    }
    private void fixAfterRemove(RBNode x){
        while(x!=root&&colorOf(x)==BLACK){
            //x是左孩子的情况
            if(x==leftOf(parentOf(x))) {
                //兄弟节点
                RBNode rnode = rightOf(parentOf(x));

                //判断此时兄弟节点是否是真正的兄弟节点
                if(colorOf(rnode)==RED){
                    setColor(rnode,BLACK);
                    setColor(parentOf(x),RED);
                    leftRotate(parentOf(x));
                    //找到真正的兄弟节点
                    rnode=rightOf(parentOf(x));
                }
                //情况三,找兄弟借,兄弟没得借
                 if(colorOf(leftOf(rnode))==BLACK&&colorOf(rightOf(rnode))==BLACK){
                     //情况复杂,暂时不写
                     setColor(rnode,RED);
                     x=parentOf(x);
                 }
                //情况二,找兄弟借,兄弟有的借
                else{
                    //分2种小情况:兄弟节点本来是3节点或者是4节点的情况
                     if(colorOf(rightOf(rnode))==BLACK){//这里已经是判断出来,一定有一个节点,那么右孩子为空,左孩子一定不为空
                        setColor(leftOf(rnode),BLACK);
                        setColor(rnode,RED);
                        rightRotate(rnode);
                        rnode=rightOf(parentOf(x));
                     }
                     setColor(rnode,colorOf(parentOf(x)));
                     setColor(parentOf(x),BLACK);
                     setColor(rightOf(rnode),BLACK);
                     leftRotate(parentOf(x));
                     x=root;
                 }
            }
            //x是右孩子的情况
            else{
                //兄弟节点
                RBNode rnode = leftOf(parentOf(x));
                //判断此时兄弟节点是否是真正的兄弟节点
                if(colorOf(rnode)==RED){
                    setColor(rnode,BLACK);
                    setColor(parentOf(x),RED);
                    rightRotate(parentOf(x));
                    //找到真正的兄弟节点
                    rnode=leftOf(parentOf(x));
                }
                //情况三,找兄弟借,兄弟没得借
                if(colorOf(rightOf(rnode))==BLACK&&colorOf(leftOf(rnode))==BLACK){
                    //情况复杂,暂时不写
                    setColor(rnode,RED);
                    x=parentOf(x);
                }
                //情况二,找兄弟借,兄弟有的借
                else{
                    //分2种小情况:兄弟节点本来是3节点或者是4节点的情况
                    if(colorOf(leftOf(rnode))==BLACK){
                        setColor(rightOf(rnode),BLACK);
                        setColor(rnode,RED);
                        leftRotate(rnode);
                        rnode=leftOf(parentOf(x));
                    }
                    setColor(rnode,colorOf(parentOf(x)));
                    setColor(parentOf(x),BLACK);
                    setColor(leftOf(rnode),BLACK);
                    rightRotate(parentOf(x));
                    x=root;
                }
            }
        }
        //情况一、替代节点是红色,则直接染红,补偿删除的黑色节点,这样红黑树依然保持平衡
        setColor(x,BLACK);
    }

完整代码

public class RBTree<K extends Comparable<K>, V> {
    private static final boolean RED = false;
    private static final boolean BLACK = true;

    private RBNode root;

    public RBNode getRoot() {
        return root;
    }

    public void setRoot(RBNode root) {
        this.root = root;
    }

    private void leftRotate(RBNode p) {
        if (p != null) {
            RBNode r = p.right;
            p.right = r.left;
            if (r.left != null) {
                r.left.parent = p;
            }
            r.parent = p.parent;
            if (p.parent == null) {
                root = r;
            } else if (p.parent.left == p) {
                p.parent.left = r;
            } else {
                p.parent.right = r;
            }
            r.left = p;
            p.parent = r;
        }
    }

    /**
     * 右旋
     *    pf                pf
     *     \                 \
     *      p             (l)pl
     *     / \      =>      /  \
     *(l)pl  pr            ll   p
     *   / \                   / \
     *  ll lr                 lr  pr
     *
     * @param p
     */
    private void rightRotate(RBNode p) {
        if (p != null) {
            RBNode l = p.left;
            p.left = l.right;
            if (l.right != null) {
                l.right.parent = p;
            }
            l.parent = p.parent;
            if (p.parent == null) {
                root = l;
            } else if (p.parent.right == p) {
                p.parent.right = l;
            } else {
                p.parent.left = l;
            }
            l.right = p;
            p.parent = l;
        }
    }

    /**
     * 找到指定节点的前驱节点,即找小于node节点的最大值
     * @param node
     */
    private RBNode predecessor(RBNode node){
        if(node==null){
            return null;
        }
        else if(node.left!=null){
            RBNode p=node.left;
            while(p.right!=null){
                p=p.right;
            }
            return p;
        }else{
            RBNode p = node.parent;
            RBNode ch=node;
            while(p!=null&&ch==p.left){
                ch=p;
                p=p.parent;
            }
            return p;
        }
    }

    /**
     * 找后继节点,即大于节点的最小值
     * @param node
     * @return
     */
    private RBNode successor(RBNode node){
        if(node==null){
            return null;
        }
        else if(node.right!=null){
            RBNode p=node.right;
            while(p.left!=null){
                p=p.left;
            }
            return p;
        }else{
            RBNode p = node.parent;
            RBNode ch=node;
            while(p!=null&&ch==p.right){
                ch=p;
                p=p.parent;
            }
            return p;
        }
    }

    private boolean colorOf(RBNode node) {
        return node == null ? BLACK : node.color;
    }

    private RBNode parentOf(RBNode node) {
        return node != null ? node.parent : null;
    }

    private RBNode leftOf(RBNode node) {
        return node != null ? node.left : null;
    }

    private RBNode rightOf(RBNode node) {
        return node != null ? node.right : null;
    }

    private void setColor(RBNode node, boolean color){
        if(node!=null){
            node.color=color;
        }
    }

    public void put(K key, V value) {
        RBNode t = this.root;
        //如果是根节点
        if (t == null) {
            root = new RBNode<>(key, value == null ? key : value, null);
            return;
        }
        int cmp;
        //寻找插入位置
        //定义一个双亲指针
        RBNode parent;
        if (key == null) {
            throw new NullPointerException();
        }
        //沿着跟节点寻找插入位置
        do {
            parent = t;
            cmp = key.compareTo((K) t.key);
            if (cmp < 0) {
                t = t.left;
            } else if (cmp > 0) {
                t = t.right;
            } else {
                t.setValue(value == null ? key : value);
                return;
            }
        } while (t != null);

        RBNode<K, Object> e = new RBNode<>(key, value == null ? key : value, parent);
        //如果比较最终落在左子树,则直接将父节点左指针指向e
        if (cmp < 0) {
            parent.left = e;
        }
        //如果比较最终落在右子树,则直接将父节点右指针指向e
        else {
            parent.right = e;
        }
        //调整
        fixAfterPut(e);
    }

    private void fixAfterPut(RBNode x) {
        x.color = RED;
        //本质上就是父节点是黑色就不需要调整,对应情况就是2,3
        while (x != null && x != root && x.parent.color == RED) {
            //1、x的父节点是爷爷的左孩子(左3)
            if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
                //叔叔节点
                RBNode y = rightOf(parentOf(parentOf(x)));
                //第3种情况
                if (colorOf(y) == RED) {
                    setColor(parentOf(x), BLACK);
                    setColor(y, BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    //爷爷节点递归
                    x=parentOf(parentOf(x));
                }
                //第2种情况
                else {
                    if (x == rightOf(parentOf(x))) {
                        x = parentOf(x);
                        leftRotate(x);
                    }
                    //父亲变黑
                    setColor(parentOf(x), BLACK);
                    //爷爷变红
                    setColor(parentOf(parentOf(x)), RED);
                    //根据爷爷节点右旋转
                    rightRotate(parentOf(parentOf(x)));
                }
            }
            //2、跟第一种情况相反操作
            else {
                //右3
                //叔叔节点
                RBNode y = leftOf(parentOf(parentOf(x)));
                //第3种情况
                if (colorOf(y) == RED) {
                    setColor(parentOf(x), BLACK);
                    setColor(y, BLACK);
                    setColor(parentOf(parentOf(x)), RED);
                    //爷爷节点递归
                    x=parentOf(parentOf(x));
                }
                //第2种情况
                else {
                    if (x == leftOf(parentOf(x))) {
                        x = parentOf(x);
                        rightRotate(x);
                    }
                    //父亲变黑
                    setColor(parentOf(x), BLACK);
                    //爷爷变红
                    setColor(parentOf(parentOf(x)), RED);
                    //根据爷爷节点右旋转
                    leftRotate(parentOf(parentOf(x)));
                }
            }
        }
        root.color=BLACK;
    }

    public V remove(K key){
      RBNode node=getNode(key);
      if(node==null){
          return null;
      }
      V oldValue = (V) node.value;
      deleteNode(node);
      return oldValue;
    }

    /**
     * 删除操作:
     * 1、删除叶子节点,直接删除
     * 2、删除的节点有一个子节点,那么用子节点来替代
     * 3、如果删除的节点有2个子节点,此时需要找到前驱节点或者后继节点来替代
     *
     * @param node
     */
    private void deleteNode(RBNode node){
        //3、node节点有2个孩子
        if(node.left!=null&&node.right!=null){
            //后继节点替代
            RBNode rep = successor(node);
            //前驱节点替代
//            RBNode rep= predecessor(node);
            node.key = rep.key;
            node.value=rep.value;
            node=rep;
        }

        RBNode replacement=node.left!=null?node.left:node.right;
        //2、替代节点不为空
        if(replacement!=null){
            //替代者的父指针指向的原来node的父亲
            replacement.parent=node.parent;
            //node是根节点
            if(node.parent==null){
                root=replacement;
            }
            //node是左孩子,所以替代者依然是左孩子
            else if(node==node.parent.left){
                node.parent.left=replacement;
            }
            //node是右孩子,所以替代者依然是右孩子
            else{
                node.parent.right=replacement;
            }
            //将node的左右孩子指针和父指针都指向null(此时node处于游离状态,等待垃圾回收)
            node.left=node.right=node.parent=null;

            //替换完之后需要调整平衡
            if(node.color==BLACK){
                //需要调整,这种情况一定是红色(替代节点一定是红色,此时只要变色)
                fixAfterRemove(replacement);
            }
        }
        //删除节点就是根节点  这里有点问题?
        else if(node.parent==null){
            root=null;
        }
        //1、node节点是叶子节点,replacement为null
        else{
            //先调整
            if(node.color==BLACK) {
                fixAfterRemove(node);
            }
            //再删除
            if(node.parent!=null){
                if(node==node.parent.left){
                    node.parent.left=null;
                }
                else if(node==node.parent.right){
                    node.parent.right=null;
                }
                node.parent=null;
            }
        }
    }

    /**
     * 删除后调整
     * @param x
     */
    private void fixAfterRemove(RBNode x){
        while(x!=root&&colorOf(x)==BLACK){
            //x是左孩子的情况
            if(x==leftOf(parentOf(x))) {
                //兄弟节点
                RBNode rnode = rightOf(parentOf(x));

                //判断此时兄弟节点是否是真正的兄弟节点
                if(colorOf(rnode)==RED){
                    setColor(rnode,BLACK);
                    setColor(parentOf(x),RED);
                    leftRotate(parentOf(x));
                    //找到真正的兄弟节点
                    rnode=rightOf(parentOf(x));
                }
                //情况三,找兄弟借,兄弟没得借
                 if(colorOf(leftOf(rnode))==BLACK&&colorOf(rightOf(rnode))==BLACK){
                     //情况复杂,暂时不写
                     setColor(rnode,RED);
                     x=parentOf(x);
                 }
                //情况二,找兄弟借,兄弟有的借
                else{
                    //分2种小情况:兄弟节点本来是3节点或者是4节点的情况
                     if(colorOf(rightOf(rnode))==BLACK){//这里已经是判断出来,一定有一个节点,那么右孩子为空,左孩子一定不为空
                        setColor(leftOf(rnode),BLACK);
                        setColor(rnode,RED);
                        rightRotate(rnode);
                        rnode=rightOf(parentOf(x));
                     }
                     setColor(rnode,colorOf(parentOf(x)));
                     setColor(parentOf(x),BLACK);
                     setColor(rightOf(rnode),BLACK);
                     leftRotate(parentOf(x));
                     x=root;
                 }
            }
            //x是右孩子的情况
            else{
                //兄弟节点
                RBNode rnode = leftOf(parentOf(x));
                //判断此时兄弟节点是否是真正的兄弟节点
                if(colorOf(rnode)==RED){
                    setColor(rnode,BLACK);
                    setColor(parentOf(x),RED);
                    rightRotate(parentOf(x));
                    //找到真正的兄弟节点
                    rnode=leftOf(parentOf(x));
                }
                //情况三,找兄弟借,兄弟没得借
                if(colorOf(rightOf(rnode))==BLACK&&colorOf(leftOf(rnode))==BLACK){
                    //情况复杂,暂时不写
                    setColor(rnode,RED);
                    x=parentOf(x);
                }
                //情况二,找兄弟借,兄弟有的借
                else{
                    //分2种小情况:兄弟节点本来是3节点或者是4节点的情况
                    if(colorOf(leftOf(rnode))==BLACK){
                        setColor(rightOf(rnode),BLACK);
                        setColor(rnode,RED);
                        leftRotate(rnode);
                        rnode=leftOf(parentOf(x));
                    }
                    setColor(rnode,colorOf(parentOf(x)));
                    setColor(parentOf(x),BLACK);
                    setColor(leftOf(rnode),BLACK);
                    rightRotate(parentOf(x));
                    x=root;
                }
            }
        }
        //情况一、替代节点是红色,则直接染红,补偿删除的黑色节点,这样红黑树依然保持平衡
        setColor(x,BLACK);
    }

    private RBNode getNode(K key){
        RBNode node=this.root;
        while(node!=null){
            int cmp = key.compareTo((K) node.key);
            if(cmp<0){
                node=node.left;
            }
            else if(cmp>0){
                node=node.right;
            }
            else
                return node;
        }
        return null;
    }

    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(K key, V value, RBNode parent) {
            this.parent = parent;
            this.color = BLACK;
            this.key = key;
            this.value = value;
        }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值