何时选择 RB 树、B-Tree 或 AVL 树?

Posted

技术标签:

【中文标题】何时选择 RB 树、B-Tree 或 AVL 树?【英文标题】:When to choose RB tree, B-Tree or AVL tree? 【发布时间】:2010-12-08 01:19:03 【问题描述】:

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

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

【问题讨论】:

好吧,我很欣赏这个问题 - 目前提供了 fastutil IntAVLTreeSet 与 IntRBTreeSet 的选择。 【参考方案1】:

在内存中B-Tree有优势,当项数超过32000时...从stx-btree看speedtest.pdf。

【讨论】:

【参考方案2】:

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

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

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

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

红黑与 AVL?我不确定这有什么大的不同。我自己的库有一个基于策略的“工具”类来操作节点,具有用于双链表、简单二叉树、展开树、红黑树和陷阱的方法,包括各种转换。其中一些方法只是因为我有时感到无聊而实施。我不确定我什至测试过陷阱方法。我选择红黑树而不是 AVL 的原因是因为我个人对算法的理解更好——这并不意味着它们更简单,只是我对它们更熟悉只是历史的侥幸。

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

【讨论】:

【参考方案3】:

在选择数据结构时,您需要权衡一些因素,例如

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

我会先阅读 Robert Harvey 引用的 Wikipedia 文章。

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

【讨论】:

公平地说,OP 询问的是when should I consider using,而不是when should I consider implementing。虽然最后一段是正确的,但在这个问题的上下文中它并没有提供太多价值。即使使用库,您也需要了解算法,以便有效地选择最适合您业务需求的结构。【参考方案4】:

用少许盐吃这个:

当您管理数以千计的项目并从磁盘或一些慢速存储介质中分页它们时的 B 树。

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

当您的插入和删除相对于您的检索而言并不频繁时,AVL 树。

【讨论】:

只是添加更多细节:B-trees 可以有可变数量的子节点,这允许它保存许多记录但仍然保持一个短高度的树。 RB 树在重新平衡方面没有那么严格的规则,这使得插入/删除比 AVL 树更快。相反,AVL 树更严格地平衡,因此查找速度比 RB 树快。 RB 树在重新平衡方面也有更好的 O(1) 性能,这使得它们更适合具有回滚和前滚功能的持久数据结构。

以上是关于何时选择 RB 树、B-Tree 或 AVL 树?的主要内容,如果未能解决你的问题,请参考以下文章

AVL树介绍与实现

AVL树介绍与实现

AVL树介绍与实现

数据结构学习笔记:B树B+树红黑树AVL树

数据结构学习笔记:B树B+树红黑树AVL树

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