数据结构之并查集实现类

并查集定义:主要是2个核心操作,合并2个元素到一个集合,查询任意集合的所在元素的祖宗。应用在图连接分量的判断。
实现类

public class UnionFind {

    private int[] parent;   // 标注当前元素的父节点的位置

    private int[] rank;     // 标注当前元素的层级数

    private int size;       // 并查集中的元素个数

    public UnionFind (int size){
        this.size = size;

        parent = new int[size];
        rank = new int[size];

        init();
    }

    private void init() {
        for (int i = 0; i < size; i++) {
            // 初始化时所有的节点的父节点指向本身,所有的元素层级均为 1
            parent[i] = i;
            rank[i] = 1;
        }
    }


    /**
     * 寻找当前节点的根节点元素
     * @param target
     * @return
     */
    public int find(int target) {
        if(target >= size)
            throw new ArrayIndexOutOfBoundsException();
        if(target == parent[target])
            return target;
        return find(parent[target]);
    }

    /**
     * 连接两个元素
     * @param p
     * @param q
     */
    public void union(int p, int q) {
        int pRoot = find(p);
        int qRoot = find(q);
        if(pRoot == qRoot)
            return;
        if(rank[pRoot] > rank[qRoot]) { // p 所在的树的高度比 q 所在输的高度高,这时应该让 q 的根节点元素连接到 p 的根节点元素
            parent[qRoot] = pRoot; // 此时树的高度不变
        } else if(rank[pRoot] < rank[qRoot]) {
            parent[pRoot] = qRoot; // 此时树的高度不变
        } else {
            parent[pRoot] = qRoot; // 此时树的高度 +1
            rank[qRoot] += 1;
        }
    }

    /**
     * 判断两个节点是否连接
     * @param p
     * @param q
     * @return
     */
    public boolean isConnected(int p, int q) {
        // 如果两个节点的根节点一致则表示这两个节点是相连接的
        return find(p) == find(q);
    }

}

测试类

   public static void main(String[] args) {
    int size = 10;
    // Step 1: init()
    UnionFind uf = new UnionFind(size);

    // Step 2: union()
    uf.union(1,2);
    uf.union(3,4);
    uf.union(0,9);
    uf.union(4,7);
    uf.union(6,5);
    uf.union(5,8);
    uf.union(3,9);
    uf.union(1,8);

    // Step 3: find()
    System.out.println(uf.find(0));     // 9
    System.out.println(uf.find(1));     // 5
    System.out.println(uf.find(2));     // 5
    System.out.println(uf.find(3));     // 9
    System.out.println(uf.find(4));     // 9
    System.out.println(uf.find(5));     // 5
    System.out.println(uf.find(6));     // 5
    System.out.println(uf.find(7));     // 9
    System.out.println(uf.find(8));     // 5
    System.out.println(uf.find(9));     // 9

    // Step 4: isConnected
    System.out.println(uf.isConnected(0,1));    // false
    System.out.println(uf.isConnected(1,2));    // true
    System.out.println(uf.isConnected(3,4));    // true
    System.out.println(uf.isConnected(5,6));    // true
    System.out.println(uf.isConnected(7,8));    // false
    System.out.println(uf.isConnected(8,9));    // false
    System.out.println(uf.isConnected(2,4));    // false
    System.out.println(uf.isConnected(3,5));    // false
    System.out.println(uf.isConnected(5,6));    // true
    System.out.println(uf.isConnected(7,9));    // true
}

本文来自 小平_ 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/xiaoping0915/article/details/79727603?utm_source=copy

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值