C++高级数据结构之并查集

C++高级数据结构之并查集

什么是并查集

并查集(Union Find Set)是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。

并查集定义了如下的三种操作:

1、makeSet(s):建立一个新的并查集,其中包含s个单元素集合。

2、unionSet(x, y):把元素x和元素y所在的集合合并,要求x和y所在的集合不相交,如果相交则不合并。

3、find(x):找到元素x所在的集合的代表,可用于判断两个元素是否处在同一个集合中。

这三种操作的时间复杂度都不超过O(log2n),其中n是元素的个数。

并查集的实现

并查集通常采用数组来实现,如果要表示多个集合,就把这个数组当成一个森林,树的根节点表示一个集合。

int father[N]; // 父节点数组

// 初始化
for (int i = 0; i < N; i++) {
    father[i] = i;
}

// 查找
int find(int x) {
    if (father[x] != x) father[x] = find(father[x]);
    return father[x];
}

// 合并
void unionSet(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx != fy) father[fx] = fy;
}

上面的代码实现就是采用了路径压缩,每次查找时直接将x的祖先节点赋值为根节点。

并查集的应用

并查集在解决一些组团及连通性问题非常高效。

例一

LeetCode 1319 连通网络的操作次数

题目描述:

一个计算机连接网络,需要进行n次操作。每次操作选择两台已经连接到网络上的电脑x、y,并且使它们之间产生一条新的连接。如果这两台电脑已经有直接的连接或者通过其他电脑建立了连接,那么将不再重复执行连接。计算机通过网络连接后可以形成若干个分组。其中网络连接次数最少的操作顺序,输入为n对互不相同的正整数x、y,表示连接x号计算机和y号计算机。连接计算机时连接次数不超过n-1次。

输入:4

[[0,1],[0,2],[1,2]]

输出:1

解释:

先连接 0 和 1,需要一次操作。

再连接 1 和 2,需要一次操作。

总共需要 2 次操作。

代码如下:

class Solution {
public:
    int father[10005];
    int n;

    int find(int x) {
        if (father[x] != x) father[x] = find(father[x]);
        return father[x];
    }

    int makeSet() {
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            father[i] = i;
            cnt++;
        }
        return cnt;
    }

    int unionSet(int x, int y) {
        int fx = find(x), fy = find(y);
        if (fx == fy) return 0;
        father[fx] = fy;
        return 1;
    }

    int makeConnected(int _n, vector<vector<int>>& connections) {
        int m = connections.size();
        n = _n;
        int groups = makeSet();
        for (int i = 0; i < m; i++) {
            groups - unionSet(connections[i][0], connections[i][1]);
        }
        if (groups > 1) return -1;
        return m - (n - 1);
    }
};

例二

P4003 [NOI2011]修建道路

题目描述:

小明所在的城市有n个交叉路口,它们之间有m条道路相连。如果两个路口之间有一条以上的道路相连,就认为它们之间的道路路况比较拥挤。现在小明受委托要对这些道路中的某些道路进行改造,以减少道路障碍,使得道路拥挤程度最低。

输入格式
第一行输入整数n,m,表示交叉路口数和道路条数。

接下来m行,每行输入两个整数x,y,表示x,y之间有一条双向的道路。

输出格式
一行输出一个整数,表示改造完毕后道路的拥挤程度。

数据范围
2≤n≤20000,
m≤100000

输入样例:
5 6
1 2
1 3
1 4
1 5
2 3
3 4
输出样例:
1

代码如下:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 20010, M = 100010;

int n, m;
int p[N], cnt[N];

struct Edge {
    int a, b;
}edges[M];

int find(int x) {
    if (x != p[x]) p[x] = find(p[x]);
    return p[x];
}

int main() {
    cin >> n >> m;

    for (int i = 1; i <= n; i++) p[i] = i, cnt[i] = 1;

    for (int i = 0; i < m; i++) cin >> edges[i].a >> edges[i].b;

    int res = n;

    for (int i = 0; i < m; i++) {
        int a = edges[i].a, b = edges[i].b;
        if (find(a) != find(b)) {
            p[find(a)] = find(b);
            cnt[find(b)] += cnt[find(a)];
            res--;
        }
    }

    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (p[i] == i) ans = max(ans, cnt[i]);
    }

    cout << res - ans << endl;

    return 0;
}

总结

