【C++研发面试笔记】11. 基本数据结构-红黑树RBT

【C++研发面试笔记】11. 基本数据结构-红黑树RBT

上一节,我们提到了为了解决二叉查找树不平衡问题,我们引入了AVL树,AVL是严格平衡树,但在增加或删除节点时,需要非常多的旋转操作。因此这一节我们介绍红黑树,红黑是弱平衡的,用非严格的平衡来换取增删节点时候旋转次数的降低,其在在增加或删除节点时,旋转操作要比AVL树更少;因此当搜索的次数远远大于插入和删除,则选择AVL树,如果搜索,插入删除次数几乎差不多,应该选择RB树。
红黑树虽然是复杂的,但在最坏情况运行时间也是非常良好的,并且在实践中是高效的,其可以在O(log n)时间内做查找、插入和删除,这里的n 是指树中元素的数目。
由于红黑树有着良好的稳定性和完整的功能,性能表现也还不错,所以C++ STL和linux都使用红黑树作为平衡树的实现。

注:老实说,红黑树在面试的时候,很少会考,因为太难太复杂了,所以面试官一般不会让写红黑树的代码,最多会让介绍下红黑树的原理,因此了解下在红黑树的插入和删除时,树旋转操作是很重要的!

11.1 RBT的结构

红黑树上每个结点内含五个域,color(颜色域,指红或黑),key(结点的值),left(左子结点),right(右子结点),p(父结点)。如果相应的指针域没有,则设为NIL。
一般的,红黑树,满足以下性质,即只有满足以下全部性质的树,我们才称之为红黑树:

  1. 每个结点要么是红的,要么是黑的。
  2. 根结点是黑的。
  3. 每个叶结点,即空结点(NIL)是黑的。
  4. 如果一个结点是红的,那么它的俩个儿子都是黑的。
  5. 对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。

红黑树


11.2 RBT的实现

11.2.1 RBT的结构

这里写图片描述

11.2.2 插入节点

首先我们将红黑树当作一颗二叉查找树,当把节点插入时,先找到合适的位置插入,然后将插入节点初始着色为红色,此时红黑树的只有性质4可能会违反!主要有如下几种情况:

  • 如果父结点(存在)是黑色的话,说明插入成功,不需要改变。
  • 如果父结点(存在)是红色的话,且是祖父的左子结点,此时说明性质4会违反
    • 如果叔结点为红色,将祖父结点调整为红,父结点和叔结点调整为黑色,然后从祖父结点递归调整一下,直到根结点。如果碰巧将根节点染成了红色, 可以在最后强制 root->黑。
    • 叔结点为黑色,且当前节点是右孩子,需要右旋
    • 叔结点为黑色,且当前节点是左孩子,需要左右旋
  • 如果父结点(存在)是红色的话,且是祖父的右子结点,此时说明性质4会违反
    • 叔结点为红色,将祖父结点调整为红,父结点和叔结点调整为黑色,然后从祖父结点递归调整一下,直到根结点。如果碰巧将根节点染成了红色, 可以在最后强制 root->黑。
    • 叔结点为黑色,且当前节点是右孩子,需要左旋
    • 叔结点为黑色,且当前节点是左孩子,需要右左旋

上面的左旋、右旋在上一节的AVL树上已经介绍了,方法是类似的,都是从叶结点出发,一直调整红黑树,使其满足红黑树的性质,直到到达根结点结束。

11.2.3 删除节点

我们知道删除节点需先选择左儿子中的最大元素或者右儿子中的最小元素取代待删除节点的位置,从而达到删除结点的目的,替代点N至少有一个子节点为NULL。

  • 若替代点N为红色,则两个子节点一定都为NULL(必须地),此时我们可以直接将替代点的值放到待删除节点的位置上,从而不违反任何性质。
  • 若替代点N为黑色,则其只有一个节点M不为NULL,且一定是红色的,此时M的子节点都为NULL,那么把N删掉时(替代点N要取代待删除节点的位置),用M替代N的位置,并改为黑色,也不违反任何性质。
  • 当N为黑色,但两个结点都为NULL,此时把N删掉,会使此路径上的一个黑节点被删除了,从而破坏了性质5,这种情况是比较麻烦的,主要有如下几种情况:
    • 兄弟结点S为红色,且N是父结点P的左孩子(或者N是P的右孩子)。因为P的左边路径上少了一个黑节点,此时要将P变红色,S变黑色,并以P为中心S向左旋(或者是右旋对应N是P的右孩子),此时再删除N。
      这里写图片描述
    • P、S及S的孩子们都为黑。将S改为红色,此时从P出发到其叶子节点到所有路径所包含的黑节点数目相等了。但还需把P当做新的起始点开始向上调整
      这里写图片描述
    • P为红,S及S的孩子们都为黑。此时将P改为黑,S改为红,因为P的路径上的黑结点数目没有发生变化,只需要直接删除N,就能完成调整。
      这里写图片描述
    • 当S为黑,N是P的左孩子,S的右孩子SR为红,S的左孩子任意(或者是N是P的右孩子,S的左孩子为红,S的右孩子任意)。将SR(SL)改为黑,P改为黑,S改为P的颜色,并以P为中心S向左左旋(或者是右右旋对应N是P的右孩子),然后直接删除N,就能完成调整。
      这里写图片描述
    • 当S为黑,N是P的左孩子,S的左孩子SL为红,S的右孩子SR为黑(或者N是P的有孩子,S的右孩子为红,S的左孩子为黑)。将SR(SL)改为黑,P改为黑,S改为P的颜色,并以P为中心S向右左旋(或者是左右旋对应N是P的右孩子),然后直接删除N,就能完成调整。
      这里写图片描述

这篇博文是个人的学习笔记,内容许多来源于网络(包括CSDN、博客园及百度百科等),博主主要做了微不足道的整理工作。由于在做笔记的时候没有注明来源,所以如果有作者看到上述文字中有自己的原创内容,请私信本人修改或注明来源,非常感谢>_<

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值