union-find算法

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);
    }

    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] == qId){
                id[i] = qId;
            }
        }
        count--;
    }
 

}

find()操作的速度显然是很快的,因为它只需要访问id[]数组一次。但quick-find算法一般无法处理大型问题,因为对于每一组输入union()都需要扫描整个id[]数组。

quick-union算法

public class QuickUnionUF {
    private int[] id;

    public QuickUnionUF(int N){
        id = new int[N];
        for(int i = 0;i < N;i++){
            id[i] = i;
        }
    }

    private int root(int i){
        while (id[i] != i){
            i = id[i];
        }
        return i;
    }

    public boolean connected(int p,int q){
        return root(p) == root(q);
    }

    public void union(int p,int q){
        int i =root(p);
        int j = root(q);
        id[i] = j;
    }
}

树的深度会影响这个算法的时间复杂度。

加权quick-union算法

public class WeightedQuickUnionUF {

    private int[] id;   //分量id
    private int[] sz;   //各个根节点所对应的分量的大小
    private int count;  //分量数量

    public WeightedQuickUnionUF(int N){
        count = N;
        id = new int[N];
        for(int i = 0;i < N;i++){
            id[i] = i;
        }
        for(int i = 0;i < N;i++){
            id[i] = 1;
        }
    }

    public int count(){
        return count;
    }

    public boolean connected(int p,int q){
        return find(p) == find(q);
    }

    private int find(int i){
        while (id[i] != i){
            id[i] = id[id[i]];    //路径压缩,使树变得扁平化。
            i = id[i];
        }
        return i;
    }


    public void union(int p,int q){
        int pId = find(p);
        int qId = find(q);

        if(pId == qId){
            return;
        }
        //关键在于这个部分,每次判断两个树的大小,防止树的深度太大。
        if(sz[pId] < sz[qId]){
            id[pId] = qId;
            sz[qId] += sz[pId];
        }else{
            id[qId] = pId;
            sz[pId] += sz[qId];
        }
        count--;
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值