#图# 克鲁斯卡尔 与 并查集

#图# 克鲁斯卡尔 与 并查集


最近有一道数据结构的习题使用到了这两个知识点。简单总结一下。

克鲁斯卡尔算法

可以解决的问题:

  • 无向网的最小生成树。

算法思想:

  • 贪心。在对问题求解时,总是做出在当前看来是最好的选择。

算法步骤:

  1. 所有的边按权值从小到大排序。
  2. 选择权值边中当前最小的权值边。
  3. 判断已选择的边是否在已选好的边构成的连通分量。
  4. 若不在,则加入。

(写的太简略了,有点抽象)

在上述算法的第三步中,待选择的边不应在已选择的边构成的连通分量。不得不祭出并查集解决问题。

并查集

可以解决的问题:

  • 不相交集合(Disjoint Sets)的合并及查询问题。

算法思想

  • 树型的数据结构

算法过程

算法主体分为三个部分初始化查找合并

  1. 初始化。设置一个数组,所有点存在一个parent数组中并初始化为-1。
  2. 查找。这里采用优化算法即压缩路径。避免** 退化树**的产生,力求成为查找时的时间复杂度为o(1)!
  3. 合并算法

并查集算法简单实现

  1. 初始化。
int point_num;//parent数组的个数 全局变量

void UFset(int &parent[])
{
	for(int i = 0;i < point_num;++i)
	{
		parent[i] = -1;
	}
}
  1. 查找
int Find(int x)
{
	int temp = parent[temp];
	while(parent[temp] >= 0)
	{
		temp = parent[temp]
	}
	//减少树的高度,优化查找。
	while(x != temp)
	{
		int k = parent[x];
		parent[x] = temp;
		x = k;
	}
	return temp;
}
  1. 合并
//R1 & R2是两个待合并的结点
void Union(int R1,int R2,int &parent[])
{
	//求根
	int r1 = Find(R1);
	int r2 = Find(R2);
	int temp = parent[r1]+parent[r2];//两个集合元素之和
	//合并至集合元素多的根中
	if(parent[r1] > parent[r2])
	{
		parent[r1] = r2;
		parent[r2] = temp;
	}
	else
	{
		parent[r2] = r1;
		parent[r1] = temp;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值