何时选择RB树,B树或AVL树?


88

作为程序员,我什么时候应该考虑使用RB树,B树或AVL树?在决定选择之前,需要考虑哪些关键点?

有人可以为每种树形结构解释一个场景,为什么参考关键点选择它而不是其他树形结构?


10
好吧,我一个人很欣赏这个问题-目前提供了fastutil IntAVLTreeSet与IntRBTreeSet的选择。

Answers:


113

用少许盐食用:

B树,当您管理成千上万的项目并从磁盘或某些慢速存储介质分页时。

RB树在您执行相当频繁的插入,删除和检索时。

相对于检索而言,插入和删除很少的AVL树。


34
只是要增加一些细节:B树的子级数目可以变化,这使其可以保存许多记录,但仍保留高度较短的树。RB树在重新平衡方面没有较严格的规则,它使插入/删除操作比AVL树更快。相反,AVL树更严格地平衡,因此查找比RB树更快。
pschang 2012年

RB树在重新平衡方面也具有更好的性能O(1),这使其更适合于具有回滚和前滚功能的持久数据结构。

20

我认为B +树即使在主内存中也是一个很好的通用有序容器数据结构。即使虚拟内存不是问题,缓存友好性通常也很重要,并且B +树特别适合顺序访问-与链接列表具有相同的渐近性能,但缓存友好性接近简单数组。所有这些和O(log n)搜索,插入和删除。

但是,B +树确实存在问题-例如,当您执行插入/删除操作时,项目在节点内到处移动,会使指向这些项目的指针无效。我有一个执行“光标维护”的容器库-游标将自身附加到当前在链接列表中引用的叶节点上,因此它们可以自动修复或失效。由于很少有一个或两个游标,所以它可以很好地工作-但这同样是额外的工作。

另一件事是,B +树本质上就是这样。我猜您可以根据是否需要剥离或重新创建非叶节点,但是使用二叉树节点,您将获得更大的灵活性。可以将二叉树转换为链表,而无需复制节点即可返回-您只需更改指针,然后记住您现在将其视为不同的数据结构即可。除其他外,这意味着您可以很容易地将树O(n)合并-将两棵树都转换为列表,将它们合并,然后再转换回树。

另一件事是内存分配和释放。在二叉树中,可以将其与算法分开-用户可以创建一个节点,然后调用插入算法,删除操作可以提取节点(将它们从树中分离出来,但不释放内存)。在B树或B +树中,这显然不起作用-数据将存在于多项目节点中。编写“计划”操作而不修改节点,直到他们知道需要多少个新节点并可以分配它们的插入方法是一个挑战。

红黑vs.AVL?我不确定这有什么大不同。我自己的库中有一个基于策略的“工具”类来操作节点,并提供了用于双链表,简单的二叉树,展开树,红黑树和挖角的方法,包括各种转换。这些方法中的某些方法仅是因为我一次又一次感到无聊而实施的。我不确定我是否已经测试过挖方方法。我选择红黑树而不是AVL的原因是因为我个人更了解算法-但这并不意味着它们更简单,这只是我更熟悉它们的历史。

最后一件事-我最初只是以开发B +树容器作为实验。这是那些从未真正结束过的实验之一,但我不鼓励其他人重复。如果您只需要一个有序的容器,最好的答案是使用现有库提供的容器-例如,C ++中的std :: map等。我的库经过多年的发展,花了很长时间才稳定下来,而我才刚刚发现它在技术上是不可移植的(取决于一些未定义的行为WRT offsetof)。



0

选择数据结构时,您需要权衡以下因素:

  • 检索速度v更新速度
  • 该结构如何处理最坏情况的操作,例如插入按排序顺序到达的记录
  • 空间浪费

我将从阅读Robert Harvey引用的Wikipedia文章开始。

实用上,当使用Java之类的语言进行操作时,普通程序员倾向于使用提供的集合类。如果在性能调整活动中发现收集性能有问题,则可以寻求替代实现。业务主导的开发很少要考虑的第一件事。很少有人需要手工实现这样的数据结构,通常可以使用一些库。


1
公平地说,OP要求when should I consider using而不是when should I consider implementing。尽管最后一段是正确的,但在此问题的上下文中并没有提供太多价值。即使使用库,您也需要了解算法,以便有效地选择最适合您业务需求的结构。
丹·贝查德
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.