红黑树在avl树


Answers:


123

选择红黑树而不是AVL树的主要原因是什么?

无论红黑树AVL树是最常用的平衡二叉搜索树,它们支持插入,删除和查询的保证O(logN) time。但是,两者之间存在以下比较点:

  • AVL树更加严格地平衡,因此提供了更快的查找。因此,对于查找密集型任务,请使用AVL树。
  • 对于插入密集型任务,请使用红黑树。
  • AVL树在每个节点上存储平衡因子。这会占用O(N)额外的空间。但是,如果我们知道将要插入树中的键始终大于零,则可以使用键的符号位来存储红黑树的颜色信息。因此,在这种情况下,红黑树不会占用额外的空间。

红黑树有哪些应用?

红黑树更通用。它们在添加,删除和查找方面表现相对较好,但AVL树的查找速度更快,但添加/删除速度较慢。红黑树用于以下用途:

  • Java :java.util.TreeMapjava.util.TreeSet
  • C ++ STL(在大多数实现中):映射,多图,多集
  • Linux内核:完全公平的调度程序,linux / rbtree.h

43
In general, the rotations for an AVL tree are harder to implement and debug than that for a Red-Black tree.是不正确的。
蒋经国姚明

9
出于趣味,C ++标准不强制要求std:: map朋友使用任何特定结构。这留给实现,尽管libstdc ++和Dinkumware至少使用红黑树,并且看来您在实践中是正确的。
mbozzi

25
存储在AVL树的每个节点中的平衡因子为两位(-1 / 0 / +1)。一棵红黑树在每个节点中存储一位颜色信息。因此,总共两棵树都需要O(N)内存才能获得额外的信息。
Seppo Enarvi

5
“对于插入密集型任务,请使用红黑树。” 为什么?在最坏的情况下,AVL树插入只需要旋转一圈,而红黑树可以插入两圈。
丹尼尔(Daniel)

3
这应该根据Ben Pfaff在2003年对BST性能的分析进行更新-AVL树具有更广泛的用途,并且性能更好。追踪Java,C ++和Linux内核选择较慢实现的确切历史原因将很有趣。
大卫·麦克马纳蒙

16

尝试阅读这篇文章

它提供了关于差异,相似性,性能等的一些很好的见解。

这是文章的引文:

RB树以及AVL树都是自平衡的。它们都提供O(log n)查找和插入性能。

不同之处在于,RB-Trees保证每次插入操作的旋转次数为O(1)。这实际上是在实际实现中牺牲性能的原因。

简化的RB树从概念上讲是2-3个树,而又不承担动态节点结构的开销,从而获得了这一优势。物理上RB树被实现为二叉树,红色/黑色标志模拟2-3行为

就我自己的理解而言,AVL树和RB树在性能方面相差不远。RB树只是B树的一种变体,并且平衡的实现方式不同于AVL树。


1
AFIAK,一个AVL树每次插入也具有O(1)旋转。对于RB树和AVL-一次插入可以旋转1或0。如果发生旋转,算法将停止。如果没有发生,通常情况下,算法会继续从树的底部到根检查/重绘节点。因此,有时旋转O(1)会更好,因为它消除了扫描剩余项O(log(n))的麻烦。由于AVL树平均会进行更多轮换,因此,AVL树通常比RB树2 log(N)具有更好的平衡〜1.44 log(N)。
谢尔盖·尚达

4

多年来,我们对性能差异的了解有所提高,现在,在AVL上使用红黑树的主要原因是无法获得良好的AVL实施,因为它们不太常见,也许是因为它们未包含在CLRS中。

现在,这两棵树都被认为是等级平衡树的形式,但是在现实世界的测试中,红黑树的速度始终降低约20%插入顺序数据后,速度甚至会降低30-40%。

因此,研究过红黑树而不是AVL树的人们倾向于选择红黑树。红黑树的主要用途在Wikipedia条目中有详细介绍。


1
滑稽!在我阅读的文章中,libavl文章似乎说AVL和RB并驾齐驱,而且两者之间的区别显然并不比其他方面更好(哪个更好取决于工作量)。我看不到任何地方声称AVL总体上快20%。
Stefan

3

