并查集三种Java代码实现

@代码模板

package Algorithm;

public class UF {
    
    
    private int[] id;//连通分量的id
    private int count;
    public UF(int n){
    
    //初始化n个触点
        count=n;
        id=new int[n];
        for (int i = 0; i < n; i++) {
    
    
            id[i]=i;//初始化时,每个触点都是一个单独的分量
        }
    }
    public int getCount(){
    
    //得到分量数
        return count;
    }
    public boolean connected(int p,int q){
    
    //判断触点p,q是否连通
        return find(q)==find(p);
    }
    public int find(int p){
    
    //找到触点p所在的分量id
    }
    public void union(int p,int q){
    
    //合并触点p,q
    }
}

实现find和union即可。

1.用循环将一个分量中的触点全部改变

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;
        for (int i = 0; i < id.length; i++) {
    
    
            if(id[i]==pID) id[i]=qID;
        }
        count--;
    }

2. 链接法

  public int find(int p){
    
    
       while (p!=id[p]) p=id[p];
       return p;
    }
    public void union(int p,int q){
    
    
        int pID=find(p);
        int qID=find(q);
        if(pID==qID) return;
        id[pID]=qID;
        count--;
    }

就两个分量,id=[1, 1, 1, 8, 3, 0, 5, 1, 8, 8]。比如下标4的是3,那么说明下标4链接到下标3,在8这个分量里面。

3. 加权树

private int[] sz;//保存树的高度,初始化都为1   
public int find(int p){
    
    
       while (p!=id[p]) p=id[p];
       return p;
    }
    public void union(int p,int q){
    
    
        int pID=find(p);
        int qID=find(q);
        if(pID==qID) return;
        if(sz[pID]<sz[qID]){
    
    //小树加到大树上面
            sz[qID]+=sz[pID];
            id[pID]=qID;
        }else{
    
    
            sz[pID]+=sz[qID];
            id[qID]=pID;
        }
        count--;
    }

路径压缩

private int find(int p){
    
    
	if(p==id[p]) return p;
	return id[p]=find(id[p]);
}

猜你喜欢

转载自blog.csdn.net/qq_43179428/article/details/108035138