首先,定义树的高度(用于 AVL 树):
height(leaf) = 1
height(node) = 1 + max(height(node.left), height(node.right))
此外,定义路径的深度(如用于红黑树,路径是从给定节点到某个叶子的后代链)到是路径上的黑色节点数。
正如您所指出的,将 AVL 树着色为红黑树的棘手之处在于确保每条路径都具有相同的深度。您将需要使用 AVL 不变量:任何给定节点的子树的高度最多只能相差一个。
直观地说,诀窍是使用一种着色算法,其深度对于给定的高度是可预测的,这样您就不需要进行任何进一步的全局协调。然后,您可以局部调整着色,以确保每个节点的子节点具有相同的深度;这是可能的,因为 AVL 条件严格限制了它们的高度差。
这种树着色算法可以解决问题:
color_black(x):
x.color = black;
if x is a node:
color_children(x.left, x.right)
color_red(x): // height(x) must be even
x.color = red
color_children(x.left, x.right) // x will always be a node
color_children(a,b):
if height(a) < height(b) or height(a) is odd:
color_black(a)
else:
color_red(a)
if height(b) < height(a) or height(b) is odd:
color_black(b)
else:
color_red(b)
对于 AVL 树的根,调用color_black(root) 以确保 b.
请注意,树是按深度优先顺序遍历的,同时也确保了一个。
请注意,红色节点的高度都是均匀的。叶子的高度为 1,因此它们将被着色为黑色,确保 c。红色节点的子节点要么有奇数高度,要么比他们的兄弟节点矮,并且将被标记为黑色,以确保 d。
最后,显示 e。 (来自根的所有路径都具有相同的深度),
在n>=1 上使用归纳法来证明:
- 为奇数
height = 2*n-1,
- color_black() 创建一个红黑树,深度为
n
- 即使
height = 2*n,
- color_red() 将所有路径设置为深度
n
- color_black() 创建深度为
n+1 的红黑树
基本情况,对于n = 1:
- 对于奇数
height = 1,树是叶子;
- color_black() 将叶子设置为黑色;唯一路径的深度为 1,
- 对于偶
height = 2,根是一个节点,两个孩子都是叶子,如上标记为黑色;
- color_red() 将节点设置为红色;两条路径的深度均为 1
- color_black() 将节点设置为黑色;两条路径的深度均为 2
归纳步骤是我们使用 AVL 不变量的地方:兄弟树的高度最多可以相差 1。对于具有给定 height 的节点:
- 子案例A:两个子树都是
(height-1)
- 子案例B:一个子树是
(height-1),另一个是(height-2)
归纳步骤:假设n 为真,证明它适用于n+1:
对于奇数height = 2*(n+1)-1 = 2*n+1,
- 子案例A:两个子树的高度相等
2*n
- color_children() 为两个孩子调用 color_red(),
- 通过归纳假设,两个孩子都有深度
n
- 对于父节点,color_black() 添加一个黑色节点,对于深度
n+1
- 子案例 B:子树的高度为
2*n 和 2*n-1
- color_children() 分别调用 color_red() 和 color_black();
- 对于均匀高度
2*n,color_red() 产生深度n(感应炒作)
- 对于奇数高度
2*n-1,color_black() 产生深度n(感应炒作)
- 对于父节点,color_black() 添加一个黑色节点,对于深度
n+1
甚至height = 2*(n+1) = 2*n + 2
- 子案例A:两个子树的高度都是奇数
2*n+1 = 2*(n+1)-1
- color_children() 为两个孩子调用 color_black() 以获取深度
n+1
- 从上面奇高的情况下,两个孩子都有深度
n+1
- 对于父节点,color_red() 添加一个红色节点,深度不变
n+1
- 对于父节点,color_black() 添加一个黑色节点,对于深度
n+2
- 子案例 B:子树的高度为
2*n+1 = 2*(n+1)-1 和 2*n
- color_children() 为两个孩子调用 color_black() 以获取深度
n+1
- 对于奇数高度
2*n+1,color_black() 产生深度n+1(见上文)
- 对于均匀高度
2*n,color_black() 产生深度n+1(感应炒作)
- 对于父节点,color_red() 添加一个红色节点,对于深度
n+1
- 对于父节点,color_black() 添加一个黑色节点,对于深度
n+2 = (n+1)+1