并查集_Java实现(模板)

关于并查集的概念和效率,这里不详述,网上一大堆,这里主要记录一下并查集的 Java代码实现

三步走:
1.初始化pres和rangks数组,pres为每个元素的父结点(上一级),ranks为每个元素作为根节点时的树的秩(树的深度),一开始设置pres的每个值为每个元素自己,设置ranks每个值为0.
2.find() 查询该元素的首级,顺便做路径压缩
3.unionSet() 合并两个集合,按秩合并,秩小的树的根节点指向秩大的树的根节点。

//Java实现的并查集数据结构和并查算法
public class 并查集 {

    public static void main(String[] args) {
        int n = 10; //结点数

        //边数据
        int[][] edges = {{0, 9}, {9, 3}, {1, 2}, {2, 8}, {4, 5}, {6, 7}, {0, 5}, {6, 8}};
        int[] pres = new int[n];
        int[] ranks = new int[n];

        //初始化,把pres每个元素的上一级设置为自己,把ranks的每个元素的深度设置为0
        for (int i = 0; i < n; i++) 
            pres[i] = i;

        //通过边数据构造并查集
        for (int[] edge : edges)
            unionSet(edge[0], edge[1], pres, ranks);

        printAns(pres, ranks);
    }

    //并:合并两个集合,按秩合并
    public static void unionSet(int n1, int n2, int[] pres, int[] ranks) {
        int root1 = find(n1, pres);
        int root2 = find(n2, pres);
        if (ranks[root1] < ranks[root2]) {
            pres[root1] = root2;
        } else {
            pres[root2] = root1;
            if (ranks[root1] == ranks[root2])
                ranks[root1]++;
        }
    }

    //查:查找元素的首级
    public static int find(int x, int[] pres) {
        int root = x;
        while (pres[root] != root)
            root = pres[root];

        //路径压缩
        int p = x;
        while (pres[p] != p) {
            int t = pres[p];
            pres[p] = root;
            p = t;
        }
        return root;
    }

    public static void printAns(int[] pres, int[] ranks) {
        System.out.print("pres:\t");
        for (int pre : pres)
            System.out.print(pre + " ");
        System.out.print("\nranks:\t");
        for (int rank : ranks)
            System.out.print(rank + " ");
        System.out.print("\nidx:\t");
        for (int i = 0; i < pres.length; i++)
            System.out.print(i + " ");
    }

}

/*
 * pres: 0 6 1 0 0 4 6 6 1 0
 * ranks:2 1 0 0 1 0 2 0 0 0
 * idx:	0 1 2 3 4 5 6 7 8 9
 *
 * */

你可能感兴趣的:(算法与数据结构)