并查集

/**
 * 并查集
 */
public class UF {

    //数组下标为数据,数组的值为分组的标识
    private int[] eleAndGroup;
    //记录分组的组数
    private int count;

    //N 分组的组数
    public UF(int N){
        this.count = N;
        this.eleAndGroup = new int[N];
        for (int i = 0; i < eleAndGroup.length; i++) {
            eleAndGroup[i] = i;
        }
    }

    /**
     * 获取并查集中的数据由多少个分组
     * @return
     */
    public int count(){
        return count;
    }

    /**
     * 判断并查集中元素p和元素q是否在同一分组中
     * @param p
     * @param q
     * @return
     */
    public boolean connected(int p, int q){
        return find(p) == find(q);
    }

    /**
     * 获取元素p所在的分组
     * @param p
     * @return
     */
    public int find(int p){
        return eleAndGroup[p];
    }

    /**
     * 把元素p所在的分组和q元素所在的分组合并
     * @param p
     * @param q
     */
    public void union(int p, int q){
        //元素p和元素q处在同一分组中,无需合并
        if(connected(p,q)) return;
        //元素p和元素q不在同一个分组中,将元素p所在分组合并到元素q所在分组中
        for (int i = 0; i < eleAndGroup.length; i++) {
            if(eleAndGroup[p] == eleAndGroup[i]){
                eleAndGroup[p] = eleAndGroup[q];
            }
        }
        //分组个数-1
        count--;
    }

    /**
     * 查看分组和数据
     */
    public void print(){
        for (int i = 0; i < eleAndGroup.length; i++) {
            System.out.printf("%2d",eleAndGroup[i]);
        }
        System.out.println();
        for (int i = 0; i < eleAndGroup.length; i++) {
            System.out.printf("%2d",i);
        }
        System.out.println();
    }
}

优化:

/**
 * 并查集_优化
 */
public class UF_Tree {

    //数组下标为数据,数组的值为分组的标识
    private int[] eleAndGroup;
    //记录分组的组数
    private int count;

    //N 分组的组数
    public UF_Tree(int N){
        this.count = N;
        this.eleAndGroup = new int[N];
        for (int i = 0; i < eleAndGroup.length; i++) {
            eleAndGroup[i] = i;
        }
    }

    /**
     * 获取并查集中的数据由多少个分组
     * @return
     */
    public int count(){
        return count;
    }

    /**
     * 判断并查集中元素p和元素q是否在同一分组中
     * @param p
     * @param q
     * @return
     */
    public boolean connected(int p, int q){
        if(p >= eleAndGroup.length || p < 0 || q >= eleAndGroup.length || q < 0) return false;
        return find(p) == find(q);
    }

    /**
     * 获取元素p所在的分组
     * @param p
     * @return
     */
    public int find(int p){
        if(p < 0 || p >= eleAndGroup.length) return -1;
        while(true){
            if(p == eleAndGroup[p]) return p;
            p = eleAndGroup[p];
        }
    }

    /**
     * 把元素p所在的分组和q元素所在的分组合并
     * @param p
     * @param q
     */
    public void union(int p, int q){
        if(p >= eleAndGroup.length || p < 0 || q >= eleAndGroup.length || q < 0) return;
        //获取p,q所在的分组
        int pGroup = find(p);
        int qGroup = find(q);
        //元素p和元素q处在同一分组中,无需合并
        if(pGroup == qGroup) return;
        //元素p和元素q不在同一个分组中,将元素p所在分组合并到元素q所在分组中
        eleAndGroup[pGroup] = qGroup;
        //分组个数-1
        count--;
    }
}

优化—路径压缩

/**
 * 并查集_优化_路径压缩
 */
public class UF_Tree_2 {

    //数组下标为数据,数组的值为分组的标识
    private int[] eleAndGroup;
    //记录分组的组数
    private int count;
    //记录分组的节点的个数
    private int[] sz;

    //N 分组的组数
    public UF_Tree_2(int N){
        this.count = N;
        this.eleAndGroup = new int[N];
        for (int i = 0; i < eleAndGroup.length; i++) {
            eleAndGroup[i] = i;
        }
        this.sz = new int[N];
        for (int i = 0; i < sz.length; i++) {
            this.sz[i] = 1; //初始为1,就是自身
        }
    }

    /**
     * 获取并查集中的数据由多少个分组
     * @return
     */
    public int count(){
        return count;
    }

    /**
     * 判断并查集中元素p和元素q是否在同一分组中
     * @param p
     * @param q
     * @return
     */
    public boolean connected(int p, int q){
        if(p >= eleAndGroup.length || p < 0 || q >= eleAndGroup.length || q < 0) return false;
        return find(p) == find(q);
    }

    /**
     * 获取元素p所在的分组
     * @param p
     * @return
     */
    public int find(int p){
        if(p < 0 || p >= eleAndGroup.length) return -1;
        while(true){
            if(p == eleAndGroup[p]) return p;
            p = eleAndGroup[p];
        }
    }

    /**
     * 把元素p所在的分组和q元素所在的分组合并
     * @param p
     * @param q
     */
    public void union(int p, int q){
        if(p >= eleAndGroup.length || p < 0 || q >= eleAndGroup.length || q < 0) return;
        //获取p,q所在的分组
        int pGroup = find(p);
        int qGroup = find(q);
        //元素p和元素q处在同一分组中,无需合并
        if(pGroup == qGroup) return;
        //元素p和元素q不在同一个分组中,将元素p所在分组合并到元素q所在分组中
        //如果pGroup所在的分组的节点个数小于qGroup所在分组的节点个数,则将pGroup加入到qGroup的分组中
        if(sz[pGroup] < sz[qGroup]){
            eleAndGroup[pGroup] = qGroup;   //加入
            sz[qGroup] += sz[pGroup];
        }else{
            eleAndGroup[qGroup] = pGroup;
            sz[pGroup] += sz[qGroup];
        }
        //分组个数-1
        count--;
    }
}

练习:畅通工程

在这里插入图片描述

public class Exercise_UF {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("trffic_project.txt")));
        //读取城市个数
        Integer cities = Integer.parseInt(br.readLine());
        //初始化并查集
        UF_Tree_2 uf = new UF_Tree_2(cities);
        //读取已修的道路数量及道路
        Integer has_road = Integer.parseInt(br.readLine());
        for (Integer i = 0; i < has_road; i++) {
            String line = br.readLine();
            String[] arr = line.split(" ");
            int p = Integer.parseInt(arr[0]);
            int q = Integer.parseInt(arr[1]);
            uf.union(p,q);
        }
        System.out.println("还需要再修:" + (uf.count()-1) + "条道路才可以完成畅通工程。");
        br.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值