并查集

	通过对并查集的学习发现,这是一个非常有用的高级数据结构,可以利用并查集来实现图中的最小生成树的Kruskal算法,非常有用。并查集用于处理不相交集合的合并问题,也可以看成对不同的连通分量之间的处理。例如以下问题:
	1.一个城市中有n个人,他们属于不同的帮派
	2.已知这些人的关系,例如1号,2号是朋友,1号,3号也是朋友,那么他们就属于同一个帮派。
	用并查集就可以和你简介的表示这个关系即相互认识的人构成一个连通分量。
	接下来开始讲解并查集的原理:
	首先是初始化问题,即各自就单独成为一个帮派,自己就是帮主。
	定义int father[]是以结点i为元素的并查集
initialize(){
	for (int i=0;i<n;i++)
		father[i] = i;
}

在这里插入图片描述

例如加入第一个关系,1和2是朋友关系,以此类推:
在并查集中,把节点1合并到结点2也就是father[1]改成2
在这里插入图片描述
将认识的人合并:

int find(int x)
{
	return x==father[x] ? x : find(father[x]);
}

void union(int x,int y)
{
	x = find(x);
	y = find(y);
	if (x != y)
		father[y] = x;
}

通过以上的代码,并查集的代码实现就完成了。
但是,这样的“简版”并查集还有很多优化的地方。

#合并的优化以及路径的优化:

const int MAX = 1000;
int height[MAX]; //需要一个辅助的树的高度的数组
void initialize()
{
	for (int i=1;i<=MAX;i++){
		father[i] = i;
		height[i] = 0;//空树高度为0
	}
}
int find(int x)
{
	if (x==father[x])
		return father[x];
	return father[x] = find(father[x]);
}

void union(int x,int y)
{
	x = find(x);
	y = find(y);
	if (height[x] == height[y]){
		father[x] = y;//将s[x]接到s[y]上
		height[y]++;
	}
	else{
		if (height[x] < height[y])
			father[x] = y;
		else
			father[y] = x;
	}
}

//由于find()函数是递归版,可能会爆栈
int find(int x)
{
	int r = x;
	while (r != father[r]) r = father[r];
	while (x != r)
	{
		int tmp = father[s];
		father[x] = r;
		x = tmp;
	}
	return r;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值