十图详解红黑树原理(HashMap)

一、二叉查找树

Binary Search Tree(BST)

不知道大家有没有玩过一个游戏,叫“猜数字”。甲先在纸上写一个数字(如11),然后让另外一些人在1-100的范围内猜这个数字(如A猜49),若猜中,则此人输,游戏结束;若没有猜中,则由甲缩小数字范围(甲说,范围变为1-49),由下一人继续猜,直至猜出数字为止。

这也是二叉查找树的精髓,通过不断比较大小,缩小范围,最终得到要找的元素的位置。

二叉树的特性:

  • 某节点的左子树节点值仅包含小于该节点值
  • 某节点的右子树节点值仅包含大于该节点值
  • 每个左右子树也必须是二叉查找树
    图解

但是,如果是这样的呢?
在这里插入图片描述
也完全符合二叉树的特性,但是这样的树,你想找“3”,就十分费劲。站在程序的角度,就要查询很多次,效率十分低下。这时,红黑树就腾空出世了。

二、红黑树

Red-Black Tree(RBT)红黑树是一种含有红黑结点并能自平衡的二叉查找树。

红黑树的特性:

  • 每个节点要么是黑色,要么是红色
  • 根节点是黑色
  • 每个叶子节点(NIL)是黑色(java中为null)
  • 每个红色结点的两个子结点一定都是黑色(即不能有两个相连的红)
  • 任意一结点到每个叶子结点的路径都包含数量相同的黑结点(黑色完美平衡,但不是完美平衡)。推论:如果一个结点存在黑子结点,那么该结点肯定有两个子结点

红黑树中节点的称呼:
在这里插入图片描述

三、红黑树实现自平衡的两大操作

变色recolor 和 rotation旋转
具体来说,该如何操作呢?现在假设我们向红黑树中插入一个新节点 X,需要执行以下步骤:

  1. 将新插入的节点标记为红色
  2. 如果新节点 X 是根结点(root),则标记为黑色,结束
  3. 若 X 的 parent 是黑色,则结束;若 X 的 parent 是红色,且 X 不是 root,则分两种情况(3.1和3.2)

3.1.当 uncle 是红色时

3.1.1 将 parent 和 uncle 标记为黑色
3.1.2 将 grand parent (祖父) 标记为红色
3.1.3 把 X 的祖父设置为当前节点
3.1.4 重复步骤 2、3

在这里插入图片描述

3.2.当 uncle 是黑色时

这时分四种情况:左左、左右、右右、右左。

3.2.1 左左 (P 是 G 的左孩子,并且 X 是 P 的左孩子)

则手提P为根节点,P和G(原根节点)分别变色
在这里插入图片描述

3.2.2 左右 (P 是 G 的左孩子,并且 X 是 P 的右孩子)
则左旋:使 X 的父节点 P 被 X 取代,同时父节点 P 成为 X 的左孩子(X和P位置互换),然后再应用 左左情况
在这里插入图片描述

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

3.2.4 右左
则右旋
在这里插入图片描述

四、左旋和右旋的精准表述

左旋:以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。
在这里插入图片描述

右旋:以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。
在这里插入图片描述
旋转操作是局部的。旋转能保持红黑树平衡:当一边子树的结点少了,那么向另外一边子树“借”一些结点;当一边子树的结点多了,那么向另外一边子树“租”一些结点。

五、红黑树查找

红黑树的查找跟二叉平衡树的查找无异。那么二叉树的查找是怎样的呢?与“猜数字”游戏的从查找无异!
二叉树查找流程
红黑树总保持黑色完美平衡,它的查找最坏时间复杂度为 O(2lgN)

六、红黑树删除

二叉树删除结点 找替代结点有3种情景:
情景1:若删除结点无子结点,直接删除
情景2:若删除结点只有一个子结点,用子结点替换删除结点
情景3:若删除结点有两个子结点,用后继结点(大于删除结点的最小结点)替换删除结点
比如我要删除P,则后继结点便为R,前继节点为M
(比如我要删除P,则后继结点便为R,前继节点为M)

删除结点被替代后,在不考虑结点的键值的情况下,对于树来说,可以认为删除的是替代结点!
在这里插入图片描述
(删除P相当于删除Q)

