并查集(标准并查集、带权并查集、扩展域并查集)

什么是并查集?

并查集是一种数据结构,用来管理集合之间的关系,可以用来进行判断是否属于同一集合或将不同的集合合并等操作。

我们用个生活中的例子来说明一下

在这里插入图片描述
原本小明家这个集合只有小明,小红家只有小红,那么他们结婚后(合并)就属于一个家庭(一个集合),像这样,通过并查集我们能够合并不同的集合,然后还能快速地查找他们是不是同一个集合。

并查集的基本操作

合并集合的操作(将两个不同的集合合并)
在这里插入图片描述
这是两个不同的集合,我们想将两个集合合并的话,那么当然就是把2和4(接下来我们叫祖宗节点,一个集合一定只有一个祖宗节点,且祖宗节点的父节点等于它本身,因为祖宗节点往上没有节点了)连接起来就形成了一个集合。

在这里插入图片描述

查找祖宗节点(用于判断是否属于统一集合)

根据上图,我们要想找3的祖宗节点,就要递归找3这个节点的父节点的祖宗节点,一直递归,直到找到祖宗节点,如果每次都这样查找,每次查找的时间是O(logn)也就是高度次,看起来时间并不长,如果需要大量查找的话,就会大大降低效率,所以要引出路径压缩的操作,该如何操作呢?

我们希望:在第一次查询的时候,让路径上的每个节点都与祖宗节点相连,那么虽然在第一次查询的次数为高度
次,但下一次再次查询的时候,时间复杂度就会压缩成O(1).

在这里插入图片描述
下面用一道模板题来实现一下并查集的操作
在这里插入图片描述

#include<iostream>
using namespace std;
const int N=1e5+10;
int p[N];//记录该节点的父亲节点
int find(int x){
   
	//查找祖宗节点操作
	if(p[x]!=x){
   
	//如果该节点的父亲节点不是本身,说明不是祖宗节点
	p[x]=find(p[x]);//让父节点指向最终找到的父亲节点,递归
	}
	return p[x];//如果不是父节点等于本身,说明是祖宗节点,返回
}
int main(){
   
	int n,m;//n是数字个数,m是操作次数
	for(int i=1;i<=n;i++) p[i]=i;
	//一定要记得初始化,这样初始化的原因是因为一开始并没有集合合并
	//每个节点的父节点都是自己,也就是是说大家都是祖宗节点,都是不同的集合
	while(m--){
   
	char op[2];int a,b;
	scanf("%s%d%d",op,&a,&b);
	if(*op=='M'){
   
	p[find(a)]=find(b);//这个操作是指,a的祖宗节点的父节点是b的祖宗节点,目的就是让两个集合连接
	}
	else{
   
	if(find(a)==find(b)) puts("Yes");
	else puts("No");
	}
	}
	return 0;
}

以上是标准并查集的一些基本操作,接下来来介绍两个标准并查集的变种:带权并查集和扩展域并查集。并用一道经典例题来介绍这两种并查集的使用。
例题如下:
在这里插入图片描述
在这里插入图片描述</

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值