ds图—最小生成树_图的应用(1)-连通图的最小生成树(Prim算法和Kruskal算法)

4448f6b6a10c251da8b0ee0cbceb4908.png

连通图的生成树:

是一个极小的连通图,它含有图中全部的N个顶点,但是只足以构成一颗树的N-1条边。

必须满足三个条件:

  1. 图是连通图;
  2. 图中包含了N个结点
  3. 图中边的数量等于N-1条。

连通图生成树的判断:

下面4幅图中哪个是连通图的最小生成树?

35e40d3ed05d78363c814bb44f343e2a.png
图1

881fcce3589b9a47cab90f1d6971a8d5.png
图2

0bee6f141d06c971cd87e11d35a2d080.png
图3

cf010e8a1dfd6195f50c1545c5ef0f57.png
图4

满足最小生成树的三个条件的只有图2。所以图2是连通图的最小生成树。

阿里的面试题

假设目前优N个顶点,每个顶点链接的路径不一样,请你设计一个算法,快速找出能覆盖所以顶点的路径。

bc3dcf92ed81d6f157e95cb4a8921905.png
阿里面试题
注意:该题并不是求两点间的最短路径,而是设计一个路线,能够覆盖所有顶点。

方案一:

28d3c4d264ad55961d5f2667b0105783.png
方案一
11+26+20+22+18+21+24+19 = 161

方案二:

da1354e47e92f45cde9626b6cbed1a6d.png
方案二
8+12+10+11+17+19+16+7=100

方案三:

e9fccc3b1d7cec8213ba90d8d302f3e9.png
方案三
8+12+10+11+16+19+16+7=99

上面三种方案中,第三种为最优解。

那么有没有一种算法能精准的算出网图的最优解呢?

方法就是最小生出树,即把连通图以最小代价生出的树,叫做最小生成树

保存图

先把上面的图用邻接矩阵存储起来。关于邻接矩阵存图,可以看我上篇文章【图的存储】相关内容。

GhostClock:经典数据结构-图​zhuanlan.zhihu.com
aa91e4d753a356de811d5085a1322833.png

最后得到结构为:

71fd6e6008137382919895a7d88c9012.png
用邻接矩阵存储图

数据结构:

#include 

创建邻接矩阵:

/*创建邻接矩阵*/

普里姆(Prim)算法

思路:

  1. 定义两个数组,lowcost,arjvex;arjvex用来保存顶点下标;lowcost用开保存顶点之间的权值;
  2. 初始化两个数组,从v0开始寻找最小生成树,默认v0是最小生成树上的第一顶点;
  3. 循环lowcost数组,根据权值找到顶点k;
  4. 更新lowcost数组;
  5. 循化所有顶点,找到与顶点k有关的顶点,并更新lowcost数组和arjvex数组。
注意:
更新lowcost数组与arjvex的条件
1.与顶点k之间有链接
2.当前结点j没有加入过最小生成树
3.顶点k与当前顶点j之间的权值小于顶点j与其他顶点k之间的权值,则更新。(简单说就是要比较之前存储的值要小,则更新)。

将与V0相关的V1-V8的所有顶点赋值对应的权值,并且arjvex[1~8]都赋值为0,表示都是与顶点V0相关的顶点。如下图所示:

6832a38fb4825aa981255ec1ea0c7e8f.png
V0相关的V1-V8顶点

如上图所示,这里定义两个数组【lowcost,arjvex】,数组lowcost存顶点之间的权值,数组arjvex保存相关顶点下标

/* Prim算法生成最小生成树 */

使用并打印

printf

bdc1aae88acc591b31ac353e2ec47361.png
打印

克鲁斯卡尔(Kruskal)算法

思路:

  1. 将邻接矩阵转换为数组;
  2. 对边表数组根据权值按照从小到大的顺序排列
  3. 遍历所有边,通过parent数组找到边的链接信息,避免闭环;
  4. 如果不存在闭环问题,则加入到最小生成树中,并且修改parent数组。

边表的定义:

/* 对边集数组Edge结构的定义 */

生成最小生成树

/* 生成最小生成树 */

工具方法

/* 交换权值以及头和尾 */

使用并打印:

printf

ef352e6c57cc0b3aae726c5cc57dc879.png
打印最小生成树_Kruskal算法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值