Algorithm 将AVL树转换为红黑树

Algorithm 将AVL树转换为红黑树,algorithm,data-structures,tree,avl-tree,red-black-tree,Algorithm,Data Structures,Tree,Avl Tree,Red Black Tree,我在某个地方读到这句话,任何AVL树T的节点都可以被涂成“红色”和“黑色”,这样T就变成了红黑树 这句话似乎很有说服力,但我不明白如何正式证明这句话 根据wiki,红黑树应满足以下五个属性: a、 节点为红色或黑色 b、 根是黑色的。这条规则有时被省略。因为根总是可以从红色变为黑色,但不一定相反 c。所有的叶子(无)都是黑色的 d、 如果节点为红色,则其两个子节点均为黑色 e、 从给定节点到其任何子代NIL节点的每条路径都包含相同数量的黑色节点 这四个条件很简单,我被困在了如何证明语句5的问题上

我在某个地方读到这句话,任何AVL树T的节点都可以被涂成“红色”和“黑色”,这样T就变成了红黑树

这句话似乎很有说服力,但我不明白如何正式证明这句话

根据wiki,红黑树应满足以下五个属性:

a、 节点为红色或黑色

b、 根是黑色的。这条规则有时被省略。因为根总是可以从红色变为黑色,但不一定相反

c。所有的叶子(无)都是黑色的

d、 如果节点为红色,则其两个子节点均为黑色

e、 从给定节点到其任何子代NIL节点的每条路径都包含相同数量的黑色节点

这四个条件很简单,我被困在了如何证明语句5的问题上。好吧,5的简单例子是一个单一的后代,它是一片叶子,由3变黑

否则,子体节点为红色,需要有2个黑色的子体乘以#4

然后这两种情况递归地应用于每个节点,因此在每个路径中始终有相同数量的黑色节点

首先,定义树的高度(用于AVL树):

另外,将路径的深度(如用于红黑树,路径是从给定节点到某个叶的子体链)定义为路径上的黑色节点数


正如您所指出的,将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)
黑色(x):
x、 颜色=黑色;
如果x是一个节点:
彩色儿童(x左,x右)
红色(x)://高度(x)必须均匀
x、 颜色=红色
color\u子节点(x.left,x.right)//x将始终是一个节点
儿童(a、b)的颜色:
如果高度(a)<高度(b)或高度(a)为奇数:
黑色(a)
其他:
红色(a)
如果高度(b)<高度(a)或高度(b)为奇数:
黑色(b)
其他:
红色(b)
对于AVL树的根,请调用
color\u black(root)
以确保b。 请注意,树是按深度优先顺序遍历的,这也确保了

请注意,红色节点的高度都相等。叶子的高度为1,因此它们将被染成黑色,以确保c。红色节点的子节点将具有奇数高度或比其兄弟节点短,并将标记为黑色,以确保d

最后,展示e。(从根开始的所有路径具有相同的深度), 使用
n>=1的归纳法证明:

  • 对于奇数
    高度=2*n-1
    • color_black()创建一棵红黑树,深度
      n
  • 对于偶数
    高度=2*n
    • color_red()将所有路径设置为深度
      n
    • color_black()创建一棵红黑树,深度
      n+1
基本情况,对于
n=1

  • 对于奇数
    高度=1
    ,树是一片叶子;
    • color_black()将叶子设置为黑色;唯一路径的深度为1
  • 对于偶数
    height=2
    ,根是一个节点,两个子节点都是叶子,上面标记为黑色;
    • color_red()将节点设置为红色;两条路径的深度均为1
    • color_black()将节点设置为黑色;两条路径都有深度2
归纳步骤是我们使用AVL不变量的地方:兄弟树的高度最多可以相差1。对于具有给定高度的节点

  • 子类A:两个子树都是
    (高度-1)
  • 子类B:一个子树是
    (高度-1)
    ,另一个子树是
    (高度-2)
归纳步骤:假设假设
n
的假设为真,则表明它适用于
n+1

对于奇数
高度=2*(n+1)-1=2*n+1

  • 子类A:两个子树的高度均为偶数
    2*n
    • color\u children()为两个子项调用color\u red()
    • 通过归纳假设,两个孩子都有深度
      n
    • 对于父级,color_black()添加一个黑色节点,用于深度
      n+1
  • 子类B:子树具有高度
    2*n
    2*n-1
    • color_children()分别调用color_red()和color_black()
    • 对于均匀高度
      2*n
      ,颜色_red()产生深度
      n
      (感应高度)
    • 对于奇数高度
      2*n-1
      ,黑色()产生深度
      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
      ,黑色()产生深度
      n+1
      (见上文)
    • 对于均匀高度
      2*n
      ,黑色()产生深度
      n+1
      (感应高度)
    • 帕伦
      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)