详解并查集

并查集

并查集可以说是判断图中的两个元素是否属于同一个连通分量之中

一.并查集是什么?

并查集可以用来管理元素分组的情况,也就是并查集可以高效合并两个元素,也可以判断两个元素是否属于同一个组

现在有一堆元素,当你每次查询某两个元素是否属于一个集合的时候,一般来说数据量很大,每次需要花费很多的时间。而并查集利用树结构就能够很高效的查找到元素的祖宗节点是否是一样的,从而来判断是否属于同一个集合。

二.并查集的操作

1.初始化

我们有n个元素,每个元素各属于自己的这个集合,所以有n个节点且没有边连接。
在这里插入图片描述

2.合并

当某两个节点之间有关系的时候就把他们用边连接起来,即为一个集合。
在这里插入图片描述
这个时候(1,2,3)是一个集合,(4,5)是一个集合,但是具体是怎样查询的呢?

3.查询

为了查询两个节点是否属于同一个集合,我们只需要沿着这棵树找到他的根节点是否一样,就可以判断他们两个是不是属于同一个集合。
在这里插入图片描述
如上所示,2,3是属于同一个集合,因为他们有着共同的根1,,而2,5则是不同的集合,因为他们的根节点不同。

但是像(2.合并)所示里面那棵树一样,那么树型结构就发生了退化,变成了线性的,复杂度就会变得很高,那么我们如何想办法避免退化呢?

4.路径压缩

要想要使并查集更高效就得使树上的层次最少
那么我们就可以记录树的高度,使高度低的连接上高度高的(路径压缩1)
在这里插入图片描述在这里插入图片描述
同时还可以每次向上查询到了根节点,就把该节点以及路上节点的边从连接其父节点改为连接根节点(路径压缩2),这样下次再查询到该节点的时候就可以很快知道根是谁,能够够快判断是否属于同一个集合。

三.并查集的代码

//初始化并查集,每个节点的根节点是他本身,高度也为0
void  init(int n)
{
	for(int i = 0; i < n; i++)
	{
		p[i] = i;
		r[i] = 0;
	}//p数组记录父节点的编号,r数组记录高度
}

//查询树的根,并把连接非根节点的边连接到根节点
//路径压缩2
int find(int x)
{
	//假如根节点是它本身,返回自己
	if(p[x] == x)
		return x;
	//否则就递归寻找父节点的父节点是不是根节点
	else
		return p[x] = find(p[x]);
}

//合并节点x和节点y的集合
void unite(int x,int y)
{
	//首先查找他们的根节点,判断是否一致
	x = find(x);
	y = find(y);
	if(x == y)
		return ;
	
	//把高度低的加在高度高的下面
	if(r[x] < r[y])
		p[x] = y;
	else
	{
		p[y] = x;
		
		//假如高度一样的话,把y加到x下面就会多一层
		//所以x的高度要加1
		if(r[x] == r[y])
			r[x]++;
	}
}

//判断两个节点是否属于同一个集合
//c++写法
bool same(int x, int y)
	return find(x) == find(y);

//c语言写法,因为C语言没有bool值,所以用1为真,0为假
int same(int x,int y)
	return find(x) == find(y)? 1 : 0;		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值