简介

     Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。由for循环可知,其时间复杂度是O(n^2)。

原理

已知图的邻接矩阵net.vexs[i][j](无向网,含权值的图)的条件下,通过遍历已知图的所有路径,用dis[i]数组来记录到i点的最短路径,然后在循环中不断判断更替。首先,将所有点的集合分为俩部分,一边是已经遍历过的,另外一边是没有遍历过的,分别用mark[i]=1、mark[i]=0来表示。

代码通解

在下面代码中,先将赋予初始值dis[i]=INF(无穷大)、mark[i]=0(未标记),而后单独将源点(x)所联通的路径权值net.arcs[x][i]赋予dis[i](<INF称为初始化),i为联通的点,暂定为到i的最短路径,标记mark[x]=1,即已经遍历;然后,在一个for遍历了所有节点的大循环里面:

①寻找遍历到点联通路径(与之相连线的点)中权值最小的一条; 标记遍历点;

②修正最短路径;

而后,便是已经遍历所有点了,dis[i]也在不断的修正中得到真正的最小值,即最短路径。详情看下列代码:

#define MAXSIZE 20
#define PLACENUM 12
#define INF 9999           // 此处定义999为无穷大struct
{int vexnum,arcnum;  //节点数和边数int vexs[MAXSIZE];      // 节点名int arcs[MAXSIZE][MAXSIZE];   //俩个节点之间的值
} net;
/*补充的结构体net,2019.7.3*/void Dijkstra(int x,int y)      // x为源点,y为终点
{int i,j,k;int min;int u;   //下一个放入集合p的点int dis[net.vexnum];   //  最短路径int mark[net.vexnum];   //   被mark的便是已经遍历,未被mark的便是未遍历/*首先进行最短路径初始化*/for(i=0; i<net.vexnum; i++){mark[i] = 0;dis[i] = net.arcs[x][i];}mark[x]=1;          // 标记源点for(k=0; k<net.vexnum; k++)          // for 大循环{min = INF;   //  min初始化最大值,便于后来数据替换(每一个点的出度入度判断)/*寻找遍历到点联通路径(与之相连线的点)中权值最小的一条; 标记遍历点;*/for(i=0; i<net.vexnum; i++){if(mark[i]==0&&min>dis[i])      //判断未遍历点 且 被赋值的最短路径(dis[i]<INF),未被赋值的点     //                                                     应当min==dis[i]=INF{min = dis[i];             //在已知赋值最短路径中,寻找权值最小的点并将他作为下一个遍历 u=i;                            //点u点}}mark[u]=1;      //标记u点,下面u修正将会以最短路径进行辐射/*修正最短路径*/for(i=0;i<net.vexnum;i++){if(!mark[i]&&dis[i]>dis[u]+net.arcs[u][i])                 // !mark[i]判断不去走回头路,         //                                                                                dis[i]>dis[u]+net.arcs[u][i]有俩个用途:①若u链接的是x源点没有赋值最短路径的点,那么这里可以赋值②若是赋值过的点,那么可以判断是上一个dis[i](此时是被赋值过的)是不是真正的最短路径,即修正。{dis[i] = dis[u] + net.arcs[u][i];      //若A->C比A->B->C更长那么A->B->C则是到C的最短路径,下图将解释。}}}printf("最短路径值为:             %d",dis[y]);
}

我们以A,B,C三个点来举例子,三个点的最短路径分别为dis[0]、dis[1]、dis[2]。

①A为源点初始化,dis[B]=3 (到B的最短路径,dis[1]),  dis[C]=6;

②dis[B]<dis[C],选取B为u下一个遍历点;与B相联的有A(不走回头路)、E、C;

③E未赋值,赋予dis[E];  C被之前赋予过,比较  dis[C] > dis[B] + net.arcs[B][C] (要不然你根本进不了这儿),重新赋值dis[C] = dis[B]+net.arcs[B][C];

④大循环遍历所有点,走遍天下。

我觉得下面几张图很不错,图片取自https://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html

