对于不相交的森林,路径压缩就足够了,为什么我们需要按等级联合

时间:2018-03-30 12:25:55

标签: algorithm minimum-spanning-tree kruskals-algorithm disjoint-sets

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的根。为什么仍然需要按等级联盟?

Shahriar已经解决了我的问题,他的答案真是令人印象深刻!

2 个答案:

答案 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)

是的,xy的深度为2,但这并不意味着根的高度发生了变化。

请注意,我们实际上从未减少任何根的等级。假设等级4的根有10个叶子节点,即10个节点在该特定集合中有3个边缘。现在通过路径压缩,您可能已经将这10个中的一个提升到2的深度,例如xy。但是仍然有9个左,根的等级仍然是4.现在如果我们将这个集合与另一组等级1链接,我们当然不希望我们当前的根成为该新集合的子集,因为它& #39;将其他9个节点的深度转换为5.这就是为什么除了路径压缩之外我们仍然需要排名。

现在,如果不知何故所有这10个叶子节点都被提升到深度2,我们应该减少根的等级以反映它的适当高度,但增加的复杂性似乎并不值得麻烦。