[图] 最小生成树-克鲁斯卡尔算法Kruskal O(eloge)稀疏图-C语言实现-gif图演示

文章目录

  • 克鲁斯卡尔算法Kruskal
    • 思想
    • 性能
    • 举例
    • 实现案例

克鲁斯卡尔算法Kruskal

思想

为使生成树上边的权值之和达到最小,则应使生成树中每一条边的权值尽可能地小。

【理解】

  1. 每一轮选一个最小的边,将边的顶点并入生成树中,直到全部顶点都在生成树中
  2. 显然,第一步是不完整的,如果选的边构成了环怎么办?所以,并入最小边的时候,还需要考虑是否形成环
    • 若该边并入后形成环:那就不并入了,继续找下一个最小边
    • 若该边不会形成环:并入,继续

【如何判断是否会构成环?】https://blog.csdn.net/summer_dew/article/details/83036947

性能

O(eloge),适合稀疏图(边少的图)
另一个,普利姆Prim O(n^2):适合稠密图(边多的图)
博客:https://blog.csdn.net/summer_dew/article/details/81660483

举例

初始:将所有的顶点纳入考虑(变黄色),所有的边纳入考虑(蓝色)

  1. 选取所有边中(蓝边)最小的边f-e(权重为3),纳入生成树的边(变棕色)
  2. 将边的两个顶点纳入生成树的顶点【e,f】
  3. 若生成树顶点中【e,f】有互联的线,变深蓝色,不考虑<=因为不能产生回边
  4. 当有n-1条边完成,退出

[图] 最小生成树-克鲁斯卡尔算法Kruskal O(eloge)稀疏图-C语言实现-gif图演示_第1张图片

实现案例

例子来源:天勤论坛数据结构课程http://www.csbiji.com

【相关的存储结构】

  1. 左边的数组:存储着图的所有边与边的权重,用结点的下标代表顶点的信息(简化版的树,树的顶点信息为数字)
  2. 右边的数组:并查集,使树的双亲存储结构
    [图] 最小生成树-克鲁斯卡尔算法Kruskal O(eloge)稀疏图-C语言实现-gif图演示_第2张图片
//边的结构
typedef struct{
	int a,b; 
	int w; //权重
}Road;
Road road[maxSize];
//并查集的结构
int v[maxSize];
//得到p的根结点
int getRoot(int p) {
	while (p!=v[p]) //当p==v[p]时,即找到了根结点
		p = v[p];
	return p; //只有根结点的父亲是它自己
}
// 克鲁斯卡尔算法
// road[]:边集
// n:顶点数
// e:边的个数
int Kruskal(Road road[], int n, int e) {
	int sum=0;
	int a,b;
	int i;
	for (i=0; i<n; ++i) v[i]=i; //构造并查集的初始状态,各个节点为单独的树(即它的父亲都为它们自己)
	sort(road, e); //将边数组,从小到大排序
	for (i=0; i<e; ++i) { //遍历边数组,边数组已经被排序过了,从小到大-->从头到尾扫描即可
		a = getRoot(road[i].a);
		b = getRoot(road[i].b);
		if (a!=b) { //不会构成环
			v[a] = b; //更新并查集
			sum += road[i].w; //将边加入生成树
		}
	}
}

你可能感兴趣的:(数据结构与算法)