Union-Find初探并查集中提到:
如果在合并的过程中就将两个对象的组份ID设为一致,查找的时候就相当容易;如果在合并的过程中只是将一个对象与另一个对象相连,则查找的时候需要确定某个对象的始祖对象才能确定其所属的组份ID。
现在介绍方便快速查找的并查集:
public class QuickFindUF {
private int[] componentID;
private int count; // number of components
public QuickFindUF(int n)
{
if(n<0) throw new IllegalArgumentException();
this.count=n;
this.componentID=new int[n];
for(int i=0;i<n;i++)
{
componentID[i]=i;
}
}
//连接两个节点
void union(int p,int q){
int rootP=this.find(p);
int rootQ=this.find(q);
if(rootP==rootQ)
return;
int label=Math.min(rootP, rootQ);
int max=Math.max(rootP, rootQ);
for(int i=0;i<this.componentID.length;i++)
if(this.componentID[i]==max)
this.componentID[i]=label;
count--;
}
//在查找p节点所属组份ID过程中会将实际上同属于一个组份的不同ID修改成相同
int find(int p)
{
int n=this.componentID.length;
if(p<0||p>=n)
throw new IllegalArgumentException("index " + p + " is not between 0 and " + (n-1));
while(p!=this.componentID[p])
{
this.componentID[p]=componentID[componentID[p]];
p=componentID[p];
}
return p;
}
boolean isConnected(int p,int q)
{
int n=this.componentID.length;
if(p<0 || p>=n || q<0 || q>=n)
throw new IllegalArgumentException("index " + p +" or "+q+ " is not between 0 and " + (n-1));
return this.find(p)==this.find(q);
}
int count()
{
return this.count;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
QuickFindUF uf=new QuickFindUF(10);
uf.union(0,5);
uf.union(1,6);
uf.union(2,1);
uf.union(3,4);
uf.union(4,9);
uf.union(5,6);
uf.union(7,2);
uf.union(8,3);
uf.union(9,4);
System.out.println(uf.count);
for(int i=0;i<uf.componentID.length;i++)
System.out.println("index "+i+" linked to "+uf.componentID[i]);
}
下面是测试结果:
2
index 0 linked to 0
index 1 linked to 0
index 2 linked to 0
index 3 linked to 3
index 4 linked to 3
index 5 linked to 0
index 6 linked to 0
index 7 linked to 0
index 8 linked to 3
index 9 linked to 3