深入红黑树查插删的流程底层,并深入操作后的自平衡

红黑树的延伸

  • 查找

    • 因为红黑树就是平衡的二叉查找树,所以查找更不会破坏红黑树的平衡
    • 查找方式流程
      • 从根结点开始查找,把根结点设置为当前结点;
      • 若当前节点为空,则返回null
      • 若当前节点不为空,用当前的key跟查找的key进行比较
      • 若当前的节点等于要查找的key,那就是我们要查找的目标
      • 若当前结点key大于查找key,把当前结点的左子结点设置为当前结点,重复步骤2;
      • 若当前结点key小于查找key,把当前结点的右子结点设置为当前结点,重复步骤2;
        img
  • 插入

    • 插入的流程
      • 查找插入的位置
      • 插入后自平衡
    • 具体判断位置流程
      • 先找到插入的位置
        • 1 .从根节点开始进行查找要进行插入的位置
        • 2 .若根节点为空,那么插入节点作为根节点,结束
        • 3 .若根结点不为空,那么把根结点作为当前结点;
        • 4 .若当前节点为null,返回当前节点的父节点,结束
        • 5 .若当前结点key等于查找key,那么该key所在结点就是插入结点,更新结点的值,结束。
        • 6 .若当前结点key大于查找key,把当前结点的左子结点设置为当前结点,重复步骤4
        • 7 .若当前结点key小于查找key,把当前结点的右子结点设置为当前结点,重复步骤4
          • img
      • ok,插入的位置已经找到了,现在就是插入的颜色是什么—>红色,理由很简单
        • 红色在父结点(如果存在)为黑色结点时,红黑树的黑色平衡没被破坏,不需要做自平衡操作。
        • 但如果插入结点是黑色,那么插入位置所在的子树黑色结点总是多1,必须做自平衡
    • 深入插入情景
      • img
      • 背景
        • img
        • 嗯,插入情景很多呢,8种插入情景!但情景1、2和3的处理很简单,而情景4.2和情景4.3只是方向反转而已,懂得了一种情景就能推出另外一种情景,所以总体来看,并不复杂
      • 深入4种插入情景(除了情景二其他都是在叶子节点上进行操作)
        • 情景一:红黑树为空树
          • 这个是最近简单的,我们直接将我们的插入节点作为根节点就OK,但是要注意,根节点的颜色为黑色,所以还需要将我们的节点的颜色设为黑色
          • 流程
            • 设为根节点
            • 设置节点颜色为黑色
        • 情景二:插入节点的Key已存在
          • 插入的节点已存在,既然红黑树总是保持平衡的,插入前就是保持平衡的,那么插入的节点设置为当前节点的颜色,在将节点的值进行更新
          • 流程
            • 将我们插入节点(也就是背景图中的I)设置为当前节点(非插入节点)的颜色
            • 更新当前节点的值为插入节点的值
        • 情景三:插入节点的父节点为黑色
          • 由于插入的结点是红色的,当插入结点的黑色时,并不会影响红黑树的平衡,直接插入即可,无需做自平衡。
          • 流程
            • 直接进行插入
        • 情景四:插入节点的父节点为红色
          • 由于插入节点的颜色为红色,但是它的父节点的颜色也是红色,违反了红黑树的规范,那该父节点不可能成为根节点,所以后续的旋转操作需要祖父节点的加入

          • 情景四又有更多的子情景,听我细细说来哈哈哈⚡
            • 插入情景4.1:叔叔结点存在并且为红结点
              • 如果叔叔节点为红结点的话,那根据红黑树的规范来看,当前插入子树的红黑层数情况是黑红红,最简单的方式也就是改变颜色,后我们的红黑层数情况是红黑红

              • 流程

                • 将P和S设置为黑色
                • 将PP设置为红色
                • 把PP设置为当前插入结点
                • img
              • 我们来进行对PP该节点的判断(因为进行插入后将PP节点又设置为红结点了)

                • 如果PP节点是有父节点的
                  • PP节点是黑色的
                    • 无需做任何的处理
                  • PP节点是红色的
                    • 根据红黑树的约束,此时的红黑树已经是不平衡的,我们需要将PP节点作为插入节点进行,继续做插入操作自平衡处理,直到红黑树为止
                • 如果PP节点已经是根节点了,根据红黑树的约束我们需要将PP节点设为黑节点
                  • 我们需要思想一个问题,我们现在的红黑层树为黑黑红,从另一个层面来讲,我们从根节点到我们的叶子节点之间的路径中,黑色节点增加了
                  • 这是唯一一种会增加红黑树黑色结点层数的情况

                这又得出来一个结论—>红黑树的生长是自底向上的,而和普通的二叉查找树是不同的,二叉查找树是自顶向下的

            • 插入情景4.2:叔叔结点不存在或为黑结点,并且插入结点的父亲结点是祖父结点的左子结点

              • 单纯从插入前来看,也即不算情景4.1自底向上处理时的情况,叔叔结点非红即为叶子结点(Nil)。

                • 因为如果叔叔结点为黑结点,而父结点为红结点,那么叔叔结点所在的子树的黑色结点就比父结点所在子树的多了,这不满足红黑树的性质5。后续情景同样如此,不再多做说明了。

                前文说了,需要旋转操作时,肯定一边子树的结点多了或少了,需要租或借给另一边。插入显然是多的情况,那么把多的结点租给另一边子树就可以了

              • 插入情景4.2.1:插入结点是其父结点的左子结点

                • 我们需要维护红黑树自平衡的规范,两边的子树都平衡的
                • 流程
                  • 将P设为黑色
                  • 将PP设为红色
                  • 对PP进行右旋
                • img
              • 插入情景4.2.2:插入结点到其父结点的右子结点

                • 跟4.2.1的情况是一样的不多说明了
                • 流程
                  • 我们将P进行左旋,同时设为插入节点
                  • 得到了4.2.1的情况
                  • 之后我们在进行左旋,得到平衡的红黑树
                • img
            • 插入情景4.3:叔叔结点不存在或为黑结点,并且插入结点的父亲结点是祖父结点的右子结点

              • 该情景对应情景4.2,只是方向反转,不做过多说明了,直接看图。

              • 插入情景4.3.1:插入结点是其父结点的右子结点

                • 流程:
                  • 将P设为黑色
                  • 将PP设为红色
                  • 对PP进行左旋
                • img
              • 插入情景4.3.2:插入结点是其父结点的左子结点

                • 流程:

                  • 对P进行右旋
                  • 把P设置为插入结点,得到情景4.3.1
                  • 进行情景4.3.1的处理
                • img
                • 插入所有的情景后,好好做功课的又会说,那上面所有的插入情况都是第一次进行插入有没有包含自下向上处理的情况吗?答案是肯定的

                • 理由很简单,但每棵子树都能自平衡,那么整棵树最终总是平衡的

  • 删除

    • 我们先搞清楚红黑树删除的过程
      • 一查找目标结点;
        • 查找目标结点显然可以复用查找操作,当不存在目标结点时,忽略本次操作;
      • 而删除后自平衡。
        • 当存在目标结点时,删除后就得做自平衡处理了。
        • 删除了结点后我们还需要找结点来替代删除结点的位置,不然子树跟父辈结点断开了,除非删除结点刚好没子结点,那么就不需要替代
    ok,屏幕前的同学,请记住:深吸一口气,带好你的AirPods Pro(降噪打开),有点难的地方来喽!,尽量不要被打扰哦,记住,不会不清楚的话,拿出你们的笔记本,画着写着,一遍不会n遍,ok,开始
    • ok,二叉树删除节点找的替换结点有三个情景
      • 若删除结点没有子节点,直接进行删除
      • 若删除结点只有一个子节点,用子节点替换删除节点
      • 若删除结点有两个子节点,那就用后继结点(大于删除结点的最小结点)替换删除结点
      • 注意(补充说明)
        • 情景3的后继结点是大于删除结点的最小结点,也是删除结点的右子树种最左结点
        • 那么
          • 那么可以拿前继结点(删除结点的左子树最右结点)替代吗?可以的
        • 但是我们一般都习惯用后继节点进行替换节点进行使用,后面的所有替换情景都是以后继节点进行的,
        • so,有一种可以进行直接发现删除结点的前继结点和后继节点
          • 把二叉树所有结点投射在X轴上,所有结点都是从左到右排好序的,所有目标结点的前后结点就是对应前继和后继结点—–看图
            • img
    • ok,介绍完删除结点找替换结点的情景后
      • 接下来,讲一个重要的思路:删除结点被替代后,在不考虑结点的键值的情况下,对于树来说,可以认为删除的是替代结点话很直接,我们看下面的图。在不注意其他因素的情况下,图17的红黑树最终结果是删除了Q所在位置的结点!这种思路非常重要,大大简化了后文讲解红黑树删除的情景!

        • img
        • 看上图,3中情景,情景之间可以互相转换,最终又到了情景1这里

        • 讲解一下上面的这句话
          • 删除结点用唯一的子节点作为替代结点,子节点替换为删除结点后,我们假如子节点下又有两个子节点,这个时候我们要进行切换到我们的情景三,注意:一直自顶向下,我们最后又会回到我们的情景1里(对于红黑树来说,根据性质5.1,只存在一个子结点的结点肯定在树末了)
          • 情景3:删除结点用后继结点(肯定不存在左结点),如果后继结点有右子结点,那么相当于转换为情景2,否则转为为情景1
    • 二叉树删除情景
      img
      • 综上所述,**删除操作删除的结点可以看作删除替代结点,而替代结点最后总是在树末。**有了这结论,我们讨论的删除红黑树的情景就少了很多,因为我们只考虑删除树末结点的情景了
    • ok,删除情景也搞ok了,我们就看看删除操作时的情景
      img
      • 是的,我们即时简化了还有9种情景,!但跟插入操作一样,存在左右对称的情景,只是方向变了,没有本质区别,ok,我们说一下删除操作前的背景
      • 操作背景前提
        • img
        • 提醒

          • 灰色代表的可能是红色,可能是灰色
          • R指得时删除结点的替代节点,在删除前,它还在原来所在位置参与树的子平衡,平衡后再替换到删除结点的位置,才算删除完成
      ok,我们来到最难的时候,这时候不要放弃,馅饼就在前面,加油!!!
  • 详解9种删除操作情景
    • 删除情景1:替换结点是红色结点
      • 我们把替换的结点换到删除结点的位置上后,由于替换结点的颜色是红色,删除后又不会影响我们红黑树的平衡,所以直接将我们的替换结点的颜色设为删除结点就ok
      • 流程
        • 将替换结点的颜色换为删除结点就ok
    • 删除情景2:替换节点是黑色结点
      • 我们替换后倒是不需要去大致的注意连续红色的结点出现,所以我们要注意的是我们的根节点到我们的叶子节点的黑结点也就多了一个,所以要进行旋转的操作,对于情况的左旋右旋
      • 删除情景2.1:替换结点是其父结点的左子结点
        • 删除情景2.1.1:替换结点的兄弟结点是红结点
          • 若兄弟结点是红结点,那它的父节点和子节点一定是黑色结点(根据约束4),不会有其他情况,所以进行处理,但是没有处理完,我们要继续深究到2.1.2.3(记住,这里的R仍然是我们的替换节点)(
          • 处理
            • 将S设为黑色
            • 将P设为红色
            • 对P进行左旋,得到情景2.1.2.3
            • 进行情景2.1.2.3的处理
            • img
        • 删除情景2.1.2:替换结点的兄弟结点是黑结点(各种情况各种定)
          • 当兄弟结点为黑时,其父结点和子结点的具体颜色也无法确定(如果也不考虑自底向上的情况,子结点非红即为叶子结点Nil,Nil结点为黑结点),此时又得考虑多种子情景
          • 删除情景2.1.2.1:替换结点的兄弟结点的右子结点是红结点,左子结点任意颜色(黑结点数量不同)
            • 即将删除的左子树的一个黑色结点,显然左子树的黑色结点少1个了,然而右子树又有红色结点,那么我们直接向右子树“借”个红结点来补充黑结点就好啦,此时肯定需要用旋转处理了。
            • 处理
              • 将S的颜色设为P的颜色
              • 将P设为黑色
              • 将SR设为黑色
              • 对P进行左旋
              • img
        平衡后的图怎么不满足红黑树的性质?前文提醒过,R是即将替换的,它还参与树的自平衡,平衡后再替换到删除结点的位置,所以R最终可以看作是删除的
        另外上幅图是考虑到第一次替换和自底向上处理的情况,如果只考虑第一次替换的情况,根据红黑树性质,SL肯定是红色或为Nil(因为R作为替换节点到树底时,这时R已经是删除结点后进行删除了,,也就是只剩SL了),所以最终结果树是平衡的。如果是自底向上处理的情况,同样,每棵子树都保持平衡状态,最终整棵树肯定是平衡的。后续的情景同理,不做过多说明了
        • 删除情景2.1.2.2:替换结点的兄弟结点的右子结点为黑结点,左子结点为红结点(借点红结点保持平衡呗)
          • 兄弟结点所在的子树有红结点,我们总是可以向兄弟子树借个红结点过来,显然该情景可以转换为情景2.1.2.1。
          • 流程
            • 将S设为红色
            • 将SL设为黑色
            • 对S进行右旋,得到情景2.1.2.1
            • 进行情景2.1.2.1的处理(进行自平衡)
            • img
        • 删除情景2.1.2.3:替换结点的兄弟结点的子结点都为黑结点
          • 好了,此次兄弟子树都没红结点“借”了,兄弟帮忙不了,找父母呗,这种情景我们把兄弟结点设为红色,再把父结点当作替代结点,自底向上处理,去找父结点的兄弟结点去“借”。但为什么需要把兄弟结点设为红色呢?显然是为了在P所在的子树中保证平衡(R即将删除,少了一个黑色结点,子树也需要少一个),后续的平衡工作交给父辈们考虑了,还是那句,当每棵子树都保持平衡时,最终整棵总是平衡的
          • 流程
            • 将S设为红色
            • 把P作为新的替换结点
            • 重新进行删除结点情景处理
      • 删除情景2.2:替换结点是其父结点的右子结点
        • 好啦,右边的操作也是方向相反,不做过多说明了,相信你理解了删除情景2.1后,肯定可以理解2.2。
        • 删除情景2.2.1:替换结点的兄弟结点是红结点
          • 我们这样子看的话,我们删除替代节点时,我们的红黑树还是不具有平衡性的,我们先进行平衡,之后再进行平行
          • 流程
            • 将S设为黑色
            • 将P设为红色
            • 对P进行右旋,得到情景2.2.2.3
            • 进行情景2.2.2.3的处理
            • img
        • 删除情景2.2.2.1:替换结点的兄弟结点的左子结点是红结点,右子结点任意颜色
          • 流程
            • 将S的颜色设为P的颜色
            • 将P设为黑色
            • 将SL设为黑色
            • 对P进行右旋
            • img
        • **删除情景2.2.2.2:替换结点的兄弟结点的左子结点为黑结点,右子结点为红结点
          • 流程
            • 将S设为红色
            • 将SR设为黑色
            • 对S进行左旋,得到情景2.2.2.1
            • 进行情景2.2.2.1的处理
            • img
        • 删除情景2.2.2.3:替换结点的兄弟结点的子结点都为黑结点
          • 流程
            • 将S设为红色
            • 把P作为新的替换结点
            • 重新进行删除结点情景处理
            • img

总结(删除总结)

红黑树删除后自平衡的处理可以总结为:
  1. 自己能搞定的自消化(情景1)
  2. 自己不能搞定的叫兄弟帮忙(除了情景1、情景2.1.2.3和情景2.2.2.3)
  3. 兄弟都帮忙不了的,通过父母,找远方亲戚(情景2.1.2.3和情景2.2.2.3)

啊,我是真的吐了,本章参考于安卓大叔的红黑树理解,但是所有的文字都是经过自己的理解敲上来的(脑子要炸掉),到这里是真的完了,现在已经是晚上的2:38了,我也该睡觉觉了,明天再复习一遍!!!


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值