我目前正在实施红黑树数据结构,以便为应用程序执行一些优化。
在我的应用程序中,在给定的点上,我需要从树中删除小于或等于给定值的所有元素(您可以假设元素是整数)。
我可以逐个删除这些元素,但我希望能有更快的速度。因此,我的问题是:如果我删除一个红黑树的整个子树,我怎么能修复树来恢复高度和颜色不变量?
答案 0 :(得分:8)
当您从红黑树中删除一个元素时,它需要O(log n)时间,其中n是当前树中元素的数量。
如果只删除少数元素,那么最好只是逐个删除它们,最后是O(k log n)操作(k =删除元素,n =删除前树中的元素)。 / p>
但是如果您知道要删除大量节点(例如树的50%或更多),那么最好迭代您想要保留的元素(O(k')操作其中k '=将保留的元素),然后根据您的内存管理方案废弃树(O(1)或O(n))并重建树(O(k'log k'))操作。总复杂度是O(k')+ O(k'log k')= O(k'log k'),当k'<1时,它明显小于O(k log n)。 k(你保留的树不到树的50%)。
嗯,无论如何,当你要删除大部分元素时,最好在实践中枚举你想要保留的元素,然后重建树。
答案 1 :(得分:6)
编辑:以下是通用子树删除。您需要的只是一个Split
操作(基于您的实际问题内容)。
在最坏情况O(log n)
时间内,可以删除红黑树的整个子树。
众所周知,红色黑树上的Split
和Join
操作可以在O(log n)
时间内完成。
分割:给定值k和红黑树T,将T分割为两个红黑树T1和T2,使得T1中的所有值<1。 k和T2中的所有值=> k。
加入:将两个红黑树T1和T2组合成一个红黑树T.T1和T2在T2中满足最大值T1 <= min(或T1 <= T2简而言之。。
您需要的是两个Splits
和一个Join
。
在您的情况下,您需要删除的子树将对应一系列值L <= v <= U
。
所以你首先在L上Split
,得到T1和T2,T1 <= T2。 Split
在U上获得T2以获得T3和T4,其中T3 <= T4。现在Join
树T1和T4。
在pseudoCode中,您的代码将如下所示:
Tree DeleteSubTree( Tree tree, Tree subTree) {
Key L = subTree.Min();
Key U = subTree.Max();
Pair <Tree> splitOnL = tree.Split(L);
Pair <Tree> splitOnU = splitOnL.Right.Split(U);
Tree newTree = splitOnL.Left.Join(splitOnU.Right);
return newTree;
}
有关详情,请参阅此处:https://cstheory.stackexchange.com/questions/1045/subrange-of-a-red-and-black-tree
答案 2 :(得分:2)
从红黑树中批量删除很难,因为黑色高度不变量会非常糟糕。假设你没有做(软)实时,我会逐个删除(因为你必须逐个插入它们,我们在这里讨论一个较小的常数因子)或切换到一个splay树