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 相关文章推荐
pycharm 使用心得(六)进行简单的数据库管理
Jun 06 Python
使用graphics.py实现2048小游戏
Mar 10 Python
node.js获取参数的常用方法(总结)
May 29 Python
Python内置模块turtle绘图详解
Dec 09 Python
python opencv之SURF算法示例
Feb 24 Python
python+splinter实现12306网站刷票并自动购票流程
Sep 25 Python
python如何发布自已pip项目的方法步骤
Oct 09 Python
Python函数装饰器常见使用方法实例详解
Mar 30 Python
使用Python代码实现Linux中的ls遍历目录命令的实例代码
Sep 07 Python
Python实现打印实心和空心菱形
Nov 23 Python
python nohup 实现远程运行不宕机操作
Apr 16 Python
python修改微信和支付宝步数的示例代码
Oct 12 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,不用COM,生成excel文件
2006/10/09 PHP
dedecms中显示数字验证码的修改方法
2007/03/21 PHP
thinkphp3.2实现在线留言提交验证码功能
2017/07/19 PHP
kindeditor 加入七牛云上传的实例讲解
2017/11/12 PHP
PHP常用header头定义代码示例汇总
2020/08/29 PHP
IE和Mozilla的兼容性汇总event
2007/08/12 Javascript
JavaScript中SQL语句的应用实现
2010/05/04 Javascript
JavaScrip实现PHP print_r的数功能(三种方法)
2013/11/12 Javascript
JS小功能(offsetLeft实现图片滚动效果)实例代码
2013/11/28 Javascript
FF IE浏览器修改标签透明度的方法
2014/01/27 Javascript
JS+CSS实现表格高亮的方法
2015/08/05 Javascript
js跨域请求数据的3种常用的方法
2015/12/01 Javascript
JS+HTML5实现上传图片预览效果完整实例【测试可用】
2017/04/20 Javascript
使用InstantClick.js让页面提前加载200ms
2017/09/12 Javascript
微信小程序登录按钮遮罩浮层效果的实现方法
2018/12/16 Javascript
说说Vuex的getters属性的具体用法
2019/04/15 Javascript
[01:12:44]VG vs Mineski Supermajor 败者组 BO3 第二场 6.6
2018/06/07 DOTA
Python增强赋值和共享引用注意事项小结
2019/05/28 Python
python logging添加filter教程
2019/12/24 Python
Python MySQLdb 执行sql语句时的参数传递方式
2020/03/04 Python
python3+selenium获取页面加载的所有静态资源文件链接操作
2020/05/04 Python
详解CSS3媒体查询响应式布局bootstrap 框架原理实战(推荐)
2020/11/16 HTML / CSS
HTML5实现简单图片上传所遇到的问题及解决办法
2016/01/20 HTML / CSS
Hotels.com印度:酒店预订
2019/05/11 全球购物
关于VPN
2012/06/10 面试题
信息部岗位职责
2013/11/12 职场文书
经理管理专业自荐信范文
2013/12/31 职场文书
教师求职信范文
2014/05/24 职场文书
交通工程专业推荐信
2014/09/06 职场文书
党员干部批评与自我批评反四风思想汇报
2014/09/21 职场文书
2014国庆节国旗下演讲稿(精选版)
2014/09/26 职场文书
银行职员工作失误检讨书
2014/10/14 职场文书
公司内部升职自荐信
2015/03/27 职场文书
道士塔读书笔记
2015/06/30 职场文书
2016春季运动会通讯稿
2015/07/18 职场文书
python opencv旋转图片的使用方法
2021/06/04 Python