最小生成树——Kruskal算法理解
背景:本文是在小甲鱼数据结构教学视频中的代码的基础上,添加详细注释而完成的。该段代码并不完整,仅摘录了核心算法部分,结合自己的思考,谈谈理解。
Prim算法理解:
如图(摘录自小甲鱼教学视频中的图片),是一个带有权值的连通网:

根据上图可以列写出该连通网的邻接表,为了方便直观的理解:(邻接表初始化需按照权值增序排列)
| edges数组 | begin | end | weight |
| edge0 | 4 | 7 | 7 |
| edge1 | 2 | 8 | 8 |
| edge2 | 0 | 1 | 10 |
| edge3 | 0 | 5 | 11 |
| edge4 | 1 | 8 | 12 |
| edge5 | 3 | 7 | 16 |
| edge6 | 1 | 6 | 16 |
| edge7 | 5 | 6 | 17 |
| edge8 | 1 | 2 | 18 |
| edge9 | 6 | 7 | 19 |
| edge10 | 3 | 4 | 20 |
| edge11 | 3 | 8 | 21 |
| edge12 | 2 | 3 | 22 |
| edge13 | 3 | 6 | 24 |
| edge14 | 4 | 5 | 26 |
以下简单描述算法运行的流程(仅描述前几次循环,旨在理解算法工作过程),主要记录和对比parent数组和最小生成树的的逐渐生成的过程:
Kruskal算法核心思想:尽可能只选用权值最小的边连成树,即为最小生成树,因此以权值升序顺序对各边进行循环判断。最理想的情况就是权值最小的几条边恰好连成最小生成树,但是实际过程中很可能会在连接过程中形成环路(树中不允许有环路),因此一个重要的步骤就是判断当前边的加入是否会导致生成树中出现环路(即代码中parent数组的作用和m!=n判断条件的来历)。
Kruskal算法和Prim算法的主要区别就是Prim算法是以定点为单位,Kruskal算法是以边为单位。因此这里所说的(第一次、第二次)循环过程实际是对于上面的邻接表中每一条进行循环判断(是否需要添加到最小生成树中)。
在理解以下过程的时候,先浏览几遍最下方的代码,逐步对比,最容易理解。
以下对于边以及循环次数的命名以0开始,为了和上面的邻接表相对应,以防止混淆。
0、第0次(edge0)
第0次循环,对第0条边进行判断:
| edges数组 | begin | end | weight |
| edge0 | 4 | 7 | 7 |
执行Find函数,得到的n = 4,m = 7。
m != n 表示不存在环路(这里不理解可以继续看以下的几个循环),则在parent数组中记录这条边带来的连接关系(parent[4] = 7)。
| parent数组 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | n | m |
| 初始化 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | \ | \ |
| 第0次 | 0 | 0 | 0 | 0 | 7 | 0 | 0 | 0 | 0 | 4 | 7 |
生成树:

1、第1次
第1次循环,对第1条边进行判断:
| edges数组 | begin | end | weight |
| edge1 | 2 | 8 | 8 |
执行Find函数,得到的n = 2,m = 8。
m != n 表示不存在环路,则记录连接关系(parent[2] = 8)。
| parent数组 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | n | m |
| 第0次 | 0 | 0 | 0 | 0 | 7 | 0 | 0 | 0 | 0 | 4 | 7 |
| 第1次 | 0 | 0 | 8 | 0 | 7 | 0 | 0 | 0 | 0 | 2 | 8 |
生成树:

此处省略几次循环......只叙述比较有特点的循环。
4、第4次
第4次循环,对第4条边进行判断:
| edges数组 | begin | end | weight |
| edge4 | 1 | 8 | 12 |
执行Find函数(参考下面第3次迭代后的parent数组),parent[1] = 5; parent[5] = 8; 得到的n = 5。parent[8] = 0; 得到m = 8。
m != n 表示不存在环路,则记录连接关系(parent[5] = 8)。
| parent数组 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | n | m |
| 第3次 | 1 | 5 | 8 | 0 | 7 | 0 | 0 | 0 | 0 | ||
| 第4次 | 1 | 5 | 8 | 0 | 7 | 8 | 0 | 0 | 0 | 5 | 8 |
生成树:
这里要注意:parent数组中的对应关系并不表示生成树中的边的关系,比如之前的循环中会在parent数组中添加如下内容:parent[1] = 5; 它表示的是1和5定点在同一个生成树中,之间存在连接关系,但并不表示存在V1->V5这样的一条边。(我自己理解的是,这个关系实际是由V0->V5的这样的一条边的加入而生成的,但是parent[0]已经被幅值为1,即表示与V1存在连接关系,故借用V1来表示出这个关系,自己的一种理解,可能错误,不要干扰思维)。

