漫画:什么是图的最小生成树?
————— 第二天 —————
————————————
首先看看第一个例子,有下面这样一个带权图:
它的最小生成树是什么样子呢?下图绿色加粗的边可以把所有顶点连接起来,又保证了边的权值之和最小:
去掉那些多余的边,该图的最小生成树如下:
下面我们再来看一个更加复杂的带权图:
同样道理,下图绿色加粗的边可以把所有顶点连接起来,又保证了边的权值之和最小:
去掉那些多余的边,该图的最小生成树如下:
怎样铺设才能保证成本最低呢?
城市之间的交通网就像一个连通图,我们并不需要在每两个城市之间都直接进行连接,只需要一个最小生成树,保证所有的城市都有铁路可以触达即可。
Prim算法是如何工作的呢?
这个算法是以图的顶点为基础,从一个初始顶点开始,寻找触达其他顶点权值最小的边,并把该顶点加入到已触达顶点的集合中。当全部顶点都加入到集合时,算法的工作就完成了。Prim算法的本质,是基于贪心算法。
接下来说一说最小生成树的存储方式。我们最常见的树的存储方式,是链式存储,每一个节点包含若干孩子节点的指针,每一个孩子节点又包含更多孩子节点的指针:
这样的存储结构很清晰,但是也相对麻烦。为了便于操作,我们的最小生成树用一维数组来表达,数组下标所对应的元素,代表该顶点在最小生成树当中的父亲节点。(根节点没有父亲节点,所以元素值是-1)
下面让我们来看一看算法的详细过程:
1.选择初始顶点,加入到已触达顶点集合。
2.从已触达顶点出发,寻找到达新顶点的权值最小的边。显然从0到2的边权值最小,把顶点2加入到已触达顶点集合,Parents当中,下标2对应的父节点是0。
3.从已触达顶点出发,寻找到达新顶点的权值最小的边。显然从2到4的边权值最小,把顶点4加入到已触达顶点集合,Parents当中,下标4对应的父节点是2。
4.从已触达顶点出发,寻找到达新顶点的权值最小的边。显然从0到1的边权值最小,把顶点1加入到已触达顶点集合,Parents当中,下标1对应的父节点是0。
5.从已触达顶点出发,寻找到达新顶点的权值最小的边。显然从1到3的边权值最小,把顶点3加入到已触达顶点集合,Parents当中,下标3对应的父节点是1。
这样一来,所有顶点都加入到了已触达顶点集合,而最小生成树就存储在Parents数组当中。
final static int INF = Integer.MAX_VALUE;public static int[] prim(int[][] matrix){List<Integer> reachedVertexList = new ArrayList<Integer>();//选择顶点0为初始顶点,放入已触达顶点集合中reachedVertexList.add(0);//创建最小生成树数组,首元素设为-1int[] parents = new int[matrix.length];parents[0] = -1;//边的权重int weight;//源顶点下标int fromIndex = 0;//目标顶点下标int toIndex = 0;while (reachedVertexList.size() < matrix.length) {weight = INF;//在已触达的顶点中,寻找到达新顶点的最短边for (Integer vertexIndex : reachedVertexList) {for (int i = 0; i < matrix.length; i++) {if (!reachedVertexList.contains(i)) {if (matrix[vertexIndex][i] < weight) {fromIndex = vertexIndex;toIndex = i;weight = matrix[vertexIndex][i];}}}}//确定了权值最小的目标顶点,放入已触达顶点集合reachedVertexList.add(toIndex);//放入最小生成树的数组parents[toIndex] = fromIndex;}return parents;}public static void main(String[] args) {int[][] matrix = new int[][]{{0, 4, 3, INF, INF},{4, 0, 8, 7, INF},{3, 8, 0, INF, 1},{INF, 7, INF, 0, 9},{INF, INF, 1, 9, 0},};int[] parents = prim(matrix);System.out.println(Arrays.toString(parents));}
这段代码当中,图的存储方式是邻接矩阵,在main函数中作为测试用例的图和对应的邻接矩阵如下:
当然,也可以使用邻接表来实现prim算法,有兴趣的小伙伴可以尝试写一下代码。
—————END—————
漫画:什么是图的最小生成树?相关推荐
- C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)
1.Prim 算法 以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树. 2.Kruskal 算法 直接寻找最小权值的边来构建最小生成树. 比较: Kruskal 算法主要是针对边来展开,边数 ...
- 算法导论之图的最小生成树
引出最小生成树,是提到电子线路设计时,要把数个元件的引脚连接在一起,使其电位相同.使n个引脚互相连通,可以使用n-1条连接线,每条连接线连接两个引脚.寻求连接线最少的方案,是最小生成树的应用.将电子线 ...
- 图的最小生成树和最短路径算法思路总结(Prim,Kruskal,Dijkstra,Floyd)
带权无向图->最小生成树算法->Prim算法: 思路: 首先,我们先设置两个集合,U_{}:一个用来放最小生成树的顶点,T_{}:一个用来放最小生成树的边.选取最开始的点V_0,将V_0放 ...
- java 最小生成树_图的最小生成树(java实现)
1.图的最小生成树(贪心算法) 我两个算法的输出都是数组表示的,当前的索引值和当前索引对应的数据就是通路,比如parent[2] = 5;即2和5之间有一个通路,第二个可能比较好理解,第一个有点混乱 ...
- 图的最小生成树(java实现)
1.图的最小生成树(贪心算法) 我两个算法的输出都是数组表示的,当前的索引值和当前索引对应的数据就是通路,比如parent[2] = 5;即2和5之间有一个通路,第二个可能比较好理解,第一个有点混乱 ...
- 数据结构值图的最小生成树
最小生成树(最小连通网) 假设在n个城市之间建立通信联络网,则连通n个城市只需要n-1条线路.这时自然会考虑这样一个问题,如何在最节省经费的前提下建立这个通信网. 在每两个城市之间都可以设置一条线路, ...
- 克鲁斯卡尔算法(Kruskal Algorithm)——图的最小生成树
听骚话讲作者 [手动滑稽] 其实早就该写这篇博客啦. 图的最小生成树 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.最小生成树可以 ...
- 图的最小生成树-Kruskal算法
问题引入 [问题描述] 编写程序,利用带权无向图的邻接矩阵存储,实现图的最小生成树Kruskal算法. [输入形式] 输入图的顶点序列及图的边的情况.如样例所示.边的输入以输入-1,-1,-1作为结束 ...
- 算法:通过克鲁斯卡尔(Kruskal)算法,求出图的最小生成树
之前我给大家分享过用普利姆(Prim)算法来求出图的最小生成树(点我去看看),今天我再给大家分享一个也是求图的最小生成树的克鲁斯卡尔(Kruskal)算法 克鲁斯卡尔(Kruskal)算法,就相当于先 ...
- 数据结构(19)图的最小生成树算法
数据结构(19)图的最小生成树算法 前言 普里姆(Prim)算法 克鲁斯卡尔(Kruskal)算法 代码 GraphMtx.h GraphMtx.c Main.c 前言 在有n个顶点的图中,要连接所有 ...
最新文章
- 十个最常用的JVM 配置参数
- 2017年嵌入式领域的MCU四个变化
- PLSQL的截取函数
- 2.控制反转 spring_ioc
- 步步为营UML建模系列总结
- JMM和底层实现原理
- jQuery.inArray()方法
- 深度学习笔记(38) 非极大值抑制
- 课工场新闻管理jsp修改项目_jspmvc实验室预约管理系统
- 在那些打磨汉芯的日子里[转贴]
- 数据结构——>顺序存储二叉树
- vue-router的编程式导航
- Landsat卫星MSS/TM/ETM数据(转自ESRI社区)(二)
- 【图像处理】.jpg 和 .png
- 运动目标识别系统Matlab仿真——附上程序
- 城市停车难,如何破局?
- 黑马粉丝感叹:好可呀,好想要!!【最新福利你还没领?】
- 双目立体视觉 II:块匹配视差图计算
- mysql输出当前是第几周使用week和weekofyear的区别
- 一篇文章搞懂「低保真原型与高保真原型」