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制作最美应用的爬虫
Oct 28 Python
彻底搞懂Python字符编码
Jan 23 Python
Tornado Web Server框架编写简易Python服务器
Jul 28 Python
python+opencv+caffe+摄像头做目标检测的实例代码
Aug 03 Python
解决pycharm的Python console不能调试当前程序的问题
Jan 20 Python
Python os.access()用法实例
Feb 18 Python
python把转列表为集合的方法
Jun 28 Python
Python IDE Pycharm中的快捷键列表用法
Aug 08 Python
python3 下载网络图片代码实例
Aug 27 Python
Python 共享变量加锁、释放详解
Aug 28 Python
简单了解Pandas缺失值处理方法
Nov 16 Python
完美解决pyinstaller打包报错找不到依赖pypiwin32或pywin32-ctypes的错误
Apr 01 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
dedecms采集中可以过滤多行代码的正则表达式
2007/03/17 PHP
一个php生成16位随机数的代码(两种方法)
2014/09/16 PHP
PHP统一页面编码避免乱码问题
2015/04/09 PHP
PHP 实现页面静态化的几种方法
2017/07/23 PHP
yii 框架实现按天,月,年,自定义时间段统计数据的方法分析
2020/04/04 PHP
javascript 建设银行登陆键盘
2008/06/10 Javascript
jQuery Lightbox 图片展示插件使用说明
2010/04/25 Javascript
jquery购物车实时结算特效实现思路
2013/09/23 Javascript
Jquery 垂直多级手风琴菜单附源码下载
2015/11/17 Javascript
JS制作类似选项卡切换的年历
2016/12/03 Javascript
微信小程序 开发经验整理
2017/02/15 Javascript
jquery实现下拉菜单的手风琴效果
2017/07/23 jQuery
JS模拟实现哈希表及应用详解
2018/05/04 Javascript
Vue自定义指令封装节流函数的方法示例
2018/07/09 Javascript
微信小程序页面上下滚动效果
2020/11/18 Javascript
vue实现点击追加选中样式效果
2019/11/01 Javascript
js实现省级联动(数据结构优化)
2020/07/17 Javascript
JavaScript实现瀑布流布局的3种方式
2020/12/27 Javascript
一篇不错的Python入门教程
2007/02/08 Python
使用Python中的线程进行网络编程的入门教程
2015/04/15 Python
Python基础教程之内置函数locals()和globals()用法分析
2018/03/16 Python
python list删除元素时要注意的坑点分享
2018/04/18 Python
python的sorted用法详解
2019/06/25 Python
pytorch中nn.Conv1d的用法详解
2019/12/31 Python
编写python代码实现简单抽奖器
2020/10/20 Python
美国电力供应商店/电气批发商:USESI
2018/10/12 全球购物
UDP协议功能
2013/01/06 面试题
小区门卫岗位职责
2013/12/31 职场文书
百年校庆节目主持词
2014/03/27 职场文书
工程材料采购方案
2014/05/18 职场文书
安全环保演讲稿
2014/08/28 职场文书
个人批评与自我批评范文
2014/10/17 职场文书
2016年大学迎新工作总结
2015/10/14 职场文书
2016优秀青年志愿者事迹材料
2016/02/25 职场文书
介绍信应该怎么开?
2019/04/03 职场文书
安装Ruby和 Rails的详细步骤
2022/04/19 Ruby