今天是基于Union-Find(动态连通性)的quick-union的优化,称为加权quick-union算法实现。
题目介绍
Union-Find(动态连通性)的题目介绍就不再粘贴了,可以看下之前的文章Union-Find(动态连通性)--quick-union。
quick-union算法的问题在于,连接的树的高度可能因输入的数据而出现特别高的情况,就以昨天的例子来说,只需要在最后一步输入9,1或者2,3等,最终都将如下:
实现思路(加权quick-union)
先看下实现思路图:
要解决这种情况改怎么办呢?其实只需要在连接两棵树的时候做些简单的调整即可:每次连接都将小的树连接到大树上面。
quick-union与加权quick-union对比.png
这样就保证了树的最大高度为lgN,从而我们的union算法的时间复杂度也为O(logN)。
实现代码
public class WeightedQuickUnionUF implements QuickUF {
private int[] id;
private int[] sz;
private int count;
public WeightedQuickUnionUF(int N) {
count = N;
id = new int[N];
sz = new int[N];
for (int i = 0; i < N; i++) {
id[i] = i;
sz[i] = 1;
}
}
@Override
public int count() {
return count;
}
@Override
public boolean connected(int p, int q) {
return find(p) == find(q);
}
@Override
public int find(int p) {
while (p != id[p]) p = id[p];
return p;
}
@Override
public void union(int p, int q) {
int i = find(p);
int j = find(q);
if (id[i] == id[j]) return;
if (sz[i] < sz[j]) {
id[i] = j;
sz[j] += sz[i];
} else {
id[j] = i;
sz[i] += sz[j];
}
count--;
}
public static void main(String[] args) {
int N = 9;
WeightedQuickUnionUF quickUnionUF = new WeightedQuickUnionUF(N);
quickUnionUF.union(1, 5);
quickUnionUF.union(2, 6);
quickUnionUF.union(6, 7);
quickUnionUF.union(4, 8);
quickUnionUF.union(7, 8);
StdOut.println(quickUnionUF.count());
StdOut.println(quickUnionUF.find(0));
StdOut.println(quickUnionUF.find(4));
StdOut.println(quickUnionUF.find(6));
StdOut.println(quickUnionUF.find(3));
StdOut.println(quickUnionUF.connected(2, 4));
StdOut.println(quickUnionUF.connected(1, 2));
}
}
算法相关实现源码地址:https://github.com/xiekq/rubs-algorithms
网友评论