并查集总结

并查集是一种高效处理集合合并查询的数据结构,常用于不相交集合问题。它支持合并和查询操作,初始时每个元素独立。查询通过递归或循环找到集合代表元素;合并操作则通过路径压缩或按秩合并来优化,以保持树的平衡,提高效率。路径压缩通过递归查询时更新父节点,按秩合并则根据树的秩选择代表元素,避免树过高。
摘要由CSDN通过智能技术生成

并查集总结

在这里插入图片描述
在一些N元素集合问题中,通常在开始时让每个元素构成一个单元素集合,然后按一定顺序将元素合并,数据量大时,应用并查集描述节省时间与空间。
并查集是一种树形数据结构,用于处理一些不相交的集合合并与查询问题。通常支持两种操作:
合并(Union):把两个不相交的集合合并为一个集合。
查询(Find):查询两个元素是否在同一个集合,通常依据一个集合的代表元素。

这是一个树状结构,要寻找集合的代表元素,只需要一层一层往上访问父节点,直到达到树的根节点,树的根节点的父节点是自己。

初始化
开始时每个元素自成一派;

int parent[MAX];
void Build(){
	for(register int i=1;i<=n;i++){
		parent[i]=i;
	}
}

在这里插入图片描述
查询
可以采用递归和循环的方式,我这里采用递归。`

inline int Find(int x){
	if(parent[x]!=x){//只有根节点的parent为自身
		return Find(parent[x]);
	}
	return x;
}

合并

inline void Union(int x,int y){
	parent[Find(x)]=Find(y);//实质是将一个集合挂到另一个集合上
}

但上面的操作执行之后,我们很容易发现所构成的树形结构成了单支树,这样会导致查找效率不高,因此产生了一种路径压缩的办法,其核心思想就是尽量减少树的高度:将每个结点的父节点直接设为集合的代表元素。
在Find时进行路径压缩

int Find_2(int x){
	if(parent[x]!=x){
		parent[x]=Find(parent[x]);
	}
	return parent[x];
}

通常可以简化为:

int Find_3(int x){
	return parent[x]==x ? parent[x] : (parent[x]=Find(parent[x]));//?:优先级比=高,加()
}

很多人可能有个误解,以为路径压缩后,并查集都是一个二层树结构,事实上,路径压缩只在查询时进行,在一般情况下,并查集还是比较复杂的结构。
那如果我们有一个复杂的树和单元素集合合并,那我们应选哪个集合的代表元素呢?
显然我们的原则是尽量不增加树的高度。

基于树的高度我们增加一个rank数组,用于记录一个树的高度。

按秩合并

初始化

void Build(){
	for(int i=1;i<=n;i++){
		parent[i]=i;
		rank[i]=1;
	}
}

合并(按秩合并)

void Union(int x,int y){
	x=Find(x);
	y=Find(y);
	if(x==y) return;
	if(rank[x]<rank[y]){
		parent[x]=y;
	}else{
		parent[y]=x;
		if(rank[x]==rank[y]){
			rank[x]++;
		}
	}
}

通常在代码中,选用一种优化方案即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值