鉴于关于这个话题有很多可以说的,我会尽量贴近你的问题,但如果我错过了重要的事情,请告诉我。
app 到底在做什么?
您是正确的,app 在下降的过程中打破了红色的不变量而不是黑色的不变量,并在返回的过程中修复了这个问题。
它app结束或合并两个服从顺序属性的子树,黑色不变量,红色不变量,并且具有相同的黑色深度成一棵也服从顺序属性,黑色不变量的新树,和红色不变量。一个值得注意的例外是根或app rb1 rb2 有时是红色的并且有两个红色子树。这种树被称为“红外线”。这在delete 中处理,只需将此行中的根设置为黑色。
case del t of {T _ a y b -> T B a y b; _ -> E}
Claim 1 (Order property) 如果输入 rb1 和 rb2 分别服从 order 属性(左子树 rb1 中的最大值为小于rb2 中的最小值,则app rb1 rb2 也服从 order 属性。
这个很容易证明。实际上,您甚至可以在查看代码时看到它 - as 始终位于 bs 或 b's 的左侧,它们始终位于 cs 的左侧或c's,它始终位于ds 的左侧。并且 b's 和 c's 也遵守此属性,因为它们是递归调用 app 的结果,子树 b 和 c 满足声明。
声明 2(红色不变量)如果输入 rb1 和 rb2 服从红色不变量(如果一个节点是红色的,那么它的两个子节点都是黑色的),那么所有的app rb1 rb2 中的节点,可能除了根。但是,只有当其参数之一具有红色根时,该根才能“红外”。
证明证明是通过模式分支。
声明 3(黑色不变量),如果输入 rb1 和 rb2 服从黑色不变量(从根到叶子的任何路径在途中都有相同数量的黑色节点)并且具有相同的黑色深度,app rb1 rb2 也遵循黑色不变量并且具有相同的黑色深度。
证明证明是通过模式分支。
- 对于
app E x = x 和 app x E = x 的情况,声明是微不足道的
- 对于
app (T R a x b) (T R c y d),我们知道因为T R a x b 和T R c y d 具有相同的黑色深度,所以它们的子树a、b、c 和d 也是如此。根据声明(请记住,这是归纳!)app b c 也将遵守黑色不变量并具有相同的黑色深度。现在,我们将证明分支到case app b c of ...
- 如果
app b c 与T R b' z c' 匹配,则为红色,其子树b' 和c' 将具有与app b c(本身)相同的黑色深度,而a 又具有与a 相同的黑色深度和d,所以T R (T R a x b') z (T R c' y d) 遵循黑色不变量,并且具有与其输入相同的黑色深度。
- 否则,
app b c 产生了一个黑色节点 bc,但同样,该节点具有与 a 和 d 相同的黑色深度,所以 T R a x (T R bc y d) 作为一个整体仍然服从黑色不变量并且具有相同的黑色深度作为其输入。
- 对于
app (T B a x b) (T B c y d),我们再次立即知道子树a、b、c 和d 都具有与app b c 相同的黑色深度。和以前一样,我们在case app b c of ... 上分支我们的证明
- 如果
app b c是T R b' z c'形式的红色节点,我们再次得到b'、c'、a和d具有相同的黑色深度,所以T R (T B a x b') z (T B c' y d)也具有相同的黑色深度
- 现在,如果
bc 变成黑色,我们应用与之前声明相同的推理来确定输出 balleft a x (T B bc y d) 实际上具有以下形式
-
T R (T B .. ..) (T B bc y d) 其中(T B .. ..) 只是将a 重新着色为黑色,因此整个树将满足黑色不变量,并且黑色深度比a、b、c 或@987654436 中的任何一个都多一个@,即与输入 T B a x b 和 T B c y d) 相同的黑色深度。
-
balance a x (T R bc y d) 和 balance 保持黑色不变。
- 对于
app a (T R b x c) 或app (T R a x b) c,我们知道a、b 和c 都具有相同的黑色深度,因此,这意味着app a b 和app b c 具有相同的黑色-depth,这意味着T R (app a b) x c 和T R (app a b) x c 也具有相同的黑色深度
为什么这么快?
我的球拍有点生锈,所以我对此没有很好的答案。一般来说,app 允许您分两步完成所有操作,从而快速删除:您进入目标站点,然后继续向下合并子树,然后在进行过程中重新修复不变量,所有通往根的路。
在您引用的paper 中,一旦您到达目标站点,您就会调用min/delete(我认为这是关键区别——否则旋转看起来非常相似),它将递归调用自身来查找元素在子树中,您可以插入目标站点以及取出该元素后子树的状态。我相信最后一部分会损害该实施的性能。