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实现微信头像加红色数字功能
Mar 26 Python
python pandas消除空值和空格以及 Nan数据替换方法
Oct 30 Python
解决python3 HTMLTestRunner测试报告中文乱码的问题
Dec 17 Python
用Python画一个LinkinPark的logo代码实例
Sep 10 Python
为什么说Python可以实现所有的算法
Oct 04 Python
Python 日期的转换及计算的具体使用详解
Jan 16 Python
python json load json 数据后出现乱序的解决方案
Feb 27 Python
通过Python扫描代码关键字并进行预警的实现方法
May 24 Python
python调用私有属性的方法总结
Jul 24 Python
python中常用的数据结构介绍
Jan 12 Python
pytorch Dataset,DataLoader产生自定义的训练数据案例
Mar 03 Python
Django使用echarts进行可视化展示的实践
Jun 10 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
DC最新动画电影:《战争之子》为何内容偏激,毁了一个不错的漫画
2020/04/09 欧美动漫
提升PHP执行速度全攻略
2006/10/09 PHP
用Zend Encode编写开发PHP程序
2010/02/21 PHP
PHP类相关知识点实例总结
2016/09/28 PHP
Array.slice()与Array.splice()的返回值类型
2006/10/09 Javascript
JavaScipt基本教程之JavaScript语言的基础
2008/01/16 Javascript
jquery向上向下取整适合分页查询
2014/09/06 Javascript
深入理解JavaScript系列(22):S.O.L.I.D五大原则之依赖倒置原则DIP详解
2015/03/05 Javascript
在windows上用nodejs搭建静态文件服务器的简单方法
2016/08/11 NodeJs
jQuery实现两个select控件的互移操作
2016/12/22 Javascript
jquery.form.js异步提交表单详解
2017/04/25 jQuery
js 监控iframe URL的变化实例代码
2017/07/12 Javascript
Angularjs上传文件组件flowjs功能
2017/08/07 Javascript
解决vue 中 echart 在子组件中只显示一次的问题
2018/08/07 Javascript
IE8中jQuery.load()加载页面不显示的原因
2018/11/15 jQuery
vue slot与传参实例代码讲解
2019/04/28 Javascript
layui 解决富文本框form表单提交为空的问题
2019/10/26 Javascript
JavaScript实现拖拽盒子效果
2020/02/06 Javascript
JavaScript实现简单的图片切换功能(实例代码)
2020/04/10 Javascript
Vue实现简单的拖拽效果
2020/08/25 Javascript
[54:15]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第二场2月1日
2021/03/11 DOTA
python常见的格式化输出小结
2016/12/15 Python
Python基于回溯法子集树模板解决全排列问题示例
2017/09/07 Python
python绘制直方图和密度图的实例
2019/07/08 Python
Python实现多线程/多进程的TCP服务器
2019/09/03 Python
Python数据库封装实现代码示例解析
2020/09/05 Python
薇诺娜官方网上商城:专注敏感肌肤
2017/05/25 全球购物
新加坡领先的在线生活方式和杂货购物网站:EAMART
2019/04/02 全球购物
信息技术专业大学生个人的自我评价
2013/10/05 职场文书
接待员岗位责任制
2014/02/10 职场文书
公司证明怎么写
2014/09/22 职场文书
乡镇群众路线教育实践活动整改措施
2014/10/04 职场文书
工程承包协议书
2014/10/20 职场文书
简单且有用的Python数据分析和机器学习代码
2021/07/02 Python
如何利用golang运用mysql数据库
2022/03/13 Golang
Python测试框架pytest高阶用法全面详解
2022/06/01 Python