ConcurrentHashMap红黑树实现分析Java8(补充:红黑树的删除操作)

此篇文章是在转载https://www.jianshu.com/p/b7dda385f83d的基础上进行了补充,原文章只介绍了红黑树的插入操作,由于红黑树的删除和插入同样重要,故站在巨人的肩膀上,进行了删除操作的补充。

红黑树

红黑树是一种特殊的二叉查找树,在满足二叉查找树的特性外,在每个节点上增加了存储颜色的标识,颜色要么是红色,要么是黑色,定义:

  1. 每个节点要么是黑色,要么是红色。
  2. 根节点是黑色。
  3. 所有叶子节点是黑色,即空节点(NIL)。
  4. 如果一个节点是红色的,则它的两个子节点必须是黑色的,也就是父子节点不能都为红色。
  5. 从一个节点到其所有叶子节点的所有路径上包含相同数目的黑节点。

注意:
(1) 特性3中的叶子节点,是只为空(NIL或null)的节点。
(2) 特性5,确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。因此在最坏情况下,红黑树能保证时间复杂度为O( lgn )
红黑树示意图

红黑树的插入

向一棵含有n个节点的红黑树插入一个新节点的操作可以在O(lgn)时间内完成。

规则约定

(1)在红黑树中插入节点时,节点的初始颜色都是红色。因为这样可以在插入过程中尽量避免对树的结构进行调整(参考第5点性质)。
(2)初始插入按照二叉查找树的性质插入,即找到合适大小的节点,在其左边或右边插入子节点。

我们插入一个节点后,可能会使原树的哪些性质改变呢?
(1)由于是以二叉查找树的性质插入,因此节点的查找性质不会破坏。
(2)如果插入空树中,成为根节点,则性质2会被破坏,需要重新涂色。
(3)如果插入节点的父节点是红色,则性质4会被破坏,需要以插入的当前节点为中心进行旋转或重新涂色来恢复红黑树的性质。执行旋转或重新涂色后有可能红黑树仍然不满足性质,则需要将当前节点变换回溯到其父节点或祖父节点,以父节点或祖父节点为中心继续旋转或重新涂色,如此循环到根节点直到满足红黑树的性质。

恢复红黑树性质的策略

根据上面说到的性质改变,对应的恢复策略其实就简单很多。
(1)把出现违背红黑树性质的结点向上移(通过旋转操作或变换当前节点到父节点或祖父节点后再旋转达到向上移动的目的),如果能移到根结点,那么很容易就能通过直接修改根结点的颜色,或旋转根节点来恢复红黑树的性质。
(2)旋转或涂色处理可分5种情况进行处理:

  1. 情况1:空树中插入根节点。
  2. 情况2:插入节点的父节点是黑色。
  3. 情况3:当前节点的父节点是红色,且叔叔节点(祖父节点的另一个子节点)也是红色。
  4. 情况4:当前节点的父节点是红色,叔叔节点是黑色,当前节点是右子节点。
  5. 情况5:当前节点的父节点是红色,叔叔节点是黑色,当前节点是左子节点。

情况1:空树中插入根节点

违反:性质2
恢复策略:直接染黑,结束循环。

情况2:插入节点的父节点是黑色

违反:插入的红色节点,未违反任何性质。
恢复策略:什么也不做,无需调整。

情况3:当前节点的父节点是红色,且叔叔节点也是红色

违反:性质4
此时祖父节点一定存在,否则插入前就已不是红黑树。
与此同时,又分为父节点是祖父节点的左子还是右子,由于对称性,我们只要解开一个方向就可以了。在此,我们只考虑父节点为祖父左子的情况。
同时,还可以分为当前结点是其父结点的左子还是右子,但是处理方式是一样的。我们将此归为同一类。
恢复策略:将当前节点的父节点和叔叔节点涂黑,祖父结点涂红,把当前结点指向祖父节点,以祖父节点为中心重新开始新一轮的旋转或涂色。
以插入节点4为例,按照恢复策略,做如下图的涂色:
在这里插入图片描述
以插入节点4为当前节点,判断父节点和叔叔节点是否都为红色,如果为红色,则将祖父节点7的颜色改为红色,父节点5和叔叔节点8的颜色改为黑色。同时当前节点移动到祖父节点7。此时,当前节点7的父节点也为红色,出现父子节点都为红色的情况,且叔叔节点为黑色,因此适用于情况4:当前节点的父节点是红色,叔叔节点是黑色,当前节点是右子节点,那么按照情况4的恢复策略,进行新一轮的旋转或涂色,如下看情况4如何进行调整。

情况4:当前节点的父节点是红色,叔叔节点是黑色,当前节点是右子节点

违反:性质4
恢复策略:以当前节点的父节点作为新的当前节点,以新的当前节点为支撑,进行左旋操作。旋转操作后再按新的情况进行旋转或涂色。
在这里插入图片描述
这里作的操作为:当前节点由原来的7变换为其

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值