学渣都能看懂的-并查集(进阶版)-按秩归并

前置文章:学渣都能看懂的-并查集(快速掌握版)

比高度:
在并集时,我们直接让v1的代表元素指向了v2的代表元素。并集操作多了以后,会导致集合树的两边出现树的高度不均衡的情况,从而查集时因路径过长,查找时间过长。

void AddClass(int v1, int v2)//合并班级
{
	int v1_Class_Monitor = Find_Class_Monitor(v1), v2_Class_Monitor = Find_Class_Monitor(v2);
	//找到两个班长
	if (v1_Class_Monitor != v2_Class_Monitor)//班长不是同一个人,两个班合并
		Classmate[v1_Class_Monitor] = v2_Class_Monitor;
}

在这里插入图片描述
为使树两边能平衡,在合并前我们需要知道两个集合的树的高度,然后让高度小的树并入高度大的树中,以实现树的平衡。

我们用了一个数组来储存每个元素指向的下一个元素。我们在查集时,是用Classmate[mate] == -1来判断查到了代表元素。实际上,代表元素的Classmate[mate]的值并不一定要等于某个特定的值,我们只需要让其等于一个非任意元素所处序号的值就行了。例如:我们总共有n个元素,按1-n给这些元素排列,查集时,非代表元素会跳转到其他的非代表元素,直到跳转到代表元素为止。我们可以让代表元素在数组中的位置储存任意非序号内的元素。例:-1000,-1,0,n+1,n+100。

代表元素在数组中储存数据的灵活性使我们可以直接使用代表元素在数组中的数值来表示高度。我们可以直接让代表元素的数组以-x的形式(其中x表示集合树的高度)来表示该集合的树的高度。
我们先将数组全部初始化为-1,再在并集中加入对树的高度高低的判断与选择

for (int i = 1; i <= vnum; i++)//初始化,还未合并班级,每个班只有一个人,每个人都是班长,每个班的集合树的高度都为1
		Classmate[i] = -1;
void AddClass(int v1, int v2)//合并班级
{
	int v1_Class_Monitor = Find_Class_Monitor(v1), v2_Class_Monitor = Find_Class_Monitor(v2);
	//找到两个班长
	if (v1_Class_Monitor != v2_Class_Monitor)//班长不是同一个人,两个班合并
		if (Classmate[v1_Class_Monitor] > Classmate[v2_Class_Monitor])//v2所在集合树的高度高度高
			Classmate[v1_Class_Monitor] = v2_Class_Monitor;
		else
		{
			if (Classmate[v1_Class_Monitor] == Classmate[v2_Class_Monitor])
				Classmate[v1_Class_Monitor]--;//如果高度相等,树高+1
			Classmate[v2_Class_Monitor] = v1_Class_Monitor;
		}
}

比规模:
但是平衡的树不一定在查找起来最快,当其他分支的元素数量远大于高度最高的分支的元素数量时,平衡的树会使查找数据变长。所以对于某些数据,我们可以让Classmate数组中代表元素位置的数据储存-x(x为集合元素的数量)。(这样我们顺便能知道集合里元素的数量
在这里插入图片描述

void AddClass(int v1, int v2)//合并班级
{
	int v1_Class_Monitor = Find_Class_Monitor(v1), v2_Class_Monitor = Find_Class_Monitor(v2);
	//找到两个班长
	if (v1_Class_Monitor != v2_Class_Monitor)//班长不是同一个人,两个班合并
		if (Classmate[v1_Class_Monitor] > Classmate[v2_Class_Monitor])//v2所在集合树的元素数量多
		{	
			Classmate[v2_Class_Monitor] += Classmate[v1_Class_Monitor];
			Classmate[v1_Class_Monitor] = v2_Class_Monitor;
		}
		else//v1所在集合树的元素数量多
		{
			Classmate[v1_Class_Monitor] += Classmate[v2_Class_Monitor];
			Classmate[v2_Class_Monitor] = v1_Class_Monitor;
		}
}

当然我们一般难以辨别到底是用比高度还是比规模,在这里我推荐用功能性更强的比规模(可以获得集合中元素的个数)。按秩归并和路径压缩是两种对并查集的优化方法,其中路径压缩优化效率更高。在初学并查集时,路径压缩是一定要写的,不然数据量一大就会超时;而按秩归并有的老师不一定会教,所以我将按秩归并放在了进阶版。
推荐免费课程:浙江大学-数据结构-集合的简化表示(往后看4节)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值