判断两个触点是否存在于相同的连通分量中?
quick-find算法
public class UF{
private int[] id; //分量id
private int count; //分量数量
public UF(int N){
count = N;
id = new int[N];
for(int i = 0;i< N; i++){
id[i] = i;
}
}
public int count(){return count;}
public boolean connected(int p , int q){return find(p) == find(q);}
//==========================quickfind算法,时间复杂度是N2级别的
public int find(int p){return id[p];}
public void union(int p , int q){
int pID = find(p);
int qID = find(q);
if ( pID == qID) return; //如果pID == qID ,那么说明两个触点已经相连接,直接跳过循环
for (int i = 0 ; i < id.length , i++){
if(id[i] == pID) id[i] = qID;
}
count--;
}
//==========================quickunion算法,使得union方法的复杂度总是线性级别的
public int find(int p){
while(p != id[p]) p = id[p];//找出分量的名称,也就是说找到p = id[p] 的源头,就是连通的源头,使得每一个数都能找到最终的那个数,看两者是否相等。
return p;
}
public void union(int p , int q){
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) return;
id[pRoot] = qRoot;
count--;
}
//=========================加权quickunion算法
//增加额外的数组
private int[] sz; //各个根节点所对应的分量的大小
//重写有参构造方法
public UF(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 find(int p){
while(p != id[p]) p = id[p];//找出分量的名称,也就是说找到p = id[p] 的源头,就是连通的源头
return p;
}
//下面的union方法使得对某个数找到其根触点的次数变少,也就是访问数组的次数减少
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--;
}
}