
200115(最小生成树的Kruskal算法(贪心))
共有15条边,将它们按权值升序排列。 接下来就是遍历按顺序每一条边; 对于某一条边是否该被纳入最小生成树的判定如下(涉及到并查集算法): 判断这条边的两个顶点
发布日期:2021-05-04 06:33:48
浏览次数:50
分类:精选文章
本文共 2709 字,大约阅读时间需要 9 分钟。
以边为目标去构建最小生成树的算法就是Kruskal算法。
直接去找最小权值的边去构建生成树是很自然的想法,只不过构建时要考虑是否会形成环路而已。
G.edge[i].begin
和G.edge[i].end
是否在同一个集合中;若顶点G.edge[i].begin
和顶点G.edge[i].end
不在同一个集合,即说明该边(G.edge[i].begin–>G.edge[i].end)没有与现有的生成树形成环路,可以把该边纳入现有的生成树;否则说明该边与现有的生成树会形成环路,所以不能把该边纳入现有的生成树。 所以问题归结到两点上: 1.如何判断某一条边的两个顶点是否在同一个集合中? 答:并查集算法,利用Find函数找出每个顶点所在集合的根结点。若根结点相同,则说明这两个顶点在同一个集合中;若根结点不同,这说明这两个顶点属于两个不同的集合。 2.如果某一条边的两个顶点属于两个不同的集合,可以纳入现有的生成树,那么该如何纳入? 答:把两个集合合并为一个集合:即先找出每个顶点所在集合的根结点,然后把两个根结点之间建立上下级关系(这里谁是上级谁是下级无所谓,优化算法不在这里讨论)。 接下来用图解法画出我的理解:
首先定义parent[e_root] = b_root;
表示b_root是e_root的上级(这就是两个集合的合并,b_root和e_root分别是两个集合的根结点)。 

完整代码如下:
#includeusing namespace std;#define MAXEDGE 20#define MAXVEX 20typedef struct { int begin; int end; int weight;}Edge;typedef struct { Edge edge[MAXEDGE]; int numEdges;}MGraph;void MiniSpanTree_KrusKal(MGraph& G);int Find(int*parent, int f);int main() { MGraph G;//权值升序排序 G.edge[0].begin = 4; G.edge[0].end = 7; G.edge[0].weight = 7; G.edge[1].begin = 2; G.edge[1].end = 8; G.edge[1].weight = 8; G.edge[2].begin = 0; G.edge[2].end = 1; G.edge[2].weight = 10; G.edge[3].begin = 0; G.edge[3].end = 5; G.edge[3].weight = 11; G.edge[4].begin = 1; G.edge[4].end = 8; G.edge[4].weight = 12; G.edge[5].begin = 3; G.edge[5].end = 7; G.edge[5].weight = 16; G.edge[6].begin = 1; G.edge[6].end = 6; G.edge[6].weight = 16; G.edge[7].begin = 5; G.edge[7].end = 6; G.edge[7].weight = 17; G.edge[8].begin = 1; G.edge[8].end = 2; G.edge[8].weight = 18; G.edge[9].begin = 6; G.edge[9].end = 7; G.edge[9].weight = 19; G.edge[10].begin = 3; G.edge[10].end = 4; G.edge[10].weight = 20; G.edge[11].begin = 3; G.edge[11].end = 8; G.edge[11].weight = 21; G.edge[12].begin = 2; G.edge[12].end = 3; G.edge[12].weight = 22; G.edge[13].begin = 3; G.edge[13].end = 6; G.edge[13].weight = 24; G.edge[14].begin = 4; G.edge[14].end = 5; G.edge[14].weight = 26; G.numEdges = 15; MiniSpanTree_KrusKal(G); system("pause"); return 0;}void MiniSpanTree_KrusKal(MGraph& G) { int parent[MAXVEX];//parent用来找根结点 for (int i = 0; i < MAXVEX; i++) parent[i] = -1; for (int i = 0; i < G.numEdges; i++) { //遍历每条边 int b_root = Find(parent, G.edge[i].begin);//找各自集合的根结点 int e_root = Find(parent, G.edge[i].end); if (b_root != e_root) { //假如b_root与e_root不相等,说明顶点G.edge[i].begin和顶点G.edge[i].end不在同一个集合,即说明边(G.edge[i].begin-->G.edge[i].end)没有与现有的生成树形成环路 parent[e_root] = b_root;//把两个集合合并成一个,即令b_root的上级为e_root或令e_root的上级为b_root //parent[b_root] = e_root;//这样写也行,谁是上下级没关系 cout << G.edge[i].begin << "-->" << G.edge[i].end << endl; } }}int Find(int*parent, int f) { //用来找根结点 while (parent[f] != -1) f = parent[f]; return f;}
所以最终构成最小生成树的边如下:

发表评论
最新留言
做的很好,不错不错
[***.243.131.199]2025年04月06日 02时45分43秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
更改github的默认语言类型
2019-03-05
使用第三方sdk,微信wechat扫码登录
2019-03-05
mysql中的行转列
2019-03-05
基于LabVIEW的入门指南
2019-03-05
PCB布局系列汇总
2019-03-05
电容入门知识
2019-03-05
2019CCPC女生专场赛_K - Tetris_打表/模拟_暴力之王
2019-03-05
“/”应用程序中的服务器错误。
2019-03-05
MUI之ajax获取后台接口数据
2019-03-05
使用sqlserver 查询不连续的数据
2019-03-05
用div+css+html+js 实现图片放大
2019-03-05
(原创)在Linux上安装运行Python3(CentOS7为例)
2019-03-05
变量覆盖漏洞
2019-03-05
weblogic之cve-2015-4852
2019-03-05
Java注释
2019-03-05
水调歌头·1024
2019-03-05
对不起
2019-03-05
C++ 函数重载
2019-03-05
Nginx简介
2019-03-05