并查集(Union Find):实现及其优化(c++)

1.什么是并查集

并查集是用来管理元素分组的数据结构。可以高效进行如下操作:

  • 查询元素a、b十是否在同一组
  • 合并a、b所在的组

并查集可以进行合并操作但不能进行分割操作。

2.并查集的结构

并查集采用多叉树形结构实现,每个元素对应一个结点,每个组对应一棵树。重点关注结整体形成一个树形结构,而不是树的形状等信息。

3.并查集的实现

3.1 初始化

对于并查集,一般采用数组来实现,其中元素为数组的索引,其父辈为数组索引对应内容。
在初始化中,将每个元素父辈设为自己,即自己形成一组,并对用一个rank数组记录以每个元素为根的树的层数,以方便后面并查集优化的实现。

    UnionFind(int count)
    {
        parent = new int[count];
        rank = new int[count];
        this->count = count;
        for (int i = 0; i < count; ++i)
        {
            parent[i] = i;
            rank[i] = 1;
        }
    }
1 2 3 4 5
parent 1 2 3 4 5

3.2 查找

为了查询两个节点否属于同一数组,需要采用查找两个节点的根,通过判断根是否相同来判断元素是否相同的方法。故查找用于实现查找元素的根。

在查找过程中采用路径压缩对组内进行优化,将树的层数降低,从而降低查找的复杂度,通常有两种压缩方法:

  • 采用递归实现,在查询过程中向上经过的所有节点都直接连到根上,将路径压缩至如下状态,使得查找时间复杂度降为 O(1),但路径压缩的过程则比较耗费时间。
    int find(int p)
    {
        assert(p >= 0 && p < count);
        /*****  路径压缩一:压缩过程耗时 *****/
        if(p != parent[p])
            parent[p] = find(parent[p]);        //递归实现路径压缩,最终find时间复杂度为 O(1)
        return parent[p];
    }
  • 采用循环,在查询过程中,将当前结点的父辈更改为当前父辈的父辈,则将路径压缩至如下状态,查找时间复杂度虽然未达到最优,但压缩时间开销相对较小。
    int find(int p)
    {
        assert(p >= 0 && p < count);
        /*****  路径压缩二:压缩过程快,find时间复杂度未达到 O(1)   *****/
        while (p != parent[p])
        {
            parent[p] = parent[parent[p]];
            p = parent[p];
        }
        return p;
    }

3.3 合并

将一组元素的根指向另一组元素的根,就实现了元素的合并:

  • 因为只要属于两个组的元素进行了合并,就相当于这两个组合并了。故两元素合并时先找到其所在组的根,再把根合并。
  • 在合并过程中,需要将层数低的数指向层数高的,以有效降低合并后树的高度,这时候就用到了我们初始化时使用的 rank 数组。

    void unionElements(int p, int q)
    {
        //合并优化,降低层数

        int pRoot = find(p);
        int qRoot = find(q);
        if(pRoot == qRoot)
            return;
        if(rank[pRoot] > rank[qRoot])
        {
            parent[qRoot] = pRoot;
        }
        else if(rank[pRoot] < rank[qRoot])
        {
            parent[pRoot] = qRoot;
        }
        else
        {   //rank[pRoot] == rank[qRoot]的情况
            parent[qRoot] = pRoot;
            rank[pRoot] += 1;
        }
    }

3.4 判断两元素是否如同组

判断元素的根是否相同,具体实现如下:

    bool isconnected(int p, int q)
    {
        return find(p) == find(q);
    }

4.小结

  • 通过优化后的并查集效率非常高。对于 n 个元素进行一次操作的复杂度时 O(a(n))。 a(n)时阿克曼(Ackermann)函数的反函数,比 O(log(n)) 还快。
  • 在最小生成树算法 Kruskal 中,需要判断一条边的两个顶点是否属于同一个连通分量,这时候需要并查集来进行高效的判断。

原文地址:https://www.cnblogs.com/joe-w/p/12323037.html

时间: 2024-11-12 08:45:15

并查集(Union Find):实现及其优化(c++)的相关文章

POJ 1611 The Suspects 并查集 Union Find

本题也是个标准的并查集题解. 操作完并查集之后,就是要找和0节点在同一个集合的元素有多少. 注意这个操作,须要先找到0的父母节点.然后查找有多少个节点的额父母节点和0的父母节点同样. 这个时候须要对每一个节点使用find parent操作.由于最后状态的时候,节点的parent不一定是本集合的根节点. #include <stdio.h> const int MAX_N = 30001; struct SubSet { int p, rank; }sub[MAX_N]; int N, M; v

【算法学习笔记】41.并查集 SJTU OJ 1283 Mixture

---恢复内容开始--- Description CC非常喜欢化学,并且特别喜欢把一大堆液体倒在一起. 现在CC有n种液体,其中m对会发生反应,现在她想把这n种液体按某种顺序倒入一个容器内,让她获得最刺激的体验,使危险系数尽量大. 我们可以这样计算危险系数,一开始容器内没有任何液体,危险系数为1.每次液体倒入容器时,若容器内已有一种或多种液体会与这种液体发生反应,则危险系数会乘2,否则危险系数不变. 请你求出把这n种液体倒在一起的最大危险系数. Input Format 第一行为两个数n和m.

ZOJ 2833-Friendship(并查集+优化)

Friendship Time Limit: 3 Seconds      Memory Limit: 32768 KB A friend is like a flower, a rose to be exact, Or maybe like a brand new gate that never comes unlatched. A friend is like an owl, both beautiful and wise. Or perhaps a friend is like a gho

并查集及其优化

并查集 概述 性质 一种树形结构 并查集算法不支持分割一个集合 元素 代表元 集合中的元素,用来代表这个集合 一个集合内的所有元素组织成以代表元为根的树形结构 parent[x] 对于每一个元素,parent[x]指向x在树形结构上的父亲节点.如果x是根节点,则令parent[x] = x 操作 MakeSet 初始化并查集 设置一个代表 function MakeSet(x) // 参数 => 选定的代表元 x.parent := x Find 确定元素属于哪一个子集,返回元素所属集合的代表元

普林斯顿公开课 算法1-10:并查集-优化的快速合并方法

应用 渗透问题 游戏中会用到. 动态连接 最近共同祖先 等价有限状态机 物理学Hoshen-Kopelman算法:就是对网格中的像素进行分块 Hinley-Milner多态类型推断 Kruskai最小生成树 Fortran等价语句编译 形态学开闭属性 Matlab中关于图像处理的bwlabel函数 渗透问题 一个N×N的矩阵,判断顶部和底部是否连通就是渗透问题. 下图中左侧的矩阵能渗透,右侧矩阵不能渗透. 渗透问题在电学.流体力学.社会交际中都有应用. 在游戏中可能需要生成一张地图,但是作为地图

并查集(union/find)

在计算机科学中,并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.有一个联合-查找算法(union-find algorithm)定义了两个操作用于此数据结构: Find:确定元素属于哪一个子集.它可以被用来确定两个元素是否属于同一子集. Union:将两个子集合并成同一个集合. 因为它支持这两种操作,一个不相交集也常被称为联合-查找数据结构(union-find data structure)或合并-查找集合(merge-find set

(贪心 + 并查集优化) poj 1456

Supermarket Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9452   Accepted: 4067 Description A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an int

Supermarket poj 1456 贪心+并查集优化

Language: Default Supermarket Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9512   Accepted: 4096 Description A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is

POJ 1456——Supermarket——————【贪心+并查集优化】

Supermarket Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1456 Description A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx