union-find算法改善(一)

在上一篇的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这种情况是该算法执行的最坏情况,那么有没有一种方法来避免最坏情况的发生呢,再提供一个思路,使用一个辅助数组来记录每个分量的权。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值