【问题标题】:Explain black height algorithm in Red-Black tree解释红黑树中的黑色高度算法
【发布时间】:2017-11-23 22:32:18
【问题描述】:

我一直在寻找一种方法来检查红黑树的这个属性:“从节点到空节点的每条路径都必须包含相同数量的黑色节点”。

大多数赞成的答案如下所示:

// Return the black-height of node x.  If its subtrees do not have
// the same black-height, call attention to it.

private int checkBlackHeight(Node x) {
if (x == null)
  return 0;
else {
  int leftBlackHeight = checkBlackHeight(x.left) +
      (x.left.isBlack() ? 1 : 0);
  int rightBlackHeight = checkBlackHeight(x.right) +
      (x.right.isBlack() ? 1 : 0);
  if (leftBlackHeight != rightBlackHeight)
      complain("blackheight error", x);
  return leftBlackHeight;
  }
}

我感到困惑的是,这段代码不是只检查树下最左边和最右边的路径吗?它如何检查内部路径? 例如在下面的树中,它应该检查路径 11-9-8-.. 和 11-16-18... 但它是否检查 11-16-13-(一些内部节点)-...

         11
       /    \
      9     16
     / \    /  \
    8  10  13   18
   /\  /\  /\   / \

提前谢谢你!

【问题讨论】:

    标签: algorithm data-structures tree


    【解决方案1】:

    代码最终检查所有路径的原因,至少我理解它的方式是因为该函数同时具有“向左”和“向右”指令,因此对于每个节点,左右都进行了探索,因此所有路径都将被覆盖。此外,判断左节点是否为黑色只是判断是否在黑色路径长度上加一(对于每个递归调用)。

    【讨论】:

    • 我有点明白你的意思。您能否再解释一下,例如在这一行中:int leftBlackHeight = checkBlackHeight(x.left) + (x.left.isBlack() ? 1 : 0); 函数 checkBlackHeight 似乎递归地调用 x 的左子节点,直到它到达一个空节点。在此递归调用完成之前,不会执行下一行。我如何想象它就像从根部开始沿着最左边的路径向下移动的波浪。同样,下一行在最右边的路径下发送另一个“波浪”。它在什么时候转移并进入内部?
    • 首先,它沿着最左边的路径。在它完成该路径后,由于该函数直到右调用也执行后才完成,所以最深的左子节点也执行其右侧调用(最终返回 0 直到右子节点不为空)。在您给出的示例中,执行下降到 8 后,它将转到 10,完成从 9 开始的递归调用,然后最终到达 11 的右侧递归调用。
    • @Van,这个答案是正确的。我认为您需要稍微了解一下递归。
    • @kylew 你是绝对正确的。我把它画出来了,它更容易理解。非常感谢凯尔!
    • @ShihabShahriar 我认为我的问题不是递归。它实际上是树遍历。这很像一个前序树遍历过程! Youtube 教程很有帮助:youtube.com/watch?v=gm8DUJJhmY4。不过还是谢谢:)