并查集非常适用于组团和连通性问题,在$O(log_2n)$的时间复杂度内可以完成查找、合并两个集合、判断两个节点是否在同一个集合中的操作。在实现时,采用路径压缩的方法,可以大大提高并查集的效率。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++高级数据结构之并查集 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Java数据结构之链表实现(单向、双向链表及链表反转)

    Java数据结构之链表实现 链表基础概念 链表是一种数据结构,它由一系列节点(Node)组成,每个节点包含两个部分,一个是数据域(data),一个是指针域(next)。数据域存储数据信息,指针域指向下一个节点。 链表的种类很多,比如单向链表、双向链表、循环链表等等。 单向链表:链表的每个节点只有一个指针域,指向下一个节点。 双向链表:链表的每个节点有两个指针…

    数据结构 2023年5月17日
    00
  • java数据结构之实现双向链表的示例

    Java数据结构之实现双向链表的示例 1. 什么是双向链表? 双向链表,英文名为doubly linked list,是一种链表结构。与单向链表不同,双向链表中的每一个节点除了保存了指向下一个节点的指针外,还保存了指向前一个节点的指针。因此,双向链表可双向遍历,可以从前向后或从后向前遍历。 2. 双向链表的实现 2.1 节点类的实现 创建节点类Node,并定…

    数据结构 2023年5月17日
    00
  • C语言近万字为你讲透树与二叉树

    C语言近万字为你讲透树与二叉树 什么是树? 树是一种用来组织数据的非线性数据结构,它由一个根节点和若干个子节点组成,并且每个节点可能有若干个子节点。 什么是二叉树? 二叉树是一种特殊的树,它的每个节点最多只有两个子节点,并且分别称为左子节点和右子节点,左子节点在二叉树中永远排在右子节点的前面。 二叉树的遍历方式 二叉树的遍历方式有三种: 前序遍历(preor…

    数据结构 2023年5月17日
    00
  • MySQL索引背后的数据结构及算法原理详解

    《MySQL索引背后的数据结构及算法原理详解》是一篇介绍MySQL索引背后的数据结构和算法原理的文章。MySQL索引是提高查询效率的一个重要工具,理解其背后的数据结构和算法原理对于提高数据库性能和优化查询操作是非常有帮助的。 本文主要分为以下三部分: MySQL索引背后的数据结构 索引的几种常见数据结构及其优缺点 索引的算法原理 MySQL索引背后的数据结构…

    数据结构 2023年5月17日
    00
  • 使用C语言详解霍夫曼树数据结构

    使用C语言详解霍夫曼树数据结构 什么是霍夫曼树 霍夫曼树是一种带权路径长度最短的树,也称为最优二叉树,它是优化编码的核心算法。 在霍夫曼树中,每个叶子节点对应一个字符,该节点的权值为该字符出现的次数。当然,字符可以是任何数据类型。生成霍夫曼树后,在对每个字符进行编码时,字符在霍夫曼树中的路径即为其编码。(一般规定,一条从根到叶子的路径上只出现0或1,从根到某…

    数据结构 2023年5月17日
    00
  • 关于图片存储格式的整理(BMP格式介绍)

    关于图片存储格式的整理(BMP格式介绍) 一、BMP格式概述 BMP全称为Bitmap,是一种基础的图像保存格式,它的格式十分简单,就是将每个像素点的颜色信息直接保存在文件中,因此它的信息量相对较大。 BMP格式的文件头有标准结构,其中包含位图的宽、高、颜色数、位图大小等信息,其中颜色数的位数(色深)决定了BMP文件的大小。BMP文件还可以包含调色板,来进行…

    数据结构 2023年5月17日
    00
  • C++二叉树结构的建立与基本操作

    C++二叉树是一种非常常见的数据结构,同时也是算法中经常使用的一种数据结构。本文将详细讲解C++二叉树的建立和基本操作,包括二叉树的定义、创建、遍历和删除等。 1. 二叉树的定义 二叉树是一种树形结构,每个节点最多只有两个子节点:左子节点和右子节点。树的深度取决于有多少个节点,根节点是最顶端的节点,不再有父节点。节点之间存在一些有天然排序关系且有先后性的关系…

    数据结构 2023年5月17日
    00
  • Java常见数据结构面试题(带答案)

    Java常见数据结构面试题(带答案)完整攻略 介绍 在Java面试中,数据结构不可避免地成为一部分的考察内容。因此,掌握Java常见数据结构,对于提高面试成功率十分必要。本篇攻略将会介绍常见的Java数据结构,并提供相应的面试题目和答案,希望可以帮助面试者在面试当中更好地展示自己的实力。 目录 结构体 数组 链表 栈 队列 树 哈希表 结构体 在Java中并…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部