数据结构-并查集

简介: 数据结构-并查集

文章目录


一、并查集概述

1. 定义

2. 作用

3. 主要操作

二、并查集思想

1. 暴力做法

2. 并查集做法

3. 并查集优化

3.1 路径压缩

3.2 按秩合并(使用较少)

4. 并查集实现详见例题——合并集合

三、并查集例题——合并集合

具体实现

1. 实现思路

2. 代码注解

3. 实现代码

四、并查集例题——连通块中点的数量

具体实现

1. 样例模拟

2. 实现思路

3. 代码注解

4. 实现代码

五、并查集例题——食物链(较难)

具体实现

1. 样例分析

2. 实现思路

3. 代码注解

4. 实现代码



一、并查集概述

  • 并查集代码很短,思维精巧,在面试和比赛当中是一种很常用的数据结构。

1. 定义


  • 并、查、集,这个三个字,其中前面两个字都是动词,第三个字是个名词。
  • 集就是集合,就是将一堆元素没有顺序地摆放在同一个地方。
  • 因此并查集的本质就是对集合进行操作。
  • 并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。常常在使用中以森林来表示。


2. 作用

  • (1) 将两个集合合并。
  • (2) 询问两个元素是否在一个集合当中



3. 主要操作

初始化:把每个点所在集合初始化为其自身。通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为 O(N) 。

查找:查找元素所在的集合,即根节点。

合并:将两个元素所在的集合合并为一个集合。通常来说,合并之前,应先判断两个元素是否属于同一集合,这可用上面的查找操作实现。


二、并查集思想

1. 暴力做法


对于如下图所示的两个集合,如果我们要判断H和A是否在同一个集合中,我们需要遍历A所在的集合,并逐一判断当前节点是否是H节点,直到最后遍历完整个蓝色集合,才能判断出H节点不在这个集合中。

5368b6754b634fffa3b658c215325b98.png


  • 同样的,如果我们需要合并两个集合,就需要遍历整个黄色的集合,将里面的节点一个一个加入到蓝色集合中。两者都是 O(N) 的时间复杂度。
  • 暴力做法一般是用来给我们提供优化的思路,整体比较简单易想,因此便不过多叙述。



2. 并查集做法


在我们生成集合的时候,就人为地将集合中的元素之间创建某种关联。那么查询和合并的操作将会省时很多。形成如下图的结构:

09f1048c19654bbca1f98006953d2e64.png


  • 对结构进行优化,我们可以发现这两个结构其实就是一个树。会形成近乎 O(1) 的时间复杂度。

97abd354af0a4f6987aafc59ab2bd795.png

  • 对于每一个点,我们都存储一下他的父节点是谁,当我们想求某个点是否属于集合当中,也就是查询操作时,就可以根据这个点的父节点是不是根节点,如果不是,就继续向上查找,直到找到根节点为止,根节点的编号就是整个集合的编号。因此,可以用这种方式快速进行查询操作
  • 那么,便会产生如下问题:


(1) 如何判断是不是根节点? 答:if ( p[x] == x ) 。

(2) 如何求 x 的集合编号? 答:while ( p[x] != x) x = p[x] 。

(3) 如何合并两个集合? 答:将一个树根节点的父节点设为另一个树。即:px 是 x 的集合编号,py 是 y 的集合编号,使得 p[x] = y 。


3. 并查集优化

3.1 路径压缩


  • 思想:每次查找时,如果路径较长,则修改信息,以便下次查找的时候速度更快。
  • 实现:(1) 找到根节点。(2) 修改查找路径上的所有节点,将他们都指向根节点。


3.2 按秩合并(使用较少)


很多人有一个误解,就是认为并查集经过路径压缩优化之后,并查集是只有两层的一颗树,其实不是的。因为路径压缩只在查找的时候进行,也只压缩一条路径,所有并查集的最终结构仍然可能是比较复杂的。


思想:应该把简单的树往复杂的树上合并,即把树的深度小的树合并到树的深度大的树中,这样合并之后,每个元素到根结点的距离变成的元素个数最少。

实现:用 rank[ ] 数组来记录每个根结点对应的树的深度(如果不是根结点,则 rank 中的元素大小表示的是以当前结点作为根结点的子树的深度);一开始,把所有元素的 rank 设为 1 ,即自己就为一颗树,且深度为 1 ;合并的时候,比较两个根结点,把 rank 较小者合并到较大者中去。


4. 并查集实现详见例题——合并集合


三、并查集例题——合并集合

题目描述


一共有 n 个数,编号是 1∼n,最开始每个数各自在一个集合中。

现在要进行 m 个操作,操作共有两种:


  • M a b,将编号为 a 和 b 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作。
  • Q a b,询问编号为 a 和 b 的两个数是否在同一个集合中。


输入格式

第一行输入整数 n 和 m。

