我们设计了一份API来封装所需的基本操作:初始化、连接两个节点、判断包含某个节点的分量、判断两个节点是否存在于同一个分量之中以及返回所有分量的数量。
public class UnionFindSet
UnionFindSet(int n) initialize N sites with integer names (0 to n-1)
void union(int a, int b) add connection between a and b
int find(int x) component identifier for x (0 to n-1)
boolean connected(int a, int b) return true if a and b are in the same component
int count() number of components
理解了思路后,实现代码比较简单:
public class UnionFindSet {
private int[] array;
UnionFindSet(int n){
array=new int[n];
for(int i=0;i<array.length;i++) {
array[i]=-1;//初始化为-1;
}
}
public int find(int x ) {
while(array[x]!=-1) {
x=array[x];
}
return x;
}
public void union(int a,int b) {
int roota=find(a);
int rootb=find(b);
if(roota!=rootb)
array[roota]=rootb;//若两个节点不是同一个根,则连接起来。
}
public boolean connected(int a,int b) {
int roota=find(a);
int rootb=find(b);
if(roota==rootb)
return true;
return false;
}
public int count() {
int count=0;//能够形成几棵独立的树(集合)。
for(int i=0;i<array.length;i++) {
if(array[i]==-1)
count++;
}
return count;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
UnionFindSet ufs = new UnionFindSet(10);
ufs.union(4,3);
ufs.union(3,8);
ufs.union(6,5);
ufs.union(9,4);
ufs.union(2,1);
System.out.println(ufs.count());
System.out.println(ufs.connected(0, 7));
System.out.println(ufs.connected(8, 9));
}
}
测试用例表现如图:
测试结果如图:
后续还可以对合并时的树高做出优化。