带路径压缩算法的加权快速联合:时间复杂度分析

时间:2016-09-02 12:43:42

标签: algorithm performance data-structures time-complexity union-find

我正在学习"加权快速联合路径压缩"联合/查找结构的算法。 Princeton edu site详细解释了算法。 这是Java中的实现:

public class WQUPC {
  private int[] id;
  private int[] sz;
  public WQUPC(int N) {
    id = new int[N];
    sz = new int[N];
    for (int i = 0; i < N; i++) {
      id[i] = i;
      sz[i] = 1;
    }
  }

  int root(int i) {
    while (i != id[i]) {
      id[i] = id[id[i]];
      i = id[i];
    }
    return i;
  }

  boolean connected(int p, int q) { return root(p) == root(q); }

  void union(int p, int q) {
    int i = root(p);
    int j = root(q);
    if (sz[i] < sz[j]) {
      id[i] = j;
      sz[j] += sz[i];
    } else {
      id[j] = i;
      sz[i] += sz[j];
    }
  }
}

但就像网站提到它的表现一样:

  

定理:从空数据结构开始,任何序列   M union和在N个对象上查找操作的时间为O(N + M lg * N)。

     

•证明非常困难。

     

•但算法仍然很简单!

但我仍然对迭代对数lg * n的结果感到好奇。它是如何衍生出来的?有人可以证明它或只是以直观的方式解释它吗?

2 个答案:

答案 0 :(得分:1)

我记得,证据与在一组搜索中分摊路径压缩的成本有关。浅层搜索很便宜,并且不会产生大量路径压缩的成本;深度搜索会为搜索和路径压缩花费很多,但路径压缩会使后续搜索的平均成本更低。

答案 1 :(得分:1)

首先,您的问题有一个小错误:仅路径压缩的复杂性仅为 O(m log(n))(没有迭代日志)。例如,参见Introduction To Algorithms中的练习21-4.4。实际上,你阻止了

    if (sz[i] < sz[j]) {
      id[i] = j;
      sz[j] += sz[i];
    } else {
      id[j] = i;
      sz[i] += sz[j];
    }

按排名结合。

通过秩和路径压缩的联合,可以很容易地证明你使用的表达式(比逆Ackerman更容易)。证据基于三点:

  1. 在每个叶根路径上,每个节点的等级都在增加。这实际上依赖于按等级,BTW联合,并且,通过它,它很容易显示。

  2. 如果树的根具有等级 r ,则该树至少具有 2 r 节点。这可以通过归纳来显示。

  3. 基于2.,可以显示

    1. 排名 r 的最大节点数最多为 n / 2 r
    2. 其余的证据现在紧接着是对队伍组织最糟糕的可能方式的巧妙安排,这仍然表明没有太多是坏的。有关详细信息,请参阅Wikipedia entry on this