数据结构学习——红黑树

数据结构学习记录DAY12(大概) :红黑树 RBtree

  • 平衡二叉树的左右高度差不能超过一,这个条件过于苛刻。

  • 红黑树(大致平衡的二叉排序树)的特点

    • 最长路径<2*最短路径,放松了对平衡的限制,但是能确保杀入删除查找的时间复杂度在Olog2n

      我们不是从零创造红黑树,我们是通过学习既有模型了解性质加以使用,因此我们用一个经典模型展示借以描述红黑树的特点。

在这里插入图片描述

    由此可以引出红黑树的五条规则:

- 每一结点非红即黑

- 根结点必定是黑色

- 一条路径上的红色节点不能连续(黑色可以)

- 所有的叶子结点视为null都为黑色

- 从任意一个结点出发,到其所有叶子结点路径上的黑色结点的数量必须相等

有这五条规则,就可以开始写一棵红黑树了(大雾

其实是就可以开始探究红黑树的插入和删除了,因为红黑树的其他操作和平衡二叉排序树是一样的。

但是由于红黑树加入了限制,所以在插入和删除的操作上会相当复杂。
  • 红黑树的插入

    • 插入规则:每次插入都是红色的(若插入的位置是一个红色的结点,则会破坏红红的规则)
      • 为什么会是这样的插入规则呢?因为从根结点出发,到叶子结点如果有m条路径,插入之后在其中一条路径上增加一个黑色结点,剩下的m-1条路径都无法使其增加黑色的结点。相较于对m-1条路径进行操作,破坏红-红规则带来的后果显然会好处理很多
    • 插入需要修复的情况:
      • 变色:有叔叔结点,则向上变色(插入在左子树或右子树效果相同
        -在这里插入图片描述

        • 父结点和叔叔结点都为红色的,则父叔染黑爷爷染红
          在这里插入图片描述

        • 对爷爷结点向上讨论,若爷爷为根则变黑
          -在这里插入图片描述

        • 网上找相关内容的时候也看见有说会把新结点染黑再将父节点染红,个人觉得可以有,但不是非得有

      • 旋转:没有叔叔结点,旋转后变色

        • RR型 : 父在爷爷右边,当前结点在爷爷右边
          -在这里插入图片描述

          • 对爷左旋,原来的父染黑爷染红,
            在这里插入图片描述
        • LL型 : 父在爷爷左边,当前结点在爷爷左边

          • (与RR型对称,就不图示了)对爷右旋,父黑爷红,
        • LR型 : 子在爷爷左边,又在父亲右边
          -在这里插入图片描述

          • 对父左旋, 对爷右旋,爷染红子染黑
            -在这里插入图片描述
        • RL型 : 子在爷爷右边,又在父亲左边

          • 对父右旋, 对爷左旋,爷红子黑
      • 最多需要两次旋转,和log2n次 的颜色变化。

  • 红黑树的删除

    • 删除的结点没有子节点
      • 删除的结点为黑色:需要进一步考虑修复平衡
      • 红色:直接删除即可
    • 删除的结点只有一个子节点
      • 其子结点一定是红色的,用红色子结点替换要删除的结点,然后把那个结点染黑;
    • 删除的结点有两个子节点
      • 找左子树最大值替换当前元素
      • 转换成以上两种情况
  • 修复需要考虑的

    • 删除了黑色结点 到这条路径上的黑色节点少了一个,解决冲突在于能否找到一个红色结点经过旋转 染色 把它替换被删除的黑色的结点

    • 有以下几种情况:

      • 兄弟结点为红色,父亲和以及侄子都为黑色
      • 如下图删除结点:7
        -在这里插入图片描述

      1、先删除该节点(路径上的黑少了1,需要修补)

      在这里插入图片描述

      2、兄弟结点左旋

在这里插入图片描述

    3、兄弟结点染成原本父亲结点的黑色,父亲结点染红

在这里插入图片描述

    4、对原来的父亲结点进行左旋

在这里插入图片描述

    5、染色,结束

- 兄弟结点为黑色:

    - 兄弟的孩子为黑

    * 若父结点为红      父染黑    兄弟染红即可 结束 

    详细情况如图中删除70号

在这里插入图片描述

    1、先寻找左子树中最大的元素,替换要删除的元素,如左子树中最大元素为红色的,则完成,若为黑色就看例子2

在这里插入图片描述

    删除75:

在这里插入图片描述

    1、取左子树中最大值替换

在这里插入图片描述

    2、替换后乍看好像完美了,但是有一条规则“所有的叶子结点视为null都为黑色”

在这里插入图片描述

    所以此时不满足,需要将78结点置为红

在这里插入图片描述

    3、将兄弟节点50染红,父亲结点61染黑即可

在这里插入图片描述

    * 若父结点为黑       兄弟染红      以父结点当作删除的结点继续向上讨论

    

    - 兄弟的孩子不全为黑
    - 远端侄子为黑  (近端为红)     近端侄子染黑    兄弟染红  对兄弟进行旋转,使得远端侄子为红

    图解(以删除28号结点为例):

在这里插入图片描述

    1、没有子树就直接干掉,有就从左子树找最大值,或者直接将右子树接上

在这里插入图片描述

    2、兄弟左旋

在这里插入图片描述

    3、近端侄子染黑

在这里插入图片描述

    4、此处情况特殊,需要右旋25,然后染黑20

在这里插入图片描述

    - 远端侄子为红         对父结点进行旋转        兄弟结点置成父结点的颜色    远端侄子和父结点置黑即可
    - 图解(以删除25号结点为例):

在这里插入图片描述

    1、左子树最大值替换

在这里插入图片描述

    2、右孩子置为红

在这里插入图片描述

    3、父结点左旋

在这里插入图片描述

    4、兄弟结点置成父结点的颜色(黑色)    远端侄子(75)和父结点置黑即可

在这里插入图片描述

总结

  • 插入

    • 插入的结点为红色
    • 插入需要解决 红+红
      • 通过染色 父 + 叔 为红 父和叔染黑 祖父染红 继续向上讨论
      • 通过旋转 叔为黑
        • 自己 和 父 处于同一边 再通过祖父旋转,让祖父(黑色的结点)到另外一边,少了一个黑色结点 把父结点变成黑色的 到达插入位置结点黑色的结点不变, 另外一边由于多了一个黑色结点(父结点旋转为公共路径上的结点) 把祖父结点(旋转到另外一边)置红,用于抵消公共路径上黑色结点的增加
  • 删除

    • 只有删除黑色叶子结点 修复
    • 因为删除黑色结点 导致到该路径上的黑色结点减少
      • 借 只有当有红色结点时才有可能借 必须是远端侄子为红
        • 兄弟为红(侄子为黑) 通过旋转 让近端侄子变为兄弟
        • 只有兄弟为黑,侄子才有可能为红
        • 只有当远端侄子为红时,才能过旋转,让兄弟结点到公共的路径上(兄弟黑的,弥补删除时删除了一个黑色的结点),删除结点的那边会少出一个黑色结点 ,让远端红色的侄子变成黑色的 (需要注意的是兄弟结点需要染成原来父结点的颜色,在实际中,父结点染黑,远端侄子染黑)
      • 一水黑 (全都为黑) 使左右各少一个黑色结点 再对父结点向上讨论
红黑树的应用
  • C++ map/set/multiset/multimap 底层的实现就是红黑树
  • JAVA TreeSet/TreeMap 底层实现也是红黑树
  • 进程管理 Task任务用红黑树存储的
  • 数据库 索引 红黑树实现的
  • 多路复用IO epoll

以上!

希望能给你一点帮助

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值