树一般来说是基于图而生的,而树是一种特殊的图:无环连通图。

定义1:对于无向图G和一棵树T来说,若T中与G中所包含的节点相同,但是边不相同,且T恰好是无环的连通图,那么称T为G的生成树。

对于图的生成树,主要有无向图的最小生成树次小生成树和有向图的最小树形图三种问题。这一次我们主要讲比较容易理解的最小生成树。

那什么是最小生成树呢?有以下定义:

定义2:对于一个具有边权的图来说,其边权和最小的生成树称作图G的最小生成树。

图的最小生成树在实际的生活中有很重要的应用,比如说用一个图表示n个城市之间的交通网,边上的权值是公路预算,现在要修建公路将多个城市连起来使得开销最少,这不就是一个求解最小生成树的问题么?

一般来说,对于一个图来说,若图中的边权值各不相同,那么图的最小生成树唯一。这个证明过程这里不再赘述,可以参考算法导论上的相关章节.

求解无向图的最小生成树主要有Prim算法和Kruscal算法两种。比较好理解的是Kruscal算法,所以我们先讲一下Prim算法。

我们现在抛开复杂的算法流程,在Prim没有发现这个算法之前,你能自己去发现么?

首先我们骨子里会有一种贪心的思想,既然是树上最小的边权和,那我希望每一步选择的边权都是最小的。此时我想从图的任意一点出发,选择与出发点相连的所有点中连接边权最小的点,此时已经访问了两个点。然后呢?我们继续找最小的权值,然后我们以第2个访问的点为起点,继续上述的操作?好像有点问题。因为可能会出现下面的这种情况:

我们会错过A-D这条更小的边,说到这里我们就会很清楚了,我们假设的以A为起点,但其实A可能只是最小生成树路径中间的一个点(不是最头上的点),因此在寻找最短边权的时候,我们要以访问过的点集为整体,去找离此点集(即红色圈内部分)最近的点对应的权值,那么什么叫离点集最近呢,下面我写一个公式:

形象一点就是在所有蓝色边中找最小的边:

好了我们重新捋一遍刚才的思路:

1.每次选取 离已访问点集最近 的点,加入集合,把对应的边权加入到最小生成树权值中

2.若找到了n-1条边,则结束算法;否则重复1过程。

为啥找到n-1条边就可以呢,因为一个图若有n个节点,则它的最小生成树必定只有n-1条边,否则再多一条边就会出现环,可以自己画画看。

这个算法就叫Prim算法,是不是感觉我们自己也能想到?我们只是感觉这样做对,但是并没有去证明这么做为什么对。不过现在可以告诉你通过这样的步骤,最后得到的确实是最小生成树。感兴趣的同学还是可以去算法导论去看相关的证明。

这个算法中一个关键的地方是如何维护已访问点集到所有其他未访问点的距离,我们可以用一个d[]数组来进行维护每一个点(未访问的点)到已访问点集的最短距离,这样每次我们访问一个点之后,对d[]数组进行更新,然后再访问其他的点重复此过程。接下来,我们通过以下的图来模拟一下过程。

所有的过程结束之后,我们来用代码一步一步的实现了。

  1. 初始化要用到的数组:Map[ ][ ]用来储存节点之间的权值,vis[ ]标记是否被访问,pre[ ]记录前驱节点,d[ ]维护到已访问点集的最短距离。
const 

2. 初始化

memset

3. 我们先从第一个点开始访问,这里我们从1节点开始:

d

因为此时集合中只有一个节点1,因此自己到自己的最短距离为0。

4. 关键代码

for

进行n-1次循环是因为我们每一次操作都会往已选点集中加入一个新的点(也可以理解为加上一条新的边),而含有n个节点的图的最小生成树的边数必定n-1,因此只要n-1循环即可。

代码中比较关键的 一个地方是松弛的过程,要明白和理解松弛的目的是什么?我们以下图为例说明一下。

当已访问点集中只有A的时候,未访问节点C到已访问点集{A}的最短距离为d[C]=3,当我们往集合中加入一个新的节点B时,我们会发现,由于点B 的加入,使得已访问点集{A,B}与点C的连接关系发生了变化,产生了新的连接关系:B-C。由于此图是一个平面图(二维),因此每加入一个新的节点,有且只有一个新的连接边产生,而对于点C到已访问点集最短距离的更新,一定是在新产生的连接边B-C和原来的d[C]中选择一个较短的进行更新,即:

对每一个点都执行上面的操作,这个更新的操作就叫做松弛。对每一个未访问节点松弛后,每一轮最后就可以得到所有未访问节点各自到已访问点集的最短距离。下一轮(下一次循环)的开始,再从这些最短距离里选择一个最短的,将连接的点加入已访问集合,以此类推。

这样我们就得到了最小生成树,权值也可以计算出来:在程序中 每加入一个节点,就把此节点与上一个节点的边权加入最终的最小生成树权值中即可。

讲完这个Prim算法,我们想一下 是不是可以优化呢?

我们发现在求最短距离的时候,要遍历所有连接的邻近点才能求出最小的距离。如下:

for

这里我们可以用一个优先队列priority_queue来对这个最小值进行维护,每次从队首取出最小值,优先队列内部是用堆实现,因此复杂度也会降低。大家可以自己实现一下,比较简单。

Prim算法就讲到这里,下一次我会继续讲解另一种最生成树算法Kruscal。

点个赞再走吧!

prim算法_图的生成树之最小生成树(Prim)相关推荐

  1. prim算法_数据结构 7.4.1 最小生成树 Prim

    最小生成树 Minimum Spanning Tree 「最小生成树」这个词包含三部分信息 树 生成树 最小 什么是树? 树可以看做是一种特殊的图,「树没有回路」 有n个顶点的树一定有n-1条边 什么 ...

  2. prim算法_自动生成随机迷宫(1)prim算法

          "程序 = 数据  + 算法",一款好的作品不单单是代码的堆砌,还有其灵魂的部分,那就是算法:算法是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机 ...

  3. prim算法_数据结构与算法

    根据MOOC上课程总结,文章目录为: 一.引论 数据结构的基本概念 数据的逻辑结构和存储结构 算法及其时间复杂度 时间复杂度及应用 二.线性表 线性表的概念及顺序存储 单链表的概念及其基本操作 建立单 ...

  4. prim算法_最小生成树(Kruskal和Prim算法)

    文章和资源同步更新至微信公众号:算法工程师之路 8月份会开启每日算法题系列,值得期待哦 上一篇文章,我们讲了图的创建和遍历,其中遍历的算法主要有BFS(广度优先算法)和DFS(深度优先算法)两种,并且 ...

  5. prim算法_最小生成树的本质是什么?Prim算法道破天机

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法和数据结构专题20篇文章,我们继续最小生成树算法,来把它说完. 在上一篇文章当中,我们主要学习了最小生成树的Kruskal算法.今 ...

  6. Prim算法求图的最小生成树(Java)

    package Algorithm.prim;import java.util.Arrays;/*** 普利姆算法解决最小生成树问题 Prim算法的实现过程 首先以一个结点作为最小生成树的初始结点,然 ...

  7. prim算法_历时两月,终拿字节跳动offer,算法面试题分享「带答案」

    欢迎关注专栏<Java架构筑基>--专注于Java技术的研究与分享! Java架构筑基​zhuanlan.zhihu.com Java架构筑基--专注于Java技术的研究与分享! 后续文章 ...

  8. 算法训练营 图的应用(最小生成树)

    最小生成树 子图:从原图中选中一些由节点和边组成的图,称之为原图的子图. 生成子图:选中一些由边和所有节点组成的图,称之为原图的生成子图. 生成树:如果生成的子图恰好是一棵树,则称之为生成树. 最小生 ...

  9. prim算法_求解最优树——Prim算法与Kruskal算法

    本文主要参考: 1.<Matlab数学建模算法全收录(数学建模比赛必备参考资料).pdf> 2.最小生成树-Prim算法和Kruskal算法 1 前言 简单来说,图由顶(就是结点)和边构成 ...

最新文章

  1. Java学习总结:46(内存流)
  2. java开发checklist,Java API设计CheckList
  3. 推荐一个集录屏、截图、音频于一体的软件给大家
  4. 蓝桥杯2016初赛-生日蜡烛-枚举
  5. Android 全局悬浮按钮,悬浮按钮点击事件
  6. Storm精华问答 | storm与Hadoop区别?
  7. Expression Atlas
  8. oracle掉电后ora 00600,ORA-00600: 内部错误代码, 参数: [kcratr1_lastbwr](转)
  9. Wheel ProgressBar 实现之三——模拟进度过程
  10. 学校计算机编程用的什么软件,电脑编程软件都有哪些
  11. html5在线显示ofd文件,基于HTML5的OFD文件在线显示的方法以及装置制造方法及图纸...
  12. 如何构建自己的游戏框架并且制作游戏(一)(附源码)
  13. 高斯核函数 python实现
  14. 佳博打印机ip地址修改软件_【动手实践】树莓派将有线打印机转为无线共享打印机 by xinlong...
  15. Android为什么图片模糊不清,Android打开图库中图片为什么从模糊变清晰
  16. 二进制转十进制c++语言数组,C++实现读入二进制数并转换为十进制输出
  17. C++:[编程题]买帽子
  18. 泛微OA流程表单提交JS验证
  19. TLS协议分析------
  20. 互联网开放平台纵横论

热门文章

  1. 书籍:Python游戏开发 Game Development Using Python - 2019.pdf
  2. C# DataTable 用法
  3. 干货分享:vue2.0做移动端开发用到的相关插件和经验总结(2)
  4. 高性能框架gevent和gunicorn在web上的应用及性能测试
  5. spring 启动完成后事件监听器处理
  6. 仿58网,赶集网,百姓网swfupload图片上传效果(asp.net 2.0)
  7. hbase 使用disruptor_一条数据的HBase之旅,简明HBase入门教程-Write全流程
  8. pythondef元组参数传递_Python参数传递(传值传引用)
  9. JavaScript变量高级定义之Object.defineProperty()方法讲解
  10. 分层架构、六边形架构、CQRS架构模式解读