我正在阅读Eternally confuzzled的红黑树教程。
在作者解释从RB树中删除节点的部分中,作者要求读者将解释作为练习:
在看到图表后,通过固定黑色高度恢复平衡是显而易见的,但令人困惑的是为什么2变为红色。好吧,红色必须到达某个地方,否则树的黑色高度会受到影响,我们确定的唯一已知节点可以变成红色就是那个特定的孩子。我不太清楚我是如何找出红色兄弟姐妹的情况,但我有理由相信酒精含蓄。 :-) 第二个红色兄弟案例着眼于兄弟姐妹的内心孩子。这个孩子不能是一个空指针(练习:为什么?),所以我们只测试它的一个孩子,并根据哪个是红色来行动。如果外部孩子是红色的,我们执行双重旋转,为新的父母黑色,右边的孩子为黑色,左边的孩子为红色:
作者如何得出结论,兄弟姐妹的内心孩子不能成为空指针?为什么那个特殊的孩子不能是空指针?为什么不是另一个孩子?
答案 0 :(得分:2)
如果是null
,那么该树将无效,因为不会满足此property:
每个红色节点必须有两个黑色子节点。
为什么这个属性很重要?
如果我们忽略此属性,我们可以得到一个有效的红黑树,如下所示:
B
\
R
\
B
\
R
\
B
\
...
这当然是二进制搜索树的绝对更糟糕的情况。它基本上使它成为一个链表 - 任何操作都需要O(n)
。
答案 1 :(得分:0)
我也同样怀疑@Tipps提出的问题。我的理解是作者没有提到属性"每个红色节点必须有两个黑色子节点"在写作中。这篇文章推断出RB-Tree必须持有的属性,因为它是从B树中诞生的。
也许案件本身并不存在?我在网上使用免费的模拟器来验证这样一个单一的黑孩子红色父母案例不应该理想地存在于有效的RB树中
"这些只是兄弟姐妹是黑人的情况。如果兄弟姐妹是红色的,那就更糟了。但是我也有好消息。除了作为一种求知欲之外,以下讨论并不重要。" - 来自同一篇文章
如果您观察到RB-Tree重新平衡代码,该代码取出了红色兄弟情况,您会发现没有特殊的案例处理。虽然我仍然想知道为什么:
if ( new_root )
root = p;
else
root->link[dir] = p;
是必要的吗?单个轮换是否已经处理了此更新?