• 红黑树的插入及删除的节点处理


    对红黑树的插入处理,真正需要考虑的有以下几点:

    1).插入位置:插入在外侧还是内侧。插入位置影响的是单次旋转是否足够使新树遵守红黑树规则,具体看下面分析。

    2).伯父节点的颜色:伯父节点的颜色是红色还是黑色。红色时只要变换颜色即可处理,而黑色则需要进行旋转了。

    3).曾祖父节点的颜色:曾祖父点的颜色是红色还是黑色。由于伯父节点是红色时,我们进行的是换色处理,如果曾祖父是红色,则新的矛盾点出现在了曾祖父节点和换色的节点之间,具体看下面分析。

    情况一:伯父节点为黑色,且为外侧插入

    首先说说插入位置的影响:

    如果是外侧插入,以下图为例:

    首先我们考虑,出现矛盾的是P与N的颜色均为红色,那简单一点直接把P变为黑色是不是就可以了呢?

    这个想法是错误的,因为在N未插入之前,该RBTree是平衡的,也就是说P子树和U子树中黑色的节点应该相同,现在为了解决N与P的颜色问题而直接将P染色成黑色,等价于在P子树中新增了一个黑色节点,破坏了任意路径中黑色节点相同的规则,因此这是不可行的。

    我们再考虑其他方式,首先,P与N是连着的,而我们的目的是在不破坏其他规则的情况下使他们异色,而直接变色已经证明是不可行的了,那我们的思路改变一下,如果让P节点不在处于P子树,也就是说在将P变色的情况下让他升高高度这样在原来P高度及以下的黑色节点个数还是一样的(因为P是红色的,移动了也不会改变原来P子树中的黑色节点个数)。

    因此我们效仿AVL树中的旋转操作,将G进行右旋,3子树并入G的左子树,则发现现在P的高度升高了。在按原定思路,改变P的颜色,现在N与P间已经没有问题了,但G由于降到右子树上,增加了右子树的黑色节点个数,但这很好处理,我们只要将G变为红色就行了。

    情况一:伯父节点为黑色,且为内侧插入

    我们在考虑内侧插入的影响:

    如果是内侧插入,以下图为例:

    直接换色我们已经在上面说过了,这是不可行的,那如果效仿外侧插入,提高P的高度在换色呢?

    这也是不可行的,原因在于插入位置的变化。在上面我们看到,旋转后P的右子树会并入G的左子树上,在上面中,由于P是红色节点,因此它的右子树的根节点一定是黑色的,因此并过去无论G是什么颜色都不会出现红红的情况。

    而现在可以看到,新插入的位置在内侧,且插入节点一定是红色的(如果插入节点为黑色,则相当于增加了一个黑色节点,破坏了黑色节点个数相同的规则),则并入G中后,会使N,G间又出现了同红色,且此时的N相对于G还是内侧插入,则如果仍这样处理N只会在左子树与右子树间跳来跳去而无法真正使红黑树平衡。

    因此我们不能简单的单次旋转就解决问题,但我们发现,如果对P进行左旋,相当于直接演变为上述外侧插入的情况。

    这样就很好处理了,首先将P左旋,化为上述外侧插入的情况,然后将G右旋,变色即可。

    然后我们谈谈伯父节点的颜色问题:

    首先对于伯父节点的颜色,上面的讨论其实已经把伯父节点为黑色的情况讨论了,我们只需要考虑伯父节点为红色的情况。

    伯父节点为红色的处理其实很简单,以下图为例子:

    出现问题在于P,N间呈现了红色同色,而如果我们只要将P与U全换色,然后将G也换色即可(为了维护黑色节点个数的平衡)。

    但这种处理方式也会带来问题,问题在于我们将G的颜色转变为了红色。

    这也就引入了影响因素3),也就是曾祖父节点的问题。

    如果曾祖父节点为黑色,那一切好说,现在RBTree平衡了,但如果曾祖父节点为红色呢?

    我们现在将NP同色的问题转换到了上一层的祖父G与N的曾祖父GG间的红色同色问题了,因此对NG间在进行前面已经说明的解决方式即可。

  • 相关阅读:
    Leecode no.22 括号生成
    修改mysql数据库的时区
    Django 路由层之反向解析
    学习 Django 的几个教程网址
    leetcode周赛 242
    AcWing第二次热身赛
    AcWing夏季每日一题--最长公共子序列
    AcWIng夏季每日一题--序列最大收益
    leetcode周赛 241
    第十二届蓝桥杯C++ B组
  • 原文地址:https://www.cnblogs.com/lxy-xf/p/11369568.html
Copyright © 2020-2023  润新知