OCaml标准库提供了一个出色的Set
实现,使用非常高效的分治算法来计算两个集合的union
。 我认为它可以从一个集合中获取整个子树(而不仅仅是单个元素),并将其插入到另一个集合中,在必要时进行重新平衡。
我想知道这是否需要AVL树中保留的高度信息,或者在红黑树中也可以实现。例如,是否可以更有效地连接一对红黑树,而不仅仅是迭代第二个树将其元素附加到第一个树的末尾?
OCaml标准库提供了一个出色的Set
实现,使用非常高效的分治算法来计算两个集合的union
。 我认为它可以从一个集合中获取整个子树(而不仅仅是单个元素),并将其插入到另一个集合中,在必要时进行重新平衡。
我想知道这是否需要AVL树中保留的高度信息,或者在红黑树中也可以实现。例如,是否可以更有效地连接一对红黑树,而不仅仅是迭代第二个树将其元素附加到第一个树的末尾?
我不确定你的问题措辞是否涉及集合并或连接,或者两者都涉及,或者你只对OCaml中常见的持久数据结构或非持久结构感兴趣。
在她的论文一章中,Heather D. Booth描述了带指针的红黑树的实现。使用指针,大小为n的红黑树可以被分成大小为p和q的两棵树,其摊销时间为O(lg(min(p,q))),并且两棵大小为p和q的红黑树可以在相同的限制下连接。此外,元素可以在rb树的任一端点以摊销O(1)时间添加或删除。通过这些操作,可以实现摊销O(p lg(q/p))时间的集合并(对于p < q),这是信息理论上最优的。也许获得这些界限的关键思想是在左右脊柱上翻转子指针。
上述界限在传统意义上是摊销的。对于像OCaml这样的函数语言,人们可能希望在数据结构被持久使用时应用这些界限。当树被持久使用时,我认为Booth的描述无法实现所有这些界限。例如,在指针处插入可能需要ω(1)次重新着色。这可以通过Driscoll等人在“使数据结构持久”中讨论的惰性重新着色来解决。
另一方面,我认为 Booth 的分析可能表明,即使在持久化使用时,串联仍然是 O(lg(max(p,q)))。我对集合并的上界持悲观态度。 在函数式环境中,可以实现具有渐进最优时间复杂度的集合操作。Hinze&Paterson描述的方法在摊销(但持久化)意义下达到了这些界限,Blandford&Blelloch描述的treaps在随机意义下达到这些界限,而Kaplan&Tarjan描述的方法则以最坏情况时间实现这些界限。后者还提供O(lg lg(min(p,q)))的连接操作,尽管Hinze&Paterson对此表示怀疑。这些树并不直接回答你的问题,这是特定于红黑树的问题,但它们希望给出一个可能性,H&P 论文包括代码,并已经使用Coq进行验证 正确性 , 可以将其提取到OCaml代码。你可能会对以下两个指针感兴趣:Brodal等人提出了具有O(lg n)查找,插入和删除以及在功能设置中具有O(1)连接的搜索树。此外,Atallah等人声称描述了一种红黑树,其摊销O(1)连接(可能仅是暂时的),但Buchsbaum和Goodrich声称该结构存在几个缺陷。
关于红黑树实用性的最后一个说明:在回答此问题的评论中,您说:
红黑树唯一的优点是每个分支的辅助信息(红色或黑色)只有1位。通过添加高度,您已经失去了这个优势,最好使用平衡树。
还有其他的优点。例如,计算几何中使用的一些数据结构基于二叉搜索树,但旋转树的代价很高。红黑树可以在插入和删除时重新平衡,最多只需3次旋转, 而AVL树对于这些操作可能需要Ω(lg n)次旋转。正如Ralf Hinze所指出的那样, Okasaki的红黑树重新平衡方案(代码可在ML, Haskell, Java和Ada中获得)没有提供相同的界限,并且在插入时可能需要Ω(lg n)次旋转。(Okasaki没有介绍删除。)
此外,高度平衡的搜索树(甚至是AVL树)可以存储为每个节点仅使用一位平衡信息。有些树在每个节点上只有两个可能的平衡位置,例如单侧高度平衡树,但每个节点最多有四个可能的平衡位置的树可以在每个孩子中存储一位平衡信息,正如Brown最初解释的,后来Haeupler等人进一步扩展了。给定两个非空红黑树L和R,我们将生成一个新的红黑树,该树是L和R的连接。这将花费的时间与O(lg(max(|L|,|R|)))成正比,其中| L |表示L中节点的数量。
首先,从L中删除最大的元素c。接下来,找到L和R的黑色高度。所谓“黑色高度”,是指从根节点到叶子节点的任意路径上的黑色节点数目。根据红黑树的不变式,这在给定树的所有路径上都保持不变。将L的黑色高度称为p,R的黑色高度称为q,并假设w.l.o.g. p ≤ q。
从R的根节点开始,沿着左孩子一直走,直到到达一个高度为p的黑色节点R'。用c作为根元素、L作为左孩子、R'作为右孩子构建一个新的红色树C。由于L本身就是红黑树,其根节点是黑色的,因此在或以下的C中不会违反颜色不变式。此外,C的黑色高度为p。
然而,我们不能简单地将C插入到R中替换R'。首先,如果p=q,则R'就是R,但C具有红色根。在这种情况下,只需将C的根重新涂成黑色即可。这就是您的新连接树。
其次,如果R'不是根节点,则它可能有一个红色父节点。不允许红色父节点有红色子节点,因此我们必须重新平衡。在R'(现在用C替换)和R的根节点之间的脊柱上应用Okasaki的重新平衡方案。
有两种可能的情况。如果C没有祖父节点,则将C的父节点涂成黑色。树现在是有效的。
如果C有祖父,则其必须为黑色且黑高度为p+1,因为C的父节点为红色。用一个新的红树替换C的祖父,其根为C的父节点的根,左孩子为被重新染成黑色的C,右孩子为由C的兄弟、C的祖先的根和C的叔叔组成的黑树,按照上述顺序。这不会增加C的祖父的黑高度,但它将其颜色更改为红色,这可能使其成为根或红色父节点的红色子节点,因此我们必须再次重新平衡,以此类推,一直到整棵树的根部。由于您似乎在谈论连接和添加到末尾,因此似乎您有以下问题:
Given two red-black trees T1 and T2, such that keys of T1 <= keys of T2,
find union of the two.