接下来 m 行,每行包含一个操作指令,指令为 M a bQ a b 中的一种。


输出格式

对于每个询问指令 Q a b,都要输出一个结果,如果 a 和 b 在同一集合内,则输出 Yes,否则输出 No

每个结果占一行。

数据范围


1 ≤ n,m ≤ 1e5

输入样例

4 5

M 1 2

M 3 4

Q 1 2

Q 1 3

Q 3 4

输出样例

Yes

No

Yes


具体实现

1. 实现思路

  • 见上文。

2. 代码注解


p[N] 是父节点数组。

p[i] = i 所有节点一开始赋值给自己。

int find (int x) 返回 x 的祖宗节点,包含路径压缩。

p[find(a)] = find(b) a 的祖宗节点的父节点等于 b 的祖宗节点,把 a 节点对应集合合并到 b 节点对应集合。

if (find(a) == find(b)) 如果 a 和 b 的祖宗节点一样的话,就说明在同一个集合里面。


3. 实现代码

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int p[N];
int find (int x)
{
    if (p[x] != x) 
    {
        p[x] = find(p[x]);
    }
    return p[x];
}
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) 
    {
        p[i] = i;
    }
    while (m -- )
    {
        char op[2];
        int a, b;
        cin >> op >> a >> b;
        if (*op == 'M')
        {
            p[find(a)] = find(b);
        }
        else
        {
            if (find(a) == find(b)) 
            {
                puts("Yes");
            }
            else 
            {
                puts("No");
            }
        }
    }
    system("pause");
    return 0;
}


相关文章
|
容器
数据结构:并查集
数据结构:并查集
206 0
数据结构:并查集
|
算法 开发者 计算机视觉
燃爆全场!Python并查集:数据结构界的网红,让你的代码炫酷无比!
在编程的世界里,总有一些数据结构以其独特的魅力和高效的性能脱颖而出,成为众多开发者追捧的“网红”。今天,我们要介绍的这位明星,就是Python中的并查集(Union-Find)——它不仅在解决特定问题上大放异彩,更以其优雅的设计和强大的功能,让你的代码炫酷无比,燃爆全场!
170 0
|
机器学习/深度学习 存储
数据结构(九)---并查集
数据结构(九)---并查集
502 5
|
Python
逆天改命!掌握Python并查集,数据结构难题从此不再是你的痛!
在编程旅程中,遇到棘手的数据结构难题是否让你苦恼?别担心,Python并查集(Union-Find)是你的得力助手。这是一种高效处理不相交集合合并及查询的数据结构,广泛应用于网络连通性、社交网络圈子划分等场景。通过维护每个集合的根节点,它实现了快速合并与查询。本文将介绍并查集的基本概念、应用场景以及如何在Python中轻松实现并查集,帮助你轻松应对各种数据结构挑战。
134 3
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
443 2
|
算法 程序员 图形学
脑洞大开!Python并查集:用最简单的方式,解决最复杂的数据结构问题!
【7月更文挑战第17天】并查集,数据结构明星,处理不相交集合合并与查询。Python实现核心操作:查找与合并。路径压缩优化查找,按秩合并保持平衡。实战应用如图连通性判断,算法竞赛利器。掌握并查集,解锁复杂问题简单解法,照亮编程之旅!
196 10
|
Python
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
131 0
|
算法 开发者 计算机视觉
Python并查集:数据结构界的肌肉男,让你在编程路上无所畏惧!
在编程的浩瀚宇宙中,数据结构如同基石,构建了解决问题的坚实框架。而并查集(Union-Find),这位数据结构界的“肌肉男”,以其独特的魅力和强大的功能,让无数开发者在面对复杂关系处理时,都能感受到前所未有的从容与自信。今天,就让我们一同揭开并查集的神秘面纱,看看它是如何成为你编程路上的得力助手的。
107 0
|
算法 程序员 计算机视觉
Python并查集:数据结构界的肌肉男,让你在编程路上无所畏惧!
并查集,一种处理不相交集合合并与查询的数据结构,被誉为编程的“肌肉男”。它提供Find(找根节点)和Union(合并集合)操作,常用于好友关系判断、图像处理、集合合并等。Python实现中,路径压缩和按秩合并优化效率。并查集的高效性能使其成为解决问题的强大工具,助力程序员应对复杂挑战。
105 0
|
Python
告别低效!Python并查集:数据结构界的超级英雄,拯救你的编程人生!
【7月更文挑战第18天】并查集,数据结构超级英雄,用于不相交集合的合并与查询。Python实现包括初始化、查找根节点和合并操作。应用广泛,如社交网络分析、图论问题、集合划分等。示例代码展示了解决岛屿数量问题,统计连通的“1”单元格数。掌握并查集,提升编程效率,解决复杂问题。
180 6

热门文章

最新文章