这里的其他答案很好地总结了RB和AVL树的利弊,但我发现这种区别特别有趣:

AVL树不支持固定的摊销更新成本 [但是红黑树则支持]

资料来源:Mehlhorn&Sanders(2008)(第7.4节)

因此,尽管RB树和AVL树都保证O(log(N))最坏情况下的查找时间,但是插入和删除时,插入或删除节点恢复AVL / RB属性仍可以在O(1)的摊销时间内完成。红黑的树木。


我相信,AVL树插入具有相同/相似的摊销成本,但会产生更好的平衡树(1.44log(N)与2log(N))。同时,AVL树中的删除可能需要更多轮换。恕我直言,这在WAVL en.wikipedia.org/wiki/WAVL_tree中
Sergey Shandar

1

程序员通常不喜欢动态分配内存。Avl树的问题在于,对于“ n”个元素,您需要至少log2(log2(n))...(height-> log2(n))位来存储树的高度!因此,当您处理大量数据时,您无法确定要分配多少位来存储每个节点的高度。

例如,如果您使用4个字节的int(32位)存储高度。最大高度可以是:2 ^ 32,因此可以在树中存储的最大元素数是2 ^(2 ^ 32)-(似乎很大,但是在这个数据时代,我猜没有什么太大的)。因此,如果您超出此限制,则必须动态分配更多空间来存储高度。

这是我大学的教授提出的答案,对我来说似乎很合理!希望我有道理。

编辑:与红黑树相比,AVL树更加平衡,但是它们可能会在插入和删除过程中引起更多旋转。因此,如果您的应用程序涉及许多频繁的插入和删除操作,则应首选Red Black树。而且,如果插入和删除操作的频率较低,而搜索操作的频率较高,则AVL树应优先于Red Black Tree。-来源GEEKSFORGEEKS.ORG


1
我会说这很有趣但不切实际。在最紧凑的情况下,确实要选择最有效的位数来分配高度将是一项艰巨的任务,但实际上,任何小于一个字节的剩余空间肯定会被闲置,而剩下的任何空间在4甚至8字节空间中,几乎肯定会不使用。出于性能方面的考虑,内存不会分配为未对齐状态,从而大大超过了回收少量空间的好处。指向子代的指针和该值占用24个字节;另外8个几乎没有实际成本。
Mumbleskates

4
you need need atleast log2(log2(n))...(height->log2(n)) bits to store the height of [an AVL] tree我不需要AVL树中任何节点的高度来实现它。你娘家一个比特的额外信息为每个节点(我就是最大的(与该最高兄弟子树))); 如AV&L所示,拥有两个额外的位(子级较高,左和右较高)比常规方式更方便和方便
。– greybeard

4
2 ^(2 ^ 32)个元素很多……就像您可以存储整个宇宙中的每个分子,以及每个可能的分子对,以及每个可能的三元组,甚至还没有开始接近在那个数字的立方根除以一百亿五千万的一小部分内,
分号

4
这是非常误导的。首先,我们不需要将高度存储在AVL树的节点中。其次,即使我们做到了,即使典型的可用内存量每年增加一倍,我们仍然有40亿年的时间,直到树的高度超过可以以32位存储的高度。
加沙

3
2 ^(2 ^ 32)对象简直荒唐可笑,绝对比我们现在可以想象的任何一台计算机所拥有的更多。我们处在2 ^ 40左右。再次检查您的数学能力。
Stefan Reich

-1

重新平衡AVL树应满足以下属性。(Wiki参考-AVL树

在AVL树中,任何节点的两个子树的高度最多相差1个。如果它们之间的任何时间差超过一个,则将进行重新平衡以恢复此属性。

因此,这意味着AVL树的整体高度不会发疯,即使用AVL树进行查找会更好。并且由于要进行附加的操作(旋转)以不使高度变差,因此树修改操作可能会有点昂贵。


提到过很多其他地方,但是答案不是很好的原因是AVL树和RB树有效地保持了极其相似的约束-RB树不会超过所需高度的2.0倍,而对于AVL树而言,约1.44。因此,AVL树轮换的频率略高,但是每轮的成本基本相同。它并不昂贵。
Mumbleskates
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.