并查集及其超级优化

1.什么是并查集

并查集是一种简单的集合表示,通常是将几种不同集合表示成一个具体的概念。比如说人群中有喜欢吃青葡萄的、有喜欢吃紫葡萄的,还有喜欢吃橘子的。并且对这集合的操作只有简单的查找和将其中俩个集合并起来的操作,即为并查集。

2.存储结构

因为并查集里有多个无关的集合,而每一个集合又需要一个具体能代表的操作,因此我们可以选择用树形结构的顺序存储来存储。但是树有孩子表示法,双亲表示法和孩子兄弟表示法。根据并查集的并操作可以了解,用树形结构时就只需要判断每个集合树的根节点,并将其中的一个根结点连接到另一个结点的孩子中,即完成并操作,因此我们需要用双亲表示法的顺序存储来表示。

                        0    -1
                        10

3.结构定义

#define SIZE 13;
int UFSets[SIZE];//集合元素数组

4.初始化操作

//初始化
void Initial(int S[]){
	for(int i=0;i<SIZE;i++)
		S[i]=-1;
} 

5.find操作(时间复杂度为O(n))

//在并查集中查找并返回包含元素X的树的根
int Find(int S[],int x) {
	while(S[x]>0)
		x=S[x];
	return x;
}

6.并操作(时间复杂度为O(1))

//求两个不相交子集合的并集
void Union(int S[],int Root1,int Root2){
	if(Root1==Root2)		//需要两个子集属于不同集合 
		return;
	S[Root2]=Root1;			//将Root2连接到另一根Root1下 
} 

7.优化操作

通过上面代码发现,Find操作与树的高度有关。因此首先优化并操作,通过将小树(高度较低的树)并到大树下,则用双亲表示法时,根结点的值为树的结点树的负数

0-结点数
//小树合并到大树
void Union(int S[],int Root1,int Root2){
	if(Root1==Root2)		//需要两个子集属于不同集合 
		return;
	if(S[Root1]>S[Roo2]){
		S[Root1]+=S[Root2];
		S[Root2]=Root1;
	}else{
		S[Root2]+=S[Root1];
		S[Root1]=Roo2;
	}
} 

目录

1.什么是并查集

2.存储结构

3.结构定义

4.初始化操作

5.find操作(时间复杂度为O(n))

6.并操作(时间复杂度为O(1))

7.优化操作

8.查操作优化


我们可以先找到根节点,然后通过查找根节点的路径,把路径上的节点的双亲表示为根节点,这样优化时间为O(a(n)),接近于常量级的时间复杂度

//在并查集中查找并返回包含元素X的树的根
int Find2(int S[],int x) {
	int root=x;
	while(S[root]>0)
		root=S[root];		//找到根节点
	while(x!=root){			//压缩路径 
		int t=S[x];			//t指向x的父节点
		S[x]=root; 			//修改双亲节点为根节点 
		x=t;
	} 
	return root;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程的小李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值