红黑树和AVL树的区别

Posted

技术标签:

【中文标题】红黑树和AVL树的区别【英文标题】:Difference between red-black trees and AVL trees 【发布时间】:2013-04-21 21:16:29 【问题描述】:

谁能解释一下这两种数据结构之间的主要区别是什么?我一直试图在网上找到一个突出差异/相似之处的资源,但我没有发现任何信息量太大的东西。在什么情况下,一种会比另一种更受欢迎?哪些实际情况会使一个比另一个“更好”使用?

【问题讨论】:

【参考方案1】:

对于小数据

插入:RB树和avl树具有恒定的最大旋转次数,但RB树会更快,因为平均而言RB树使用较少的旋转。

查找:AVL 树更快,因为 AVL 树的深度更小。

delete:RB 树的最大旋转次数是恒定的,但 AVL 树的最坏旋转次数可能为 O(log N)。并且平均而言,RB树的旋转次数也更少,因此RB树更快。

对于大数据

插入:AVL 树更快。因为您需要在插入之前查找特定节点。当您拥有更多数据时,查找特定节点的时间差异与 O(log N) 成正比。但是 AVL 树和 RB 树在最坏的情况下仍然只需要恒定的旋转次数。因此,瓶颈将成为您查找该特定节点的时间。

查找:AVL 树更快。 (与小数据情况相同)

delete:平均而言,AVL 树更快,但在最坏的情况下,RB 树更快。因为你还需要在移除之前查找一个非常深的节点进行交换(类似于插入的原因)。平均而言,两棵树都有恒定的旋转次数。但是RB树有一个固定的旋转上限。

【讨论】:

这似乎意味着 AVL 树几乎总是首选处理大量数据。它是如何在 Java 和 C++ STL 中使用的? ***.com/questions/3901182/… 你需要有一定的数据量(例如100万)才能使AVL树在插入/删除的情况下比RB树更好,这实际上取决于你如何实现它。即使数据量较少,智能 AVL 实现也可以击败 std::map。例如,如果 parent->height 大于 5,则不需要检查 child 和 grandchild 是否为 null。 这是一个很好的分析,应该是任何类型的数据结构比较的典范。比公认的答案更好 作为“小数据”的简短摘要,我从中得出的结论是:AVL 在前期做了更多的工作并且更严格(写入/旋转),以提高以后的性能(读取)。随着数据的增长,阅读变得更加重要,因为你会读的比写的多(与搜索相比,旋转是微不足道的)。所以 AVL 在所有方面都获胜,因为它针对阅读进行了优化。【参考方案2】:

RedBlack 树的旋转较少这一事实可以使它们在插入/删除时更快,但是 .... 。由于它们通常更深一些,因此它们在插入和删除时也可能更慢。每次从树中的一个级别转到下一个级别时,都会发生很大的变化,即请求的信息不在缓存中,必须从 RAM 中检索。 因此,由于它必须更深入地导航,因此必须更频繁地更新其缓存,因此可能已经失去了更少旋转所获得的时间。是否能够从缓存中操作会产生很大的不同。如果相关信息在缓存中,那么您可以在需要导航一个附加级别并且下一级信息不在缓存中的时间内进行多次旋转操作。 因此,如果 RedBlack 理论上更快,仅查看所需的操作,实际上它可能会更慢,因为缓存未命中。

【讨论】:

【参考方案3】:

要了解 AVL 树的工作原理,this 交互式可视化会有所帮助。

AVL 和 RedBlack 树是高度平衡的树数据结构。它们非常相似,真正的区别在于在任何添加/删除操作时执行的旋转操作次数 - 在 AVL 的情况下更高,以保持整体更均匀的平衡。

两种实现都可以缩放为O(lg N),其中 N 是叶子的数量,但实际上 AVL 树在查找密集型任务上更快:利用更好的平衡,树的遍历平均更短。另一方面,在插入和删除方面,AVL 树更慢:需要更多的旋转次数才能在修改时正确地重新平衡数据结构。

对于通用实现(即先验,尚不清楚查找是否是主要的操作),红黑树是首选:它们更容易实现,并且在常见情况下更快 - 无论数据结构被修改为经常搜索。例如,Java 中的TreeMapTreeSet 使用了一个支持红黑树。

【讨论】:

【参考方案4】:

总而言之:AvlTrees 比 RedBlackTrees 更平衡。两棵树的查找、插入和删除总共需要 O(log n) 时间,但对于插入和删除,前者需要 O(log n) 次旋转,而后者只需要 O(1) 次旋转。

