HashMap1.8 -- 红黑树 -讲解

红黑树

红黑树的5个特性:
1.每个节点要不黑色就是红色
2.根节点是黑色
3.每个叶子节点是黑色(NIL)
4.不能有两个 红色节点相连接,那么红色节点的 两个孩子节点必定 为黑色
5.黑高  任意节点出发到叶子节点  褐色节点数量相同
6.如果一个节点存在一个黑色子节点,那么必定该节点有两个孩子节点

红黑树的 节点属性:
1.颜色color
2.左孩子节点leftNode
3.右孩子节点rightNode
4.父亲节点 parent
5.Key  value

在这里插入图片描述

左旋和右旋(核心)
左旋:
在这里插入图片描述

右旋:
在这里插入图片描述

插入算法:
1.类似于 二叉排序树 先查找到插入的节点位置,插入进去。之后再做 红黑树的平衡操作。(注意:相等的时候,直接 覆盖掉value值即可);
  思路:
1.1.申明一个节点指向待插入位置的parent
1.2申明p用于遍历循环查找到待插入位置 
1.3判断parent是否为空,如果为空 即红黑树为空树,直接插入变色,相反插入后进行平衡操作。

2.插入平衡操作(记住 在最后设置根节点为黑色)
  情形一:红黑树为空树,(这个已经在插入已经实现)。
  情形二: 插入节点的key已经存在,(在插入的时候已经完成覆盖)
  情形三:插入节点的父节点为黑色,直接插入即可
  情形四:(重点处理对象)插入节点的父节点为红色
|---情景4.1:叔叔节点存在,并且为红色(父-叔 双红)
*          |---情景4.2:叔叔节点不存在,或者为黑色,父节点为爷爷节点的左子树
*               |---情景4.2.1:插入节点为其父节点的左子节点(LL红情况)
			      1.Parent和gparent 交换颜色 2.右旋
*               |---情景4.2.2:插入节点为其父节点的右子节点(LR红情况)
			    1.先以parent左旋,2.然后按照LL红处理
*          |---情景4.3:叔叔节点不存在,或者为黑色,父节点为爷爷节点的右子树
*               |---情景4.3.1:插入节点为其父节点的右子节点(RR红情况)
*               |---情景4.3.2:插入节点为其父节点的左子节点(RL红情况)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
删除操作:(复杂一些)
分三个方法:
1.查找待删除节点 searchRemoveNode
2.执行删除操作 removeNode

3.二叉树平衡操作 balanceRBTree


一.查找待删除节点
RBNode needRemoveNode = root;
while(needRemoveNode!=null)
{
    if(needRemoveNode.key.compareTo (key)<0) // needRemoveNode<key
    {
        needRemoveNode = needRemoveNode.rightNode;
    }
    else if(needRemoveNode.key.compareTo (key)>0)  //needRemoveNode>key
    {
        needRemoveNode = needRemoveNode.leftNode;
    }
    else //相等的情况  此时needRemoveNode 就是 待删除节点
    {
        break;
    }
}




二.执行删除操作   (二叉排序树的删除操作)
* 1.无子节点
* 2.只有一个节点
* 3.有两个  ->转为 12
* 传进来的是 待删除节点 用于 情形3  转为 情形12 提供桥梁

主要处理的就是删除节点 是黑色的无孩子节点

private void removeNode(RBNode n)
{
    /**
     * 接下来就是删除节点  (思想是按照 二叉排序树)
     * 1.无节点时候  1.1 红色  直接删除
     *                1.2 黑色,需要平衡调整
     * 2.只有一个节点  此时 n肯定为黑色   他的子节点必定为红色
     * 3.有两个节点  转至 1 和2  情形
     */
    // 1 无子节点时候
    if(n.leftNode == null && n.rightNode == null)
    {
        // 1.1 删除节点为红色时候  此时不可能为根节点  因为root 一定为黑色
        if(isRed (n))
        {
            if(n.parent.leftNode == n)
            {
                n.parent.leftNode = null;
            }
            else if(n.parent.rightNode == n)
            {
                n.parent.rightNode = null;
            }
        }
        //*******删除节点为黑色的时候 需要平衡操作  仅仅此一处 调整异常麻烦********
        else
        {   //先进行平衡操作,然后再 删除该节点
            balanceRBTree(n);
            if(this.root == n)
            {
                this.root = null;
            }
            else
            {
                if(n.parent.leftNode == n){
                    n.parent.leftNode = null;
                } else {
                    n.parent.rightNode = null;
                }
            }
        }
    }
    /**
     * 2.只有一个子节点的时候
     * 此时删除节点只能为黑色,子节点一定为红色
     */
    else if((n.leftNode != null && n.rightNode == null)||(n.leftNode == null && n.rightNode != null))
    {
        //查找那个不为空的子节点
        RBNode replaceNode = n.leftNode != null ? n.leftNode : n.rightNode;
        replaceNode.parent = n.parent;

        //n可能为 根节点
        if(replaceNode.parent == null)
        {
            root = replaceNode;
        }
        else if(n.parent.leftNode == n)
        {
            n.parent.leftNode = replaceNode;
        }
        else
        {
            n.parent.rightNode = replaceNode;
        }
        n.remove ();
        //涂黑  达到平衡  这里 就可以直接返回
        setBlack (replaceNode);
        return;
    }

    /**
     * 3. 有两个节点时候
     *   可以转到 情形 1 和 2
     */
    else
    {
        //最终这个p指向的就是 替换节点
        RBNode p = n.leftNode;
        while (p .rightNode!= null)
        {
            p = p.rightNode;
        }
        //替换值操作
        n.key = p.key;
        n.v = p.v;
        //将 n 指向p  那么 n 变为待删除节点 转到了情形 1 和 2
        n = p;
        //递归遍历 实质上-> 情形三 转为 情形一  和   情形二
        // 此时的  n  必定    要不 无子节点   要不 就一个子节点
        removeNode (n);
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.2 S在右子树上 N在左子树上
变色操作 左旋 如以上操作

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值