图一

图二

19.3.24

关于修正最短路径

请参考一下文中引入的动图(图一)和表格图(图二),迪杰斯特拉求最短路径是,将需要遍历的点集合一个个进行遍历的。!mark[i]是需要其值为false(尚未遍历到,这是相对于当前遍历点),当然,这就实现了它不会往回走,同时记录它“向前走”的最短距离点u,在其基础上(修正循环),与u点相连的未被标记(遍历到)的点记其中一个为z,判断源点x->z点们的dis(最短)值是否大于x->u->z点们的距离,如果大于,更新z点们的最新(新的路径)最短距离,在已知最短距离的情况下然后进行更新,直到遍历完所有的点集合(所有路径)。从源点往外辐射就能够理解了。

比如说1,2,3为三角形相互联系。当前是2。已经遍历了1,赋予了1->2、1->3、1->6的dis值,那么在修正部分就会从u(设12、13、16中12距离最小),也就是2往外与没遍历且相邻的3和4判断以下:1->3大于1->2->3?  1->4大于1->2->4?,如果大于,更新dis值,此为修正,这里在已知最短距离1->2的基础上修正了1->3和1->4的dis值。同理到3的时候会修正源点(x/1)到4和到6的最短距离。

下图圆形为已遍历点,方形为未遍历的集合数据,实线为相邻连线,虚线为修正过程。

PS:mark是已经被找过从该点出发的相邻路径,修正在已知最短距离的情况下(u),进行辐射,也就相对于找了u的所有相邻路径来比较更新(!mark[i]&& dis[i]>dis[u]+net.arcs[u][i]),但他并未记录u辐射的路径中的相邻最短路径(需要大循环)。

遍历第一个点——1的过程

遍历点2的过程

21.4.16

关于负权值问题

迪杰斯特拉本质上是贪心:找局部最优解,前提是最终的结果是由不断简化问题的局部最优解组成的,贪心是一种特殊的动态规划:他只关注局部最优解(但是我们知道局部最优解不一定是全局最优)。弗洛伊德是动态规划。这里体现出一点:迪杰斯特拉只是单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。而弗洛伊德则是算出所有的点之间的最短路径(多对多)。

那么我们再看负权值问题:迪杰斯特拉:每次修正,我们只会修正当前点所连接的,未被遍历过的(mark[i]),注意前面这句话有两个条件。那么久说明他不会修改早已经(很久以前)就已经确定的最短路径,因为已经确定了是局部最优解,这里在代码里面也能看出来。而也因为这样,弗洛伊德是是能够算负权的(他可以更新“早已经”确定的最短路径,因为他要算出全部点之间的最短路径),值得注意的是弗洛伊德不能解决带有“负权回路”(或者叫“负权环”)的图,因为带有“负权回路”的图没有最短路。

除此之外,求带负权值边的单源最短路径还可以用贝尔曼-福特算法。至于迪杰斯特拉比弗洛伊德快,也是因为他是单源的缘故。

如果看懂了点个赞,给点小动力,谢谢啦~

PS:最简单(代码量)实现寻找最短路径的弗洛伊德算法点这里

