C++数据结构之并查集详解

 更新时间:2023年08月29日 09:59:56   作者:CodeRanger  
这篇文章主要介绍了C++数据结构之并查集详解,并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题,并查集的思想是用一个数组表示了整片森林,需要的朋友可以参考下

一、概念:

并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。

并查集的思想是用一个数组表示了整片森林(parent),树的根节点唯一标识了一个集合

我们只要找到了某个元素的的树根,就能确定它在哪个集合里。

二、用法:

并查集用在一些有 N 个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。

这个过程看似并不复杂,但数据量极大,若用其他的数据结构来描述的话,往往在空间上过大,计算机无法承受,也无法在短时间内计算出结果,所以只能用并查集来处理。

简述一下:

1,将两个集合合并。

2,询问两个集合是否在同一集合中。

三、基本原理:

每个集合用一颗树来储存。树的根节点编号是每个集合的编号。

每个节点存储它的父节点,p[x]表示x的父节点。

四、常见问题/要处理的问题:

1,如何判断树根:if(p[x]==x)

2,如何求x的集合编号: while(p[x]!=x) x=p[x] (对照用法二)

3,如何合并两个集合:px是x的集合边界,py是y的编号集合。p[x]=y

实践题目:

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

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

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

输入格式

第一行输入整数 n 和 m。

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

输出格式

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

每个结果占一行。

数据范围

1≤n,m≤10^5   

1≤n,m≤10^5

输入样例:

4 5
M 1 2
M 3 4
Q 1 2
Q 1 3
Q 3 4

输出样例:

Yes
No
Yes

先上代码:

#include<iostream>
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(){
	char op[2];
	int n,i,j,k,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		p[i]=i;
	}
	while(m--){
		int a,b;
		cin>>op>>a>>b;
		if(op[0]=='M'){
			p[find(a)]=find(b);
		}
		else{
			if(find(a)==find(b)){
				cout<<"Yes"<<endl;
			}
			else{
				cout<<"No"<<endl;
			}
		}
	}
	return 0;	
}

解读思路:

初始化:由于一开始我们得到的是几个散乱的集合,即每个数都是一个集合,所以我们初始化为 p[x]=x ,这就表示他自己就是一个集合,也可以说成他就是自己的父节点/祖宗节点。

集合合并与查找:假如我们有{1},{2}这两个单独集合,我们要把它合成一个集合,就需要把他们的祖宗节点变成一个,就是上面说到的 p[x]=p[y]=x

注:这里以谁为父节点是按你输入的顺序定的马,可以理解为随机的,例如你第一个数是1,那么之后的想要把其他数都合并在1这个数的集合里,那么他们的父节点为 p[1]=p[2]=p[3]=....p[n]=1 )之后集合就成了{1 , 2}。

那么我们的查找操作也相应完成了,既然都在一个集合里,都有一个父节点,判断两个数是否在一个集合里直接比较父节点即可,高效准确。

find()函数:这里建议自己模拟一遍。如果此时我们已经将1,2合并到一个集合中去,此时把1再执行一边find函数,根据代码:p[1]=2 -> !=1 -> p[1]=find(2) -> p[2]=2 -> return 2  结束函数。

好,我们加一问,询问某个数所在集合中的元素数量。

代码:

#include<iostream>
using namespace std;
const int N = 100010;
int p[N];
int siz[N];
int find(int x){
	if(p[x]!=x){
		p[x]=find(p[x]);
	}
	return p[x];
}
int main(){
	char op[2];
	int n,i,j,k,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		p[i]=i;
		size[i]=1;
	}
	while(m--){
		int a,b;
		cin>>op;
		if(op[1]=='1'){
			cin>>a>>b;
			if(find(a)==find(b)){
				cout<<"Yes"<<endl;
			}
			else{
				cout<<"No"<<endl;
			}
		}
		else if(op[0]=='C'){
			cin>>a>>b;
			if(find(a)==find(b)){
				continue;//注意特判,否则重复相加个数
			}
			siz[find(b)]+=siz[find(a)];
			p[find(a)]=find(b);
		}
		else{
			cin>>a;
			cout<<siz[find(a)]<<endl;
		}
	}
	return 0;	
}

思路大致相同,要找某个数所在集合中元素的个数,我们也只需找到他的父节点的标号下的元素个数即可。

我们需要开一个size[]数组存放元素个数,例如还是举上面的例子:1,2,3在同一个集合里,他们的父节点是p[2]=2,那么他们的size的值也都变成size[2]=size[3]=size[1]=3,另外这个数组也是需要维护更新的

我们看具体操作:先初始化,size[i]=1,之后相加即可。

为什么siz[]里面的参数是find(x)呢,原因还是要找到相同的父节点。

到此这篇关于C++数据结构之并查集详解的文章就介绍到这了,更多相关C++并查集内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 华为云CodeArts IDE Online快速入门和使用

    华为云CodeArts IDE Online快速入门和使用

    华为云CodeArts IDE Online服务,提供了可随时随地编码的云上开发环境,同时具备开放的生态和独立插件市场,本文主要介绍了华为云CodeArts IDE Online快速入门和使用,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • C语言实现简易连连看游戏

    C语言实现简易连连看游戏

    这篇文章主要为大家详细介绍了C语言实现简易连连看游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 深入C++实现函数itoa()的分析

    深入C++实现函数itoa()的分析

    本篇文章是对C++实现函数itoa()进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • VS2022 CUDA环境配置的实现步骤

    VS2022 CUDA环境配置的实现步骤

    本文主要介绍了VS2022 CUDA环境配置的实现步骤,文中通过图文示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Qt利用QNetwork实现上传数据的示例代码

    Qt利用QNetwork实现上传数据的示例代码

    这篇文章主要为大家详细介绍了Qt如何利用QNetwork实现上传数据的 功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-02-02
  • C++简易版Tensor实现方法详解

    C++简易版Tensor实现方法详解

    这篇文章主要介绍了C++简易版Tensor的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
    2022-08-08
  • 如何利用C语言实现最简单的HTTP服务器详解

    如何利用C语言实现最简单的HTTP服务器详解

    这篇文章主要给大家介绍了关于如何利用C语言实现最简单的HTTP服务器的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C语言具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-11-11
  • C++中vector<vector<int> >的基本使用方法

    C++中vector<vector<int> >的基本使用方法

    vector<vector<int> >其实就是容器嵌套容器,外层容器的元素类型是vector<int>,下面这篇文章主要给大家介绍了关于C++中vector<vector<int> >的基本使用方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • C语言编程计算信噪比SNR理解学习

    C语言编程计算信噪比SNR理解学习

    这篇文章主要介绍了C语言编程信噪比SNR计算的理解学习,信噪比,英文名称叫做SNR或S/N(SIGNAL-NOISE RATIO)。是指一个电子设备或者电子系统中信号与噪声的比例
    2021-10-10
  • C++继承和多态的用法解读

    C++继承和多态的用法解读

    这篇文章主要介绍了C++继承和多态的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06

最新评论