并查集-java语言版

623 阅读2分钟

并查集是一种树型的数据结构 ,并查集可以高效地进行如下操作:

1、查询元素p和元素q是否属于同一组

2、合并元素p和元素q所在的组

并查集.jpg

-- 设计思想:

    1、eleAndGroup数组,索引为值,索引处保存的是其父节点,如果索引和值相等说明到达根结点
    2、sz数组用于保存树中的元素个数,
    3、合并的时候将较小的树,添加到较大的树中
    
  

-- API设计:

API设计.jpg

-- 代码:

public class UF_Tree_Weighted {
    // 记录结点元素和该元素所在的父结点
    private int[] eleAndGroup;
    // 存储每个根结点对应的树中元素的个数
    private int[] sz;
    // 记录并查集中数据的分组个数
    private int count;

    // 初始化并查集
    public UF_Tree_Weighted(int N) {
        // 初始情况下,分组数量和元素数量相当
        this.count = N;
        // 初始化数组
        eleAndGroup = new int[N];
        sz = new int[N];

        // 初始情况下i索引处存储的值就是i
        for (int i = 0; i < N; i++) {
            eleAndGroup[i] = i;
        }

        // 初始情况下数组中都为1
        for (int i = 0; i < N; i++) {
            sz[i] = 1;
        }
    }

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

    // 元素p所在树的父结点
    public int find(int p) {
        while (true) {
            // 如果元素p和父结点相等,说明找到根结点
            if(p == eleAndGroup[p]) {
                return p;
            }
            // 如果不是根结点,继续找其父结点
            p = eleAndGroup[p];
        }
    }

    // 把p元素所在分组和q元素所在分组合并
    public void union(int p,int q) {
        // 找到p元素所在的根结点
        int pRoot = find(p);
        // 找到q元素所在的根结点
        int qRoot = find(q);

        // 如果元素p和q已经在同一个树中,则无需合并
        if(pRoot == qRoot) {
            return;
        }

        // 将较小的树添加到较大的树上面
        if(sz[pRoot] < sz[qRoot]) {
            eleAndGroup[pRoot] = qRoot;
            // 重新调整较大的树元素个数
            sz[pRoot] += sz[qRoot];
        }else {
            eleAndGroup[qRoot] = pRoot;
            sz[pRoot] += sz[qRoot];
        }

        // 分组数量-1
        count--;
    }
}

@ 以上内容属于个人笔记