MAKE-SET(x)
x.p = x
x.rank = 0
UNION(x, y)
LINK(FIND-SET(x),FIND-SET(y))
LINK(x, y)
if x.rank > y.rank
y.p = x
else
x.p = y
if x.rand == y.rank
y.rank = y.rank +1
The FIND-SET procedure with path compression is quite simple:
FIND-SET(x)
if x != x.p
x.p = FIND-SET(x.p)
return x.p
您可以在第21章 Introduction to Algorithms 3rd 中找到伪代码。
这是具有排名和路径压缩的不相交集林的伪代码。 从伪代码中,我们可以看到每次联合运算之前,我们将首先找到每个节点的集合数。在具有路径压缩的FIND-SET操作中,x和y的高度将始终仅为2.因为x.p和y.p都将在FIND-SET之后指向set的根。为什么仍然需要按等级联盟?
答案 0 :(得分:2)
请注意,我们仅在执行path compression
操作时应用find-set
,并且当我们执行两个union
时,无法应用路径压缩。
按等级联合,我们注意这样一个事实,即具有较低等级(或较少深度/高度)的树的根被指向具有高等级(或更高深度/高度)的树的根)。这可以确保表示集合的树永远不会出现偏差。
执行按排名结合的示例:
depth=1,n=2 depth=0,n=1 depth=1,n=3
O U O = O
/ / \
O O O
如果我们没有按级别执行联合,那么树可能会变成这样:
depth=1,n=2 depth=0,n=1 depth=2,n=3
O U O = O
/ /
O O
/
O
即它的高度增加了。
您可以进行摊销分析并计算find-set
的时间复杂度,当按级别结合时,您会发现时间永远不会超过O(log2(n))
。
因此,如果你没有按级别执行联合,那么find-set
操作将花费O(d)时间(d
表示树的深度),在最坏的情况下d
可以成为n
(集合中的元素数量)。因此,对于find-set
操作,时间复杂度将首次成为O(n)
。但是,对于下一次find-set
操作,时间可能会减少,但重点是我们不希望O(n)
时间进行任何find-set
操作。因此,对于有多个联合操作的情况,最后有一个find-set
操作,如果不使用O(n)
,则会消耗union by rank
时间。
我们通过秩和路径压缩同时使用联合,因为我们想要降低树的高度并使其小于log2(n)(n是不相交集中的元素数),最终目标是使树的高度几乎为一。
答案 1 :(得分:0)
是的,x
和y
的深度为2,但这并不意味着根的高度发生了变化。
请注意,我们实际上从未减少任何根的等级。假设等级4的根有10个叶子节点,即10个节点在该特定集合中有3个边缘。现在通过路径压缩,您可能已经将这10个中的一个提升到2的深度,例如x
和y
。但是仍然有9个左,根的等级仍然是4.现在如果我们将这个集合与另一组等级1链接,我们当然不希望我们当前的根成为该新集合的子集,因为它& #39;将其他9个节点的深度转换为5.这就是为什么除了路径压缩之外我们仍然需要排名。
现在,如果不知何故所有这10个叶子节点都被提升到深度2,我们应该减少根的等级以反映它的适当高度,但增加的复杂性似乎并不值得麻烦。