此处再次省略几次循环......只叙述一次比较特殊的循环(m==n的情况)。
7、第7次
第7次循环,对第7条边进行判断:
| edges数组 | begin | end | weight |
| edge7 | 5 | 6 | 17 |
执行Find函数(参考下面第6次迭代后的parent数组),parent[5] =85; parent[8] = 6; 得到的n = 6。parent[6] = 0; 得到m = 6。
m == n 表示存在环路,则忽略这条边(不添加到最小生成树中)。
| parent数组 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | n | m |
| 第6次 | 1 | 5 | 8 | 7 | 7 | 8 | 0 | 0 | 6 | ||
| 第7次 | 1 | 5 | 8 | 0 | 7 | 8 | 0 | 0 | 6 | 6 | 6 |
在实际的生成树可以直观的看出V5和V6之间的连线不应该加入(会形成环路),如下图为进行第7次循环之前的生成树情况:

可见,V5->V6边的加入将导致最小生成树中出现环路,因此舍弃。
......
如此对所有边进行循环,判断是否应该加入最小生成树中,直至循环结束,则生成树完成。
代码如下:(仅Kruskal算法的两个核心函数)
int Find(int *parent,int f)
{
/* parent该数组元素>0表示已完成的生成树中存在与该顶点有连接关系的顶点 */
while(parent[f] > 0)
{
/* 则迭代寻找与该点存在连接关系的结束顶点(当前所在树的结束顶点) */
f = parent[f];
}
return f;
}
void MiniSpanTree_Kruskal(MGraph G)
{
int i,n,m;
/* 边数组:应按照边的权值升序进行初始化 */
Edge edges[MAXEDGE];
/* parent数组用来存放顶点之间的连接关系 以判断是否存在环路 */
int parent[MAXVEX];
/* parent数组初始化 */
for(i=0;i<G.numVertexes;i++)
{
parent[i] = 0;
}
for(i=0;i<G.numVertexes;i++)
{
n = Find(parent,edges[i].begin);
m = Find(parent,edges[i].end);
/* 若n == m则表示形成环路 */
if(n != m)
{
/* 若未形成环路 */
/* 将该边添加到生成树中(此处即打印) */
/* 将由该边引起的连接关系保存到parent数组中(注意这里不是简单的将边保存到parent数组中 而是保存了一种连接关系) 表示该顶点已经在生成树中 */
/* 存放方式:parent[p] = q表示:从顶点p到顶点q存在通路(即顶点p和顶点q在同一个生成树中) */
parent[n] = m;
printf("(%d,%d) %d",edges[i].begin,edges[i].end,edges[i].weight);
}
}
}
——cloud over sky
——2020/3/12
最小生成树——Kruskal算法理解的更多相关文章
- 【转】最小生成树——Kruskal算法
[转]最小生成树--Kruskal算法 标签(空格分隔): 算法 本文是转载,原文在最小生成树-Prim算法和Kruskal算法,因为复试的时候只用到Kruskal算法即可,故这里不再涉及Prim算法 ...
- 求最小生成树——Kruskal算法
给定一个带权值的无向图,要求权值之和最小的生成树,常用的算法有Kruskal算法和Prim算法.这篇文章先介绍Kruskal算法. Kruskal算法的基本思想:先将所有边按权值从小到大排序,然后按顺 ...
- 数据结构:最小生成树--Kruskal算法
Kruskal算法 Kruskal算法 求解最小生成树的还有一种常见算法是Kruskal算法.它比Prim算法更直观.从直观上看,Kruskal算法的做法是:每次都从剩余边中选取权值最小的,当然,这条 ...
- 【一个蒟蒻的挣扎】最小生成树—Kruskal算法
济南集训第五天的东西,这篇可能有点讲不明白提前抱歉(我把笔记忘到别的地方了 最小生成树 概念:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的 ...
- 最小生成树kruskal算法、
克鲁斯卡尔(kruskal) //kruskal算法生成最小生成树. //对边集数组Edge结构的定义 typedef struct { int begin; int end; int weight; ...
- 最小生成树——kruskal算法
kruskal和prim都是解决最小生成树问题,都是选取最小边,但kruskal是通过对所有边按从小到大的顺序排过一次序之后,配合并查集实现的.我们取出一条边,判断如果它的始点和终点属于同一棵树,那么 ...
- 最小生成树Kruskal算法
Kruskal算法就是把图中的所有边权值排序,然后从最小的边权值开始查找,连接图中的点,当该边的权值较小,但是连接在途中后会形成回路时就舍弃该边,寻找下一边,以此类推,假设有n个点,则只需要查找n-1 ...
- 最小生成树------Kruskal算法
Kruskal最小生成树算法的概略描述:1 T=Φ:2 while(T的边少于n-1条) {3 从E中选取一条最小成本的边(v,w):4 从E中删去(v,w):5 if((v,w)在T中不生成环) { ...
- 最小生成树 kruskal算法&prim算法
(先更新到这,后面有时间再补,嘤嘤嘤) 今天给大家简单的讲一下最小生成树的问题吧!(ps:本人目前还比较菜,所以最小生成树最后的结果只能输出最小的权值,不能打印最小生成树的路径) 本Tianc在刚学的 ...
随机推荐
- Unity 游戏框架搭建 2019 (四十四、四十五) 关于知识库的小结&独立的方法和独立的类
在上一篇,我们完成了一个定时功能,并且接触了 Action 和委托.lambda 表达式这些概念. 到目前为止,我们的库作为知识收录这个功能来说,已经非常好用了,由于使用了 partial 关键字,所 ...
- CSS躬行记(9)——网格布局
网格布局(Grid Layout)也叫栅格布局,与表格布局类似,也依赖行和列.但与之不同的是,网格布局能直接控制HTML文档中元素的顺序.位置和大小等,而不用再借助辅助元素. 一.术语 下图展示了CS ...
- Linux之《荒岛余生》(一)准备篇
xin片之争,已经暴露了中国xin的问题,我等码农束手无策:而在操作系统方面,成果也是乏善可陈:现如今酷炫的Web监控工具,让很多研发丧失了真正处理问题的能力. 越接近底层,就越接近真相,在计算机的世 ...
- PUBG 1V3 线段树扫描线
PUBG 1V3 这个题目我觉得好难写啊. 感觉自己码力不太行啊. 题目大意是,给你n个人,n个人组成m个队伍,每个队伍最多4个人. 然后给你每一个人的位置队伍信息还有攻击范围. 问当一个队伍剩下一个 ...
- Blazor入门:ASP.NET Core Razor 组件
目录 关于组件 组件类 静态资产 路由与路由参数 组件参数 请勿创建会写入其自己的组参数属性的组件 子内容 属性展开 任意参数 捕获对组件的引用 在外部调用组件方法以更新状态 使用 @ 键控制是否保留 ...
- Fortify Audit Workbench 笔记 File Disclosure: Spring 文件泄露(Spring框架)
File Disclosure: Spring 文件泄露(Spring框架) Abstract 若通过用户输入构造服务器端重定向路径,攻击者便能够下载应用程序二进制码(包括应用程序的类或 jar 文件 ...
- 广义Fibonacci数列模n的循环节
见这里:http://blog.csdn.net/ACdreamers/article/details/25616461 有详细的分析推理 只找出了循环节的上限,设 f[n] = (af[n - 1] ...
- 【HDU4990】递推式
题目大意:给定序列 1, 2, 5, 10, 21, 42, 85, 170, 341 …… 求第n项 模 m的结果 递推式 f[i] = f[i - 2] + 2 ^ (i - 1); 方法一: ...
- 通过PAML中的CODEML模块计算dnds的过程以及踩坑
最近帮女朋友做毕业设计的时候用到了 PAML这个软件的codeml功能,发现网上相关的资料很少,于是把自己踩的一些坑分享一下,希望能帮到其他有相同困难的人 一.下载与安装 PAML软件下载地址 htt ...
- Mysql 常用函数(10)- strcmp 函数
Mysql常用函数的汇总,可看下面系列文章 https://www.cnblogs.com/poloyy/category/1765164.html strcmp 的作用 比较两个字符串的顺序是否完全 ...