并查集

并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题,主要用于解决一些元素分组的问题。判断是否产生回路要用到并查集,关于并查集只介绍它在本算法中的应用。并查集中保存了一棵或者几棵树,这些树有这样的特点:通过树中一个结点,可以找到其双亲结点,进而找到根结点(其实就是之前讲过的树的双亲存储结构)。这种特性有两个好处: - -是可以快速地将两个含有很多元素的集合并为一个。两个集合就是并查集中的两棵树,只需找到其中一棵树的根,然后将其作为另一棵树中任何一个结点的孩子结点即可。二是可以方便地判断两个元素是否属于同一个集合。通过这两个元素所在的结点找到它们的根结点,如果它们有相同的根,则说明它们属于同一个集合,否则属于不同集合。并查集可以用一维数组来简单地表示。图7-13所示即为并查集在数组中的表示及合并过程。

public class DisjointSetUnion {
    private int[] dsu;

    public DisjointSetUnion(int n) {
        this.dsu = new int[n + 1];
        for (int i = 1; i <= n; i++) { // 合并前各自为政
            this.dsu[i] = i;
        }
    }

    /**
     * 认爹过程,查找节点 v 的根节点
     */
    public int getUnionRoot(int v) {
        if (dsu[v] == v) {
            return v;
        }
        // 查询过程中的路径压缩,降低每个节点与根节点的路径长度
        dsu[v] = getUnionRoot(dsu[v]);
        return dsu[v];
    }

    /**
     * u 和 v  不属于同一个团伙才可合并返回true结果
     */
    public boolean mergeUnion(int v, int u) {
        // 两个团伙合并时,要经过各自的老大来实现
        int t1 = getUnionRoot(v);
        int t2 = getUnionRoot(u);
        if (t1 != t2) {
            dsu[t2] = dsu[t1]; // 让 t2 归顺于 t1 节点
            return true;
        }
        return false;
    }

    public int[] getDsu() {
        return dsu;
    }
}

并查集—解密犯罪团伙: https://blog.csdn.net/wtyvhreal/article/details/43494647
算法学习笔记(1) : 并查集: https://zhuanlan.zhihu.com/p/93647900/
数据结构--并查集(Disjoint-Set):https://michael.blog.csdn.net/article/details/105294270

posted @ 2021-06-14 16:46  TomStudio  阅读(74)  评论(0)    收藏  举报