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中的闭包实例详解
Aug 29 Python
Python中列表元素转为数字的方法分析
Jun 14 Python
python中通过预先编译正则表达式提高效率
Sep 25 Python
python中的常量和变量代码详解
Jul 25 Python
8种用Python实现线性回归的方法对比详解
Jul 10 Python
python环境下安装opencv库的方法
Mar 05 Python
IDLE下Python文件编辑和运行操作
Apr 25 Python
python属于解释语言吗
Jun 11 Python
Python中zipfile压缩文件模块的基本使用教程
Jun 14 Python
Python sublime安装及配置过程详解
Jun 29 Python
关于 Python json中load和loads区别
Nov 07 Python
使用Python开发冰球小游戏
Apr 30 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
php中获取指定IP的物理地址的代码(正则表达式)
2011/06/23 PHP
深入探讨<br />和 \r\n两者有什么区别??
2013/06/05 PHP
使用php 获取时间今天明天昨天时间戳的详解
2013/06/20 PHP
php使用ICQ网关发送手机短信
2013/10/30 PHP
PHP中使用Imagick操作PSD文件实例
2015/01/26 PHP
PHP类相关知识点实例总结
2016/09/28 PHP
javascript 浏览器判断 绑定事件 arguments 转换数组 数组遍历
2009/07/06 Javascript
jquery插件 cluetip 关键词注释
2010/01/12 Javascript
in.js 一个轻量级的JavaScript颗粒化模块加载和依赖关系管理解决方案
2011/07/26 Javascript
jQuery对val和atrr(&quot;value&quot;)赋值的区别介绍
2014/09/26 Javascript
在HTML代码中使用JavaScript代码的例子
2014/10/16 Javascript
javascript中的this详解
2014/12/08 Javascript
js改变Iframe中Src的方法
2015/05/05 Javascript
jQuery EasyUI实现右键菜单变灰不可用效果
2015/09/24 Javascript
基于jQuery实现仿51job城市选择功能实例代码
2016/03/02 Javascript
基于JS实现数字+字母+中文的混合排序方法
2016/06/06 Javascript
vue路由导航守卫和请求拦截以及基于node的token认证的方法
2019/04/07 Javascript
wx-charts 微信小程序图表插件的具体使用
2019/08/18 Javascript
JavaScript实现表单验证功能
2020/12/09 Javascript
vue打开新窗口并实现传参的图文实例
2021/03/04 Vue.js
Python ZipFile模块详解
2013/11/01 Python
让python同时兼容python2和python3的8个技巧分享
2014/07/11 Python
python基础教程之面向对象的一些概念
2014/08/29 Python
零基础写python爬虫之使用urllib2组件抓取网页内容
2014/11/04 Python
Python实现处理管道的方法
2015/06/04 Python
TF-IDF算法解析与Python实现方法详解
2017/11/16 Python
Python人脸识别第三方库face_recognition接口说明文档
2019/05/03 Python
python中bytes和str类型的区别
2019/10/21 Python
Python实现自动整理文件的脚本
2020/12/17 Python
奇怪的鱼:Weird Fish
2018/03/18 全球购物
长辈证婚人证婚词
2014/01/09 职场文书
社会公德演讲稿
2014/05/20 职场文书
青年教师师德演讲稿
2014/08/26 职场文书
浪漫婚礼主题活动策划方案
2014/09/15 职场文书
追讨欠款律师函
2015/05/27 职场文书
JAVA 线程池(池化技术)的实现原理
2022/04/28 Java/Android