现在我们再来回顾一下删除结点时的3种情况:
情景1,删除结点无子结点,直接删除(这时删除的结点在树末)
情景2,删除结点只有一个子结点,用子结点替换删除结点(即其实相当于删除了子结点,而这个子节点在树末)
情景3,删除结点有两个子结点,用后继结点替换删除结点(相当于删除了后继结点,而后继结点在树末)
发现了吗?无论那种情景,最终删除的结点,都在树末。
所以,我们把重点,放在这个树末结点(也即是替代结点)!(因为整棵树都平衡了之后,要做的就只是替换值和删除了)
在这里插入图片描述

七、红黑树删除例子

删除情景1:替代结点是红色结点

用替代结点代替删除结点,颜色变为删除结点的颜色。(由于替代结点是红色,删除了并不会影响红黑树的平衡,所以此情况无须做自平衡处理)

删除情景2:替换结点是黑结点

当替换结点为黑色时,我们就需要做自平衡处理了。
记住,对于替换结点,先自平衡,后替换(删除)
还记得红黑树是如何自平衡的吗,对的,根据不同的情况进行左旋和右旋操作;删除结点时的自平衡,与此类似。

删除情景2.1:替换结点是其父结点的左子结点

2.1.1:替换结点的兄弟结点是红结点

在这里插入图片描述
(R是替换结点,是父结点的左子结点,其兄弟结点是红结点)

处理:
将S设为黑色
将P设为红色
对P进行左旋,得到删除情景2.1.2.3(再接删除情景2.1.2.3处理)
在这里插入图片描述

2.1.2:替换结点的兄弟结点是黑结点

当兄弟结点为黑时,其父结点和子结点的具体颜色无法确定,遂需要考虑多种情况。

2.1.2.1:替换结点的兄弟结点的右子结点是红结点,左子结点任意颜色

在这里插入图片描述
即将删除左子树的一个黑色结点 (即R),显然左子树的黑色结点少了1个,而右子树有红色结点,遂向右子树“借”个红结点来补充黑结点。(这里和红黑树的特性“任意一结点到每个叶子结点的路径都包含数量相同的黑结点”有关,此特性的推论为“如果一个结点存在黑子结点,那么该结点肯定有两个子结点”)
处理:
将S的颜色设为P的颜色
将P设为黑色
将SR设为黑色
对P进行左旋
在这里插入图片描述
(R是准备删除的)

2.1.2.2:替换结点的兄弟结点的右子结点为黑结点,左子结点为红结点

在这里插入图片描述
兄弟结点所在的子树有红结点,可向兄弟子树借红结点
处理:
将S设为红色
将SL设为黑色
对S进行右旋,得到情景2.1.2.1
接情景2.1.2.1的处理
在这里插入图片描述

2.1.2.3:替换结点的兄弟结点的子结点都为黑结点

在这里插入图片描述
此时兄弟子树都没红结点可“借”,兄弟帮忙不了,找父母呗。这种情景我们把兄弟结点设为红色(因为黑色R即将删除),再把父结点当作替代结点,自底向上处理,去找父结点的兄弟结点“借”。
处理:
将S设为红色
把P作为新的替换结点
重新进行删除结点情景处理
在这里插入图片描述

删除情景2.2:替换结点是其父结点的右子结点

(删除情景2.1的镜像情景)

2.2.1:替换结点的兄弟结点是红结点

处理:
将S设为黑色
将P设为红色
对P进行右旋,得到情景2.2.2.3
进行情景2.2.2.3的处理
在这里插入图片描述

2.2.2:替换结点的兄弟结点是黑结点
2.2.2.1:替换结点的兄弟结点的左子结点是红结点,右子结点任意颜色

处理:
将S的颜色设为P的颜色
将P设为黑色
将SL设为黑色
对P进行右旋
在这里插入图片描述

2.2.2.2:替换结点的兄弟结点的左子结点为黑结点,右子结点为红结点

处理:
将S设为红色
将SR设为黑色
对S进行左旋,得到情景2.2.2.1
进行情景2.2.2.1的处理
在这里插入图片描述

2.2.2.3:替换结点的兄弟结点的子结点都为黑结点

处理:
将S设为红色
把P作为新的替换结点
重新进行删除结点情景处理
在这里插入图片描述

八、问题

  • 哪些场景可以应用红黑树?
  • 你了解各种树的时间复杂度吗?

来源:https://www.jianshu.com/p/104fa73c81b3

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值