讲清迪杰斯特拉(DIJKSTRA)算法,附python代码
最近有个同事问我迪杰斯特拉算法,以前都是直接用,三个循环体直接一套就出来,具体逻辑懒得去理解,这次被问到,就花了点时间理了理算法的底层逻辑。
---------
迪杰斯特拉算法是搜索出所有点到起点的最短距离。
怎么找?
第一步,找出距离V0最近距离的点,设为V2。(显然此时V2的最短路径已经找到,就是V2直达路径。)
第二步,以V2为中转点mid_Node,用m替代
(Lx0,表示Vx到V0的距离,Lxm表示Vx到mid_Node的距离,其他同理)
第三步,取其他任意点Vx,比较Lx0和Lxm+Lm0的大小,令cost[X]=min(Lx0,LXm+Lm0),即找到了点x到0的更短路径,并更新进cost数组里。(其实就是让其他点尝试以mid_Node为中转,能否缩短路径,若能,就更新最短路径。)在for循环里把所有的点都尝试一遍中转方案,并把最短路径更新。(对应代码里 for NEXT_Node in range(lenth):循环体的内容)
第四步,搜索cost数组里的最短路径(除被选为mid_Node的点外,点是否选过为mid_Node是用数组v[]做标记,在if语句中判断,V[X]代表X是否已找到最短路径,1是,0不是。实际上被选为mid_Node就表示该点已经找到抵达V0的最短路径。这个等下会解释,先把流程弄清)
第五步,把第三步里搜索到最短路径的端点设置为mid_Node,并且在V数组里把该端点的标志位置1.
第六步,判断是否所有点都设置为过mid_Node,是则结束,否则跳转到第三步。
--------
结合图片走一下步骤
贴一下几个代码会用到的数组变量
cost[i] 表示V0到Vi的已知最短路径长度
mid_Node:中转点,以已求得V0到Vi的最短路径的Vi作为中转点。
NEXT_Node:尝试优化的点,以中转点为中心,检测NEXT_Node直达V0方案,和经过mid_Node中转到V0的方案哪个更优
check_Node:索引,搜索cost数组里最短路径的点,最短的点会赋值给mid_Node,作为中转点。
V数组用来存放标志位,表示是否已经找到x点的最短路径,找到则V[x]=1,否则为0,这是为了避免陷入死循环,一直卡在第一条最短路径出不来。
cost数组初始化时是所有点到V0的距离,即cost=[0,4,1,max,5,max,max,max]
第一步,显然选中V2,
第二步,V2作为中转点,
第三步,尝试优化其他点,其他点把中转点作为中转,比较能否缩短到V0的距离,这里能看到,V4经过V2中转后,到V0距离短了由5变为3,V3由无穷远变为6,其他点经过V2中转反而更长(变为无法抵达,即无穷远,因为其他点无法直达V2,到V2的距离是max)。把优化后的值更新进cost数组。
此时cost=[0,4,1,6,3,max,max,max]
第四步,选取cost数组里除cost[0],cost[2]以外最短的路径,显然是3,即cost[4],取得的端点是V4
第五步,把V4作为中转点,并把V数组的标志位置1,表示已找到V4的最短路径。
第六步,跳转到第三步循环,直到所有点都找到最短路径。
前面遗留的问题:被选为mid_Node就表示该点已经找到抵达V0的最短路径
这也是迪杰斯特拉算法里最绕的一个地方-----凭什么确定这个点已经找到了最短路径?
迪杰斯特拉算法的核心思想就是每次选mid_Node都是取cost数组待探索点里距离最小的( for check_Node in range(lenth):循环里做的)。也就是说,这条路径在剩下其他已知路径里已经是最小了,没法再优化了。为什么说没法优化了?
因为唯一可行的优化方法就是用比该点Vx到V0的路径Lx0更短的路径Lm0作为中转,中转距离就是Lxm+L0m,(这个路径优化就是for NEXT_Node in range(lenth)循环里做的事,选取mid_Node前已经做完了,所以可行的优化方法已经优化过了),
剩下的所有优化方案,只剩下用比Lx0(或Lm0+Lxm,取决于哪个更小)更长的路径作为中转。这显然是绕弯路了,必然增加长度,没必要尝试,所以没法再优化了,故得到的就是Vx到V0的最短路径。
python代码实现如下:
代码和前文示例的图片不对应,图片是随手画的,强迫症可以复制一下代码改一下数组和cost,path,range的长度,就能对应到图片了
def dijkstra(graph, start_Node, path, cost, max):"""graph:二维数组,就是用行列坐标表示图形上两点之间的距离。start_Node:起始点path[i] 表示vi节点的前一个节点,即中转点。cost[i] 表示V0到Vi的已知最短路径长度mid_Node:中转点,以已求得V0到Vi的最短路径的Vi作为中转点。NEXT_Node:尝试优化的点,以中转点为中心,检测NEXT_Node直达V0方案,和经过mid_Node中转到V0的方案哪个更优check_Node:索引,搜索cost数组里最短路径的点,最短的点会赋值给mid_Node,作为中转点。"""lenth = len(graph)v = [0] * lenth # V数组初始化为0,用于标记该点是否已取得最短路径# 初始化 path,cost,Vfor i in range(lenth):if i == start_Node:v[start_Node] = 1else:cost[i] = graph[start_Node][i] # cost获取起点至其他点的直达权重path[i] = (start_Node if (cost[i] < max) else -1) # 前置点为起点或-1(无法直达起点)# print v, cost, pathfor i in range(1, lenth): # 遍历的数等于除去起点的点的数量minCost = max # 初始值取最大mid_Node = -1for check_Node in range(lenth): # 搜索一个到起点V0最近的点,作为中转点mid_Nodeif v[check_Node] == 0 and cost[check_Node] < minCost: # mid_Node点未取得最短路径,且路径权重小于最小值,则获取w,也就是先取得minCost = cost[check_Node]mid_Node = check_Nodeif mid_Node == -1: break # 找不到权重小于max的点# 剩下都是不可通行的节点,跳出循环v[mid_Node] = 1 # check_Node已取得最短路径for NEXT_Node in range(lenth):if v[NEXT_Node] == 0 and (graph[mid_Node][NEXT_Node] + cost[mid_Node] < cost[NEXT_Node]): # 检查所有未遍历的点NEXT_Node,检测前面获取的mid_Node对NEXT_Node的影响cost[NEXT_Node] = graph[mid_Node][NEXT_Node] + cost[mid_Node] # 更新权值path[NEXT_Node] = mid_Node # 更新路径# for 更新其他节点的权值(距离)和路径return pathif __name__ == '__main__':max = 999999 # max即表示为无法直达graph = [[5, max, 10, max, 30, 100],[max, max, 5, max, max, max],[max, 15, max, 50, max, max],[max, max, max, max, max, 10],[max, max, max, 20, max, 60],[max, 15, max, max, max, max],]path = [0] * 6cost = [0] * 6print(dijkstra(graph, 0, path, cost, max))print(cost)
讲清迪杰斯特拉(DIJKSTRA)算法,附python代码相关推荐
- 迪杰斯特拉dijkstra算法的python实现
原图链接:http://www.cnblogs.com/skywang12345/p/3711516.html 本文以下图为例,用dijkstra算法计算由节点D至其它所有节点的最短路径 此时,起点D ...
- 数据结构与算法(7-4)最短路径(迪杰斯特拉(Dijkstra)算法、弗洛伊德(Floyd)算法)
目录 一.最短路径概念 二.迪杰斯特拉(Dijkstra)算法(单源最短路径) 1.原理 2.过程 3.代码 三.弗洛伊德(Floyd)算法(多源最短路径) 1.原理 2.存储 3.遍历 4.代码 参 ...
- 059.迪杰斯特拉(Dijkstra)算法的原理以及解决最短路径问题
1. 迪杰斯特拉(Dijkstra)算法的原理 1.1. 算法应用场景-最短路径问题 1.2. 基本介绍 1.3. 步骤详解 1.4. 思路解析 1.5. 图解步骤 2. 迪杰斯特拉(Dijkstra ...
- java数据结构和算法——迪杰斯特拉(Dijkstra)算法
目录 一.迪杰斯特拉(Dijkstra)算法介绍 二.迪杰斯特拉(Dijkstra)算法过程 三.迪杰斯特拉(Dijkstra)算法--应用场景(最短路径问题) 四.迪杰斯特拉(Dijkstra)算法 ...
- 迪杰斯特拉(Dijkstra)算法解决最短路径问题
Dijkstra 算法介绍 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法.迪杰斯特拉(Dijkstra)算法是最经典的最短路径算法之一,用 ...
- 最短路径算法-迪杰斯特拉(Dijkstra)算法
最短路径算法-迪杰斯特拉(Dijkstra)算法 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思 ...
- Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法
1.Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法 1.1 迪杰斯特拉(Dijkstra)算法 1.1.1 迪杰斯特拉(Dijkstra)算法介绍 迪杰斯特拉(Dijkstra ...
- java实现迪杰斯特拉(Dijkstra)算法求解最短路问题
迪杰斯特拉(Dijkstra)算法是由荷兰计算机科学家狄克斯特拉于1959年提出的.是寻找从一个顶点到其余各顶点的最短路径算法,可用来解决最短路径问题. 迪杰斯特拉算法采用贪心算法的策略,将所有顶点分 ...
- 数据结构——图——迪杰斯特拉(Dijkstra )算法
数据结构--图--迪杰斯特拉(Dijkstra )算法 这是一个按路径长度递增的次序产生最短路径的算法.它的思路大体是这样的. 比如说要求图7-7-3中顶点v0到顶点v1的最短距离,没有比这更简单的了 ...
最新文章
- JS+Canvas的棋盘游戏和Java的动态结合
- localdatetime获得时间搓_得用户者得天下,一禅小和尚×往事若茶如何获得消费者认同...
- redis实现session共享,哨兵
- Python系列之入门篇——HDFS
- python io多路复用框架_python之IO多路复用
- python xml转字典_python xml转成dict
- Google Code的简单使用
- python爬取小猪短租信息
- Matlab计算器设计
- 优化网页加载各项的讨论
- ICMAX解析无线路由器WAN口应该怎么设置
- android ListView中含有按钮事件实时更新ListView数据案例-1
- 360°幻影成像展示产品,带来逼真的视觉效果
- 为什么Android没有iOS顺滑zz
- 人工智能在医疗发展突破分析
- 李建忠老师-设计模式
- 谷歌实现移动VR“白日梦”
- 如何在Microsoft Edge中更改主页
- mysql用于检索的关键字_Mysql全文搜索match...against的用法
- 新能源车,许家印的雄心,恒大的第二战场