在红黑树中,自上而下删除比自下而上删除更快,更节省空间吗?

时间:2008-12-13 01:15:40

标签: data-structures red-black-tree

每页http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx “自上而下删除”是红黑树节点移除的实现,其通过向下推动树中的红色节点来主动平衡树,使得正被移除的叶节点保证是红色的。由于叶节点保证是红色的,因此您不必担心重新平衡树,因为删除红叶节点不会违反任何规则,并且您不必执行任何其他操作即可平衡并恢复红黑。

“自下而上删除”涉及在树下进行常规二进制搜索以找到要删除的节点,在叶节点中交换(如果找到的节点不是叶节点),然后恢复红色 - 黑树属性通过攀爬树而修复红黑规则违规。

自上而下删除是否会最大限度地减少重新平衡操作的次数?自上而下的删除是否有可能主动进行过多的重新着色和重新平衡?

这种情况如何:(x)表示红色节点

               8
         _____/ \____
        /            \
       4              12
     /   \          /    \
   2       6      10      14
  / \     / \    /  \    /  \
 1   3   5   7   9  11  13  15
                             \
                            (16)

如果我想删除16,则自下而上的删除不会进行任何重新平衡,但是在发现不需要重新着色操作之前,自上而下的删除会一直重新着色节点:

迭代1:

              (8)
         _____/ \____
        /            \
       4              12
     /   \          /    \
   2       6      10      14
  / \     / \    /  \    /  \
 1   3   5   7   9  11  13  15
                             \
                            (16)

迭代2:

               8
         _____/ \____
        /            \
      (4)            (12)
     /   \          /    \
   2       6      10      14
  / \     / \    /  \    /  \
 1   3   5   7   9  11  13  15
                             \
                            (16)

迭代3:

               8
         _____/ \____
        /            \
      (4)             12
     /   \          /    \
   2       6     (10)    (14)
  / \     / \    /  \    /  \
 1   3   5   7   9  11  13  15
                             \
                            (16)

然后在迭代4中,您发现您不需要按下,因为16已经是红色。那么自上而下的删除更有时间和空间效率吗?

2 个答案:

答案 0 :(得分:4)

从我收集的内容:“自上而下删除”避免在操作期间多次遍历路径中的同一节点。因此,考虑到从根到给定节点的简单路径,如果你要对那个路径中的节点做一些事情,为什么不在下行呢?它避免了不止一次遍历路径的某些部分。因此,这节省了时间。

类似的原则用于2-3-4树中的多个操作(包括插入)(a,b-tree的特殊子例)

自上而下删除是否会最小化重新平衡操作的次数?

认为,在一般情况下,确实如此。因为通过几次重新平衡操作,你可以更容易地插入一些东西。

自上而下的删除是否有可能主动进行过多的重新着色和重新平衡?

可能,但这取决于数据集。但是,如上所述。这可以减少整体重新着色和重新平衡的次数。

答案 1 :(得分:3)

自上而下的空间比自下而上更有效吗?

总之,是的。在eternally confuzzled处呈现的自顶向下算法不需要节点上的父指针。自下而上的算法在时间和空间之间进行权衡:在插入和删除后重新平衡时,父指针允许一些短路。

例如,红黑树的OpenJdk-7's implementation有父指针,允许它选择删除后是否需要重新平衡(例如在你的场景中)。

自上而下的时间比自下而上更有效吗?

通常,是:自上而下的方法每次操作只能遍历一次树,而底层方法每次操作必须遍历树两次。正如我之前提到的,自下而上的方法可以通过使用父指针来缩短一些时间。但绝对不是每次都遍历整个树。

两种实现也可以选择利用threading来改进迭代整个树所需的时间或空间。这需要每个节点一两个标志的开销。这也可以使用父指针实现,但效率不高。 NB:线程链接表示线程不如父指针有效,但这仅适用于自下而上的树(本书涵盖的内容)。

轶事证据

回到大学时,我们在C ++中实现了eternally confuzzled's top-down red-black tree,并与我们STL(自下而上)的std :: map实现进行了比较。我们自上而下的方法肯定更快 - 我想说它在所有变异操作上都快2倍。搜索也更快,但我不能说这是由于更平衡的树还是更复杂的代码。

可悲的是,我不再拥有代码,也没有代码。