在上一篇的union-find算法中,每次执行union()方法都要遍历一次数组,造成很大的时间消耗,那么,有没有一种方法来改善union()方法呢,提供一条思路。我们采用链式结构来存储数据,即属于一个分量的数据保存到一条链中中,比如1,3,5属于一条链,那么,我们把数组存储为a[1] = 3 a[3] =5 a[5] =5,这样可以减少union()将不用遍历数组,只用找到一个分量的根节点,再用根节点指向我们要绑定的数据,比如要绑定7,只需把a[5] = 7就可以了,合并两天链就生成了树结构,实现如下。
public class UF{
private int[] a;
private int count;
//初始化
public UF(int cap){
count = cap;
a = new int[cap];
for(int i=0;i<cap;i++)
a[i] = i;
}
//找到分量的标记
public int find(int p){
while(a[p]!=p) p = a[p];
return p;
}
//连接p和q
public void union(int p,int q){
int rootP = find(p);
a[rootP] = q;
count--;
}
//返回分量的数量
public int count(){
return count;
}
//判断两个分量是否连通
public boolean commected(int p,int q){
return find(p)==find(q);
}
}
这样用链式结构来存储触点在一般的情况下可以有效的提高效率,但也有特殊的情况,比如 0 1 0 2 03 04 ……在这种情况下我们union()时需要访问数组的次数为1,2,3,4,5…N这种情况是该算法执行的最坏情况,那么有没有一种方法来避免最坏情况的发生呢,再提供一个思路,使用一个辅助数组来记录每个分量的权。