路径压缩和联盟如何相互补充?

时间:2017-01-16 23:43:42

标签: algorithm tree disjoint-sets union-find

我一直在阅读关于工会发现问题。两个主要的改进是路径压缩和按等级联合。据我所知,按等级联合用于确定如何组合不相交的树。如果我们有两个不相交的树T1和T2,那么我们将具有较小等级的树的根附加到具有较高等级的树。如果我们不使用路径压缩,则排名只是树的深度。这是有道理的,因为我们不想增加树的深度,因为它直接影响发现和联合。

我的问题是我们也使用路径压缩。我一直在读这两个优化相互补充,但我不明白。由于路径压缩,秩不再是树的深度(它成为深度的上限)。假设T1有2个分支(让T1的等级为3),T2有深度2和等级2.现在假设我们在标有" *"的T1的叶子上执行查找操作(带路径压缩)。下面。现在,如果我们将T1的根和T2的根联合起来,那么T2将被附加到T1的根(因为秩不是由find更新的)。得到的树有3个深度。但如果我们将T1连接到T2,我们可以有更好的性能。

T1:    o       (Rank = 3)      T2: o  (Rank = 2)       
     /| |\                         |
    * o o o                        o
                                   |
                                   o
Result of T1 union T2
       o
   / | | |\
  * o o o  o   Rank = 3 and Max Depth = 3
           |
           o
           |
           o

在T1的叶子上找到(" *"),然后在T1和T2的根上结合

#include <iostream>
using namespace std;

int main()
{
    int num1;
    int num2;
    int sum = 0;
    cout << "Which sum do you wanna do?" << endl;
    cout << "Introduce your first number";
    cin >> num1;
    cout << "The second number?";
    cin >> num2;

    int sum = num1 + num2;
    cout "The result is" << sum;
}

我在这里遗漏了什么吗?路径压缩和联盟如何相互补充?我知道等级只是树深度的上限,但我不知道按等级联合是如何提高结构的整体性能的。这比一个随机组合根的联合更好吗?

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

按队列联盟可确保树的最大深度为log N,因此它会在每次操作时将O(log N)的最坏情况设置为上限。

没有任何特殊联合规则的路径压缩是每个操作的摊销成本的O(log N)的上限,但并不限制最坏情况的成本。 (甚至可能对摊余成本有更严格的约束,但O(log N)是我知道如何证明的那个)

同时使用两者,在最坏的情况下得到O(log N)限制分摊的界限提高到O((N)),这实际上是常数。通过这种方式,两种优化是互补的。

你是对的,有一系列的操作,按等级联合不是绝对最优的,但保证比没有它的情况好,这就是重要的。我们通常不会花费精力优化最佳案例效果。我们优化最差平均案例。

答案 1 :(得分:0)

如果按等级/权重使用并集,则问题中的图形T2不能首先形成。

只需尝试使用3个节点,然后看看是否可以提出图形T2。这是不可能的。甚至图T1都不能一开始就形成。

您可以从N个节点的示例开始,如果从头开始按等级/权重进​​行合并,则实际上您会看到它会提供最佳的合并结构(某些操作序列可能没有给出最好的合并,但是大多数时候它给出了最好的结果。

换句话说,按等级/权重进​​行联合有助于查找方法(依次使用路径压缩进行进一步优化),使查找操作几乎是恒定时间的操作。