最短路径 Dijkstra 算法

最短路径 Dijkstra 算法解析数据结构输入思路输出Python 代码最短路径可以说是出名的算法问题了,无论现实中还是数据结构上都十分有意义,两点之间距离最短的走法。基于离散数学图论,对于给定的点级和边集,边的权值模拟距离。在无法确定中转还是直达最快的情况下,通过算法找出最短的距离。解析一般而言,Dijkstra 算法适用于单源点(入口)有向边,经过改进可适用于无向边。数据表示需要一种方法,处理则是核心。数据结构为了方便描述,所有点以数字或字母表示,以0或a作为入口。对于边集的表示两种方法
摘要由CSDN通过智能技术生成

最短路径 Dijkstra 算法

最短路径可以说是出名的算法问题了,无论现实中还是数据结构上都十分有意义,两点之间距离最短的走法。基于离散数学图论,对于给定的点级和边集,边的权值模拟距离。在无法确定中转还是直达最快的情况下,通过算法找出最短的距离。
图片来自网络

解析

一般而言,Dijkstra 算法适用于单源点(入口)有向边,经过改进可适用于无向边。数据表示需要一种方法,处理则是核心。

数据结构

为了方便描述,所有点以数字或字母表示,以0或a作为入口。
对于边集的表示两种方法:
用邻接矩阵,即如果两点间存在边就将权值放在二维数组,其他位置设为无限(以变量上限值标记)。个人觉得表示方法一般,优点是比较清晰。
在这里插入图片描述
第二种方法是用三元组表示每条边,格式为【起点,终点,权值】,比如 Py 里的 list、C/C++ 的结构体链表。个人认为边少时比较合适。在这里插入图片描述
另外需要用一个 visit 数组表示每个点是否访问过处理过,一个 via 数组表示两点间是直达还是从哪个点中转更快,下面会提到怎么写。(我重新命名了)
本文使用 Python:用三元组形式表示边,对于无边或不可达用 None 表示,处理上也就复杂一点;dist 数组为源点0到各边距离,当处理完就是最短距离;via 数组是一维的,如果到点i经过i表示直达,否则表示绕路。

输入

输入没什么好说,依次输入起点、终点、距离,找个条件退出输入。一般来说两点间同向边不能重复,必然有一个短一点没意义,输入函数可以用来检查是否重复。

思路

Dijkstra 算法用到了贪婪策略,将点分为已确认和未确认最短路径的两部分,每一轮取最短距离加入已处理集合。
首先将入口(本文是0)到各点距离加入到 dist,标记点0为已访问。然后找离点0最近的点进行下一波操作,最近的点就是确认了最短路径的,比如点2。
在这里插入图片描述
这里需要简单的数学证明:离0最近的点没有比直达的更短路径,如果存在中转的更短路径,中转点就是离0最近的而非这个点。比如图中点3不是离0最近,可能存在0-2的中转。对于已确认最短路径的点,可以看作一个整体,到下一个距离最短的点必然是最短路径。
现在以点2为中转点,检查到其它的点是否比原本更近,或者到达了新的点(在本文条件即0不能直达的),找到了 2-5 和 2-1,那么 dist 数组更新对应位置。
在这里插入图片描述
然后在未访问的点找最近的(0和2已访问),找到点5作为中转点,然后发现新到达点 5-4,另外 0(-2)-5-3 的距离比 dist 数组(即 0-3)短要修改。
在这里插入图片描述
然后是选择点1作为中转,找到 (0-2)-1-4 比当前到 (0-2-)-5-4 短,更新。在这里插入图片描述
然后选择点3,没有可更新的。
在这里插入图片描述
这个时候已经是完成了。虽然还有一个点没有访问,但是如果只剩一个点没有访问,其它点都找到最短路并且做过中转,那么剩下一个也是最短路径。单源点可以根据 false 剩余1个作为退出条件,如果强行在 Dijkstra 算法添加双源点,但是设定了源点,那么退出条件就是没法找到可访问的点,从设定的源点到多出来的源点距离 None 即不可达。本文采用后种方法退出。
在这里插入图片描述

输出

dist 数组比较简单,从0到各点最短距离就在数组。路径输出稍有难度,按照 via 数组情况举例,via[2] 是2表示0到2直连,举 via[3] 是5为例:到3要绕路经过5,到5要绕路经过2,到2就是直连,所以先输出 0-2,递归返回后输出 -5,然后递归返回输出 -3,结束。
在这里插入图片描述

Python 代码

这段代码稍微说下:因为懒得一条条边输入,没启用 inPath 函数,这个是用来输入一条边并且统计节点的;dijkstra 函数输入边的集合和点的数量,因为 None 不能和 int 比较,所以要先处理 None 的情况;view 函数直接放在处理好结束,findPath 函数通过递归找最短路径经过的点.

def dijkstra(path, amount):
    dist = [None]*
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值