特定意图的二进制搜索树

时间:2010-01-04 18:29:34

标签: algorithm data-structures binary-tree

我们都知道有很多自平衡二分查找树(BST),其中最着名的是红黑和AVL。看看AA树和替罪羊树也许有用。

我希望删除插入和搜索,就像任何其他BST一样。但是,删除给定范围内的所有值或删除整个子树是很常见的。所以:

  1. 我想在O(log n)(平衡树)中插入,搜索,删除值。
  2. 我想删除一个子树,保持整个树平衡,在O(log n)(最坏情况或摊销)
  3. 在平衡树
  4. 之前,删除行中的多个值可能很有用
  5. 我通常会一次插入2个值,但这不是一个规则(如果有一个树数据结构考虑到这一点,只是一个提示)
  6. 是否有AVL或RB的变体可以帮我解决这个问题?替罪羊树看起来更像这样,但也需要一些改变,任何有经验的人都可以分享一些东西吗?

    更准确地说,哪种平衡程序和/或删除程序可以帮助我保持这项行动的时间效率?

5 个答案:

答案 0 :(得分:5)

可以在O(logn +对象num)中删除BST值的范围。

我知道最简单的方法是使用Deterministic Skip List数据结构(在继续之前,您可能想要阅读一些关于此数据结构的内容)。 在确定性跳过列表中,所有实际值都存储在底层,并且在它们的上层有指针。插入,搜索和删除都在O(logn)中完成。

范围删除操作可以根据以下算法完成:

  • 找到范围中的第一个元素 - O(logn)
  • 在链接列表中前进,并删除仍在范围内的所有元素。如果有指向上层指针的元素 - 也将它们删除,直到达到最高层(从链接列表中删除) - O(已删除对象的数量)
  • 修复指针以适合确定性跳过列表(每个指针向上之间有2-3个元素)

范围删除的总复杂度为O(logn +范围内的对象数)。 请注意,如果您选择使用随机跳过列表,则会获得相同的复杂性,但平均而言,并非最坏情况。优点是你不必修复上层指针来满足2-3的需求。

确定性跳过列表具有到2-3树的1-1映射,因此通过更多工作,上述过程也适用于2-3树。

答案 1 :(得分:3)

很久以前在STL之前的日子里,我编写了自己的B-Tree(BST)算法,因为当时我有一个相当大的数据集(2棵树中大约700K项是相互依赖的)。我发现每100-200次插入/删除后重新平衡是我在486和SGI硬件上进行实验时获得的最高性能。此数字现在可能不同,或者可能不同,因为除非您转换为并行模型,否则它似乎确实是算法优化限制。

简而言之,您可以为重新平衡应用修改触发器,并在完成所有修改后允许强制重新平衡。

改善非常显着。 25米后初始直接负荷未完成(杀死过程)。我们去的时候重新平衡也在15米后被杀。限制修改加载每100个mod加载重新平衡,并在不到3米的时间内运行。请注意,在“运行”部分期间,每个初始条目对树进行了0-8次修改。你真的需要考虑在短期内再次修改树时是否总是需要保持平衡。

答案 2 :(得分:2)

嗯,B树怎么样?它们也是平衡的,如果你选择一个大订单 - 它取决于你有多少项---,你将节省一堆对象创建/销毁时间。

至2.如果你有一个100级的B树,你可以通过一个函数调用删除多达100个项目。

To 3.此功能几乎可以应用于任何树,只需实现RemoveSome()函数即可删除N个项并进行重新平衡。对于B树来说,它有点棘手,但可以做到。

注意:我认为你是一名程序员。如果您需要一个完整的,经过测试的现成解决方案,则需要另一个答案。

答案 3 :(得分:2)

如果每个节点存储其高度而不是平衡因子,则应该很容易实现在AVL树中删除节点及其子节点。删除节点后,保持旋转直到两个子节点相差不超过一个。然后向上移动树并重复。与正常删除的唯一真正区别是while而不是if来测试高度。

答案 4 :(得分:1)

OCaml标准库中的Set实现是一个纯功能的AVL树,可以满足您的所有要求,特别是具有集合理论操作(并集,交集,差异)的非常有效的实现。插入和删除是O(log n)。您可以通过将子集表示为集合并使用集合差异来删除子树和元素集。您可以通过创建2元素集并应用set union来同时插入两个元素。