最短路径之Dijkstra(迪杰斯特拉)算法(无向图)相关推荐

  1. Dijkstra(迪杰斯特拉)算法求单源最短路径问题

    Dijkstra(迪杰斯特拉)算法求单源最短路径问题 重要的事情说三遍:代码不是我写的!代码不是我写的!代码不是我写的! 第一个算法是严蔚敏数据结构(C语言版)上写的,第二个算法是王道数据结构上写的, ...

  2. MATLAB轻松绘制地图路线——Dijkstra(迪杰斯特拉)算法最短路径规划

    文章目录 1. 地图绘制 2. 计算各节点之间的距离 3. Dijkstra(迪杰斯特拉)算法 4. 根据计算出的距离利用Dijkstra(迪杰斯特拉)算法找出指定节点之间的最短路径 工程文件(可直接 ...

  3. Dijkstra迪杰斯特拉算法 C++实现

    本篇文章主要介绍了Dijkstra迪杰斯特拉算法的C++实现,文章包含两个部分,在第一部分中我会简单介绍迪杰斯特拉算法以及一些个人的理解,第二部分会对C++代码的逻辑进行解释.下面是我已经上传的代码资 ...

  4. Dijkstra(迪杰斯特拉)算法

    一.简介 迪克斯特拉算法又名Dijkstra算法(属于贪心算法).Dijkstra算法是从一节点到其余各节点最短路径计算方法. 迪杰斯特拉算法以起始点为中心向外层层扩展,直到扩展到终点为止. 算法思想 ...

  5. 算法提升:图的Dijkstra(迪杰斯特拉)算法

    目录 概念 思路 代码 概念 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路 ...

  6. JavaScript实现dijkstra迪杰斯特拉算法(附完整源码)

    JavaScript实现dijkstra迪杰斯特拉算法 PriorityQueue完整源代码 MinHeap.js完整源代码 Heap.js完整源代码 Comparator.js完整源代码 dijks ...

  7. C++实现Dijkstra(迪杰斯特拉)算法(附完整源码)

    C++Dijkstra迪杰斯特拉算法的实现 C++Dijkstra(迪杰斯特拉)算法的完整源码(定义,实现,main函数测试) C++Dijkstra(迪杰斯特拉)算法的完整源码(定义,实现,main ...

  8. 图的应用---最短路径问题 用迪杰斯特拉算法解决 《地铁换乘问题》

    图的应用-最短路径问题 用迪杰斯特拉算法解决 <地铁换乘问题> 代码是在我学习的过程中完成的,也许会有问题,希望大家批评指正. 题目: 描述:已知2条地铁线路,其中A为环线,B为东西向线路 ...

  9. dijkstra迪杰斯特拉算法(邻接表法)

    算法简易过程: 迪杰斯特拉算法(朴素) O(n^2) G={V,E} V:点集合 E:边集合 初始化时 令 S={某源点ear}, T=V-S= {其余顶点},T中顶点对应的距离(ear, Vi)值若 ...

最新文章

  1. 分布式事务 -- seata框架AT模式实现原理
  2. python第六周实验_第六周实验四
  3. relative与absolute相结合
  4. python调用所有函数_python 调用函数
  5. 自由之战服务器显示登录失败,自由之战:生存的游戏一直登入不进去怎么办
  6. meterpreter--收集系统信息
  7. puppet负载均衡之nginx+passenger
  8. MSSQL获取当前日期及格式
  9. 如何自学生物信息学:从菜鸟到专家
  10. FileResponse django下载文件问题
  11. 手握IP却不知如何讲好城市故事?“宝藏天津”慢直播支招城市营销
  12. 如何系统地自学 Python?
  13. matlab 矩阵白化,主成分分析中如何对矩阵进行白化处理
  14. 面试之NGFW 性能测试
  15. 科比,老大1000天
  16. perl中正则匹配中文字符
  17. python qqplot 检验正态分布
  18. vue: Invalid prop: type check failed for prop “action“. Expected String with valu
  19. 太激动!Android修改全局字体样式,替换整个APP字体
  20. 【STM32F429】第4章 ThreadX FileX文件系统移植到STM32F429(SD卡)

热门文章

  1. 《2022大数据产业年度创新服务企业》榜重磅发布丨金猿奖
  2. 怎么计算机械加工产能,产能计算方法
  3. 手机QQ浏览器访问liferay工程页面异常解决
  4. 使用 checkra1n 越狱(非完美越狱)
  5. 1T固态硬盘Linux最优分区,1t固态硬盘如何分区才合理?
  6. 库存商品出入库方式分析
  7. iOS实现简单备忘录程序——TaskList
  8. vfifo控制mig_基于MIG IP核的DDR3控制器(一)
  9. Splashtop_Wired_XDisplay将手机或平板扩展为你的副屏
  10. 使用at命令创建定时任务