python Dijkstra算法实现最短路径问题的方法


Posted in Python onSeptember 19, 2019

本文借鉴于张广河教授主编的《数据结构》,对其中的代码进行了完善。

从某源点到其余各顶点的最短路径

Dijkstra算法可用于求解图中某源点到其余各顶点的最短路径。假设G={V,{E}}是含有n个顶点的有向图,以该图中顶点v为源点,使用Dijkstra算法求顶点v到图中其余各顶点的最短路径的基本思想如下:

  • 使用集合S记录已求得最短路径的终点,初始时S={v}。
  • 选择一条长度最小的最短路径,该路径的终点w属于V-S,将w并入S,并将该最短路径的长度记为Dw。
  • 对于V-S中任一顶点是s,将源点到顶点s的最短路径长度记为Ds,并将顶点w到顶点s的弧的权值记为Dws,若Dw+Dws<Ds,
  • 则将源点到顶点s的最短路径长度修改为Dw+Ds=ws。
  • 重复执行2和3,知道S=V。
  • 为了实现算法,
  • 使用邻接矩阵Arcs存储有向网,当i=j时,Arcs[i][j]=0;当i!=j时,若下标为i的顶点到下标为j的顶点有弧且弧的权值为w,则Arcs[i][j]=w,否则Arcs[i][j]=float(‘inf')即无穷大。
  • 使用Dist存储源点到每一个终点的最短路径长度。
  • 使用列表Path存储每一条最短路径中倒数第二个顶点的下标。
  • 使用flag记录每一个顶点是否已经求得最短路径,在思想中即是判断顶点是属于V集合,还是属于V-S集合。

代码实现

#构造有向图Graph
class Graph:
  def __init__(self,graph,labels): #labels为标点名称
    self.Arcs=graph
    self.VertexNum=graph.shape[0]
    self.labels=labels
def Dijkstra(self,Vertex,EndNode): #Vertex为源点,EndNode为终点
  Dist=[[] for i in range(self.VertexNum)] #存储源点到每一个终点的最短路径的长度
  Path=[[] for i in range(self.VertexNum)] #存储每一条最短路径中倒数第二个顶点的下标
  flag=[[] for i in range(self.VertexNum)] #记录每一个顶点是否求得最短路径
  index=0
  #初始化
  while index<self.VertexNum:
    Dist[index]=self.Arcs[Vertex][index]
    flag[index]=0
    if self.Arcs[Vertex][index]<float('inf'): #正无穷
      Path[index]=Vertex
    else:
      Path[index]=-1 #表示从顶点Vertex到index无路径
    index+=1
  flag[Vertex]=1
  Path[Vertex]=0
  Dist[Vertex]=0
  index=1
  while index<self.VertexNum:
    MinDist=float('inf')
    j=0
    while j<self.VertexNum:
      if flag[j]==0 and Dist[j]<MinDist:
        tVertex=j #tVertex为目前从V-S集合中找出的距离源点Vertex最断路径的顶点
        MinDist=Dist[j]
      j+=1
    flag[tVertex]=1
    EndVertex=0
    MinDist=float('inf') #表示无穷大,若两点间的距离小于MinDist说明两点间有路径
    #更新Dist列表,符合思想中第三条
    while EndVertex<self.VertexNum:
      if flag[EndVertex]==0:
        if self.Arcs[tVertex][EndVertex]<MinDist and Dist[
          tVertex]+self.Arcs[tVertex][EndVertex]<Dist[EndVertex]:
          Dist[EndVertex]=Dist[tVertex]+self.Arcs[tVertex][EndVertex]
          Path[EndVertex]=tVertex
      EndVertex+=1
    index+=1
  vertex_endnode_path=[] #存储从源点到终点的最短路径
  return Dist[EndNode],start_end_Path(Path,Vertex,EndNode,vertex_endnode_path)
#根据本文上述定义的Path递归求路径
def start_end_Path(Path,start,endnode,path):
  if start==endnode:
    path.append(start)
  else:
    path.append(endnode)
    start_end_Path(Path,start,Path[endnode],path)
  return path

if __name__=='__main__':
  #float('inf')表示无穷
  graph=np.array([[0,6,5,float('inf'),float('inf'),float('inf')],
          [float('inf'),0,2,8,float('inf'),float('inf')],
          [float('inf'),float('inf'),0,float('inf'),3,float('inf')],
          [float('inf'),float('inf'),7,0,float('inf'),9],
          [float('inf'),float('inf'),float('inf'),float('inf'),0,9],
          [float('inf'),float('inf'),float('inf'),float('inf'),0]])
  G=Graph(graph,labels=['a','b','c','d','e','f'])
  start=input('请输入源点')
  endnode=input('请输入终点')
  dist,path=Dijkstra(G,G.labels.index(start),G.labels.index(endnode))
  Path=[]
  for i in range(len(path)):
    Path.append(G.labels[path[len(path)-1-i]])
  print('从顶点{}到顶点{}的最短路径为:\n{}\n最短路径长度为:{}'.format(start,endnode,Path,dist))

输出结果如下:

请输入源点
a
请输入终点
f
从顶点a到顶点f的最短路径为:
['a', 'c', 'e', 'f']
最短路径长度为:17

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现dnspod自动更新dns解析的方法
Feb 14 Python
使用Python编写一个模仿CPU工作的程序
Apr 16 Python
R语言 vs Python对比:数据分析哪家强?
Nov 17 Python
浅谈机器学习需要的了解的十大算法
Dec 15 Python
利用 python 对目录下的文件进行过滤删除
Dec 27 Python
Python数据分析之双色球统计两个红和蓝球哪组合比例高的方法
Feb 03 Python
Python实现判断并移除列表指定位置元素的方法
Apr 13 Python
完美解决Pycharm无法导入包的问题 Unresolved reference
May 18 Python
Python配置虚拟环境图文步骤
May 20 Python
python定时任务 sched模块用法实例
Nov 04 Python
python创建学生成绩管理系统
Nov 22 Python
python函数超时自动退出的实操方法
Dec 28 Python
PHP统计代码行数的小代码
Sep 19 #Python
Python实现代码统计工具
Sep 19 #Python
python实现统计代码行数的小工具
Sep 19 #Python
python日志模块logbook使用方法
Sep 19 #Python
python统计指定目录内文件的代码行数
Sep 19 #Python
python如何从文件读取数据及解析
Sep 19 #Python
python实现代码统计器
Sep 19 #Python
You might like
古巴咖啡 Cubita琥爵咖啡 独特的加勒比海风味咖啡
2021/03/06 新手入门
使用PHP模拟HTTP认证
2006/10/09 PHP
一个简单安全的PHP验证码类、PHP验证码
2016/09/24 PHP
使用JavaScript 编写简单计算器
2014/11/24 Javascript
javascript中tostring()和valueof()的用法及两者的区别
2015/11/16 Javascript
全面解析Bootstrap弹窗的实现方法
2015/12/01 Javascript
jQuery进行组件开发完整实例
2015/12/15 Javascript
使用jQuery实现Web页面换肤功能的要点解析
2016/05/12 Javascript
JS实现添加,替换,删除节点元素的方法
2016/06/30 Javascript
jQuery实现的简单百分比进度条效果示例
2016/08/01 Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(三)
2016/09/14 Javascript
深入浅析vue组件间事件传递
2017/12/29 Javascript
Vue 父子组件的数据传递、修改和更新方法
2018/03/01 Javascript
vue弹窗插件实战代码
2018/09/08 Javascript
JS返回页面时自动回滚到历史浏览位置
2018/09/26 Javascript
微信小程序封装分享与分销功能过程解析
2019/08/13 Javascript
layui table单元格事件修改值的方法
2019/09/24 Javascript
原生javascript单例模式的应用实例分析
2020/02/23 Javascript
Vue中父子组件的值传递与方法传递
2020/09/28 Javascript
Vue实现点击当前行变色
2020/12/14 Vue.js
python中使用enumerate函数遍历元素实例
2014/06/16 Python
使用Python脚本将文字转换为图片的实例分享
2015/08/29 Python
python自动裁剪图像代码分享
2017/11/25 Python
关于Python 的简单栅格图像边界提取方法
2019/07/05 Python
Pycharm安装python库的方法
2020/11/24 Python
trivago美国:全球最大的酒店价格比较网站
2018/01/18 全球购物
澳大利亚在线家具、灯饰和家居装饰店:LivingStyles
2018/11/20 全球购物
包装类的功能、种类、常用方法
2012/01/27 面试题
database面试题
2013/03/28 面试题
优秀员工自荐书范文
2013/12/08 职场文书
公司庆典活动邀请函
2014/01/09 职场文书
竞选班干部演讲稿400字
2014/08/20 职场文书
一份恶作剧的检讨书
2014/09/13 职场文书
Python中的xlrd模块使用整理
2021/06/15 Python
详解Python中__new__方法的作用
2022/03/31 Python
Redis分布式锁的7种实现
2022/04/01 Redis