由于旋转意味着写入内存,而写入内存的成本很高,因此 RedBlackTrees 在实践中比 AvlTrees 更新速度更快

【讨论】:

【参考方案5】:

树木的最大高度对于保持平衡至关重要。对于 AVL,它几乎等于 1.44 * log(n),但对于 RB 树,它是 2 * log(n)。因此我们可以得出结论,当问题是搜索激励时,最好使用 AVL。重要的是 AVL 和 RB 树的另一个问题。 RB树在面对随机插入时优于AVL,旋转成本较低,但AVL适合插入升序或降序数据。所以如果问题是插入激励,我们可以使用RB树。

【讨论】:

【参考方案6】:

AVL 树通常与红黑树进行比较,因为它们都支持相同的操作集并且花费O(log n) 时间进行基本操作。对于查找密集型应用程序,AVL 树比红黑树更快,因为它们更加严格地平衡。与红黑树类似,AVL 树是高度平衡的。对于任何 μ ≤ ½,两者通常都不是重量平衡的,也不是 μ 平衡的;也就是说,兄弟节点的后代数量可能大不相同。

来自AVL Trees 上的***文章

【讨论】:

【参考方案7】:

AVL 树比红黑树保持更严格的平衡。在 AVL 树中从根到最深叶的路径最多为 ~1.44 lg(n+2),而在红黑树中最多为 ~2 lg (n+1)。

因此,在 AVL 树中的查找通常更快,但由于更多的旋转操作,这是以更慢的插入和删除为代价的。因此,如果您希望查找次数支配树的更新次数,请使用 AVL 树。

【讨论】:

要求更好地理解概念。 avl 树和红黑树每次插入最多有两次旋转。那么,你怎么能说 AVL 树很慢呢?提前致谢! @larsmans!性能差异是否如此之大,以至于创造了一个新概念? @Shashwat 我不明白你的意思。新概念? @larsmans!我的意思是当我们有 AVL 树的时候,为什么我们会有红黑树的概念如此著名,尽管它们的插入、删除和更新性能只有细微的差别。红黑树与AVL树有什么不同吗? 维护它们的算法不同,因此它们得到不同的名称。 AFAIK,它们支持具有相同大 O 时间界限的相同操作集。【参考方案8】:

从我所看到的看来,AVL 树似乎会根据需要进行尽可能多的旋转(有时会向上递归)以获得所需的 AVL 树高度(Log n)。这使它更加严格地平衡。

对于红黑树,您需要 5 套规则来确保在插入和移除过程中保持不变,您可以在此处找到 http://en.wikipedia.org/wiki/Red-black_tree。

对红黑树可能有帮助的主要一点是,如果叔叔是红色的,那么根据这五个规则,您可以递归地为树着色直到根。如果叔叔是黑人,您最多需要进行两次旋转来解决您遇到的任何问题,但是在那一两次旋转之后,您就完成了。打包并说晚安,因为这就是您需要做的操作的结束。

最大的规则是数字 5... '从给定节点到其任何后代叶子的每条简单路径都包含相同数量的黑色节点'。

这将导致您需要使树工作的大部分旋转,并导致树不会失去平衡。

【讨论】:

【参考方案9】:

引自:Difference between AVL and Red-Black Trees

RB-Tree 和 AVL 树一样是自平衡的。它们都提供 O(log n) 的查找和插入性能。 不同之处在于 RB-Trees 保证每个插入操作的 O(1) 次旋转。这就是在实际实现中实际成本性能的原因。 简化后,RB-Trees 从概念上是 2-3 棵树获得了这一优势,而无需携带动态节点结构的开销。物理上 RB-Trees 实现为二叉树,红/黑标志模拟 2-3 行为。

根据定义,因此每个 AVL 都是 Red-Black 的子集。应该能够为任何 AVL 树着色,无需重组或旋转,将其转换为红黑树。

【讨论】:

以上是关于红黑树和AVL树的区别的主要内容,如果未能解决你的问题,请参考以下文章

详解 AVL 树和红黑树的区别

红黑树插入删除详细步骤动画演示与AVL树的区别

Linux内核之于红黑树and AVL树

说一下B+tree和二叉搜索树的区别?说一下二叉搜索树和AVL树红黑树之间的差别

AVL树和红黑树的模拟实现

红黑树基本特点,及其建立——转