我正在学习"加权快速联合路径压缩"联合/查找结构的算法。 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的结果感到好奇。它是如何衍生出来的?有人可以证明它或只是以直观的方式解释它吗?
答案 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更容易)。证据基于三点:
在每个叶根路径上,每个节点的等级都在增加。这实际上依赖于按等级,BTW联合,并且,通过它,它很容易显示。
如果树的根具有等级 r ,则该树至少具有 2 r 节点。这可以通过归纳来显示。
基于2.,可以显示
其余的证据现在紧接着是对队伍组织最糟糕的可能方式的巧妙安排,这仍然表明没有太多是坏的。有关详细信息,请参阅Wikipedia entry on this。