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

Posted

技术标签:

【中文标题】在红黑树中,自上而下的删除是不是比自下而上的删除更快、更节省空间?【英文标题】:In red-black trees is top-down deletion faster and more space efficient than bottom-up deletion?在红黑树中,自上而下的删除是否比自下而上的删除更快、更节省空间? 【发布时间】:2010-09-26 17:59:09 【问题描述】:

每页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 已经是红色的。那么自上而下的删除是否更节省时间和空间?

【问题讨论】:

【参考方案1】:

据我所知:“自上而下删除”避免了在操作过程中多次遍历路径中的同一节点。所以,给定从根到给定节点的简单路径,如果无论如何你要对该路径中的节点做一些事情,为什么不直接在向下的路上做呢?它避免了多次遍历路径的某些部分。因此,这样可以节省时间。

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

自上而下的删除是否最大限度地减少了重新平衡操作的次数?

认为,在一般情况下,确实如此。因为您可以通过很少的重新平衡操作使之后插入一些东西变得更容易。

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

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

【讨论】:

你能看看我的 RedBlackTree 删除方法吗? ***.com/questions/28705454/…【参考方案2】:

自上而下是否比自下而上更空间

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

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

自上而下是否比自下而上更时间

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

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

轶事证据

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

遗憾的是,我不再有代码,也没有文章。

【讨论】:

感谢您回答我的赏金呼吁,让更多人关注这个问题! Eternally confuzzled 的 bottom-up 插入和删除算法也无需父指针即可管理,正是因为它们在向下递归时存储在堆栈中。当然,堆栈使用是不同的空间使用,即使没有父节点的节点更轻。 也有相反的证据。例如:gedare-csphd.blogspot.cz/2011/08/… 他声称他发现自下而上的方法更快。 很高兴知道!这让我相信我的实现比 std::map 更快,因为代码要简单得多。 你们能看看我在 RedBlackTree 中的 remove 方法吗? ***.com/questions/28705454/…

以上是关于在红黑树中,自上而下的删除是不是比自下而上的删除更快、更节省空间?的主要内容,如果未能解决你的问题,请参考以下文章

红黑树

红黑树

红黑树是怎么来的

关于红黑树的左旋右旋

红黑树删除操作

红黑树(更高级的二叉查找树)