动态连通性
什么叫动态连通性?
- symmetric(对称性): If p is connected to q, then q is connected to p.
- transitive(传递性): If p is connected to q and q is connected to r, then p is connected to r.
- reflexive(自反性): p is connected to p.
quick-find算法
public int find(int q){
return id[q]
}
public void union(int p,int q){
int pID = find(p);
int qID = find(q);
if(pID == qID) return;
for(int i = 0;i < id.length;i++)
if(id[i] == pID) id[i] == qID;
count --;
}
在quick-find
算法中,每次find()
调用都要访问数组一次,要归并两个分量的union()
操作访问数组的次数在(N+3)
到(2N+1)
之间。
quick-union算法
private int find(int p){
//找出分量的名称
while(p != id[p])
p = id[p];
return p;
}
public void union(int p,int q){
//将p和q的根结点统一
int pRoot = find(p);
int qRoot = find(q);
if(pRoot == qRoot) return;
id[pRoot] = qRoot;
count --;
}
union算法的实现(加权quick-union算法)
public class WeightedQuickUnionUF{
private int[] id; //父链接数组(由触点索引)
private int[] sz; //(由触点索引的)各个根结点所对应的分量的大小
private int count; //连通分量的数量
public WeightedQuickUnionUF(int N){
count = N;
id = new int[N];
for(int i = 0;i<N;i++) id[i] = i;
sz = new int[N];
for(int i=0;i < N;i++) sz[i] = 1;
}
public int count(){
return count;
}
public boolean connected(int p,int q){
return find(p) == find(q);
}
public int find(int p){
//跟随链接找到根结点
while(p != id[p])
p = id[p];
return p;
}
public void union(int p,int q){
int i = find(p);
int j = find(q);
if (i == j) return;
//将小树的根结点连接到大树的根结点
if(sz[i] < sz[j]){
id[i] = j;
sz[j] += sz[i];
}
else{
id[j] = i;
sz[i] += sz[j];
}
count --;
}
}
各种union-find
算法的性能特点:
Exercise
Creative Problems
- Quick-union with path compression. Modify QuickUnionUF.java to include path compression, by adding a loop to find() that links every sie on the path from p to the root. Give a sequence of input pairs that causes this method to produce a path of length 4. Note: the amortized cost per operation for this algorithm is known to be logarithmic.
|
|