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将html转成PDF的实现代码(包含中文)
Mar 04 Python
python实现电子词典
Apr 23 Python
python超简单解决约瑟夫环问题
May 12 Python
详解在Python程序中自定义异常的方法
Oct 16 Python
jupyter安装小结
Mar 13 Python
Python 模拟员工信息数据库操作的实例
Oct 23 Python
Python中的pygal安装和绘制直方图代码分享
Dec 08 Python
Python 查找list中的某个元素的所有的下标方法
Jun 27 Python
Python求两个圆的交点坐标或三个圆的交点坐标方法
Nov 07 Python
浅谈pyqt5中信号与槽的认识
Feb 17 Python
Python pandas对excel的操作实现示例
Jul 21 Python
pycharm全局搜索的具体步骤
Jul 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
基于curl数据采集之单页面并行采集函数get_htmls的使用
2013/04/28 PHP
PHP定时任务延缓执行的实现
2014/10/08 PHP
PHP加密解密实例分析
2015/12/25 PHP
PHP简单实现二维数组赋值与遍历功能示例
2017/10/19 PHP
PHP实现转盘抽奖算法分享
2020/04/15 PHP
php提取微信账单的有效信息
2018/10/01 PHP
初窥JQuery(二)事件机制(2)
2010/12/06 Javascript
浅说js变量
2011/05/25 Javascript
js操作输入框提示信息且响应鼠标事件
2014/03/25 Javascript
js实现简单排列组合的方法
2016/01/27 Javascript
JavaScript模拟push
2016/03/06 Javascript
好好了解一下Cookie(强烈推荐)
2016/06/14 Javascript
浅析Javascript ES6中的原生Promise
2016/08/25 Javascript
jQuery实现ajax无刷新分页页码控件
2017/02/28 Javascript
ReactNative实现图片上传功能的示例代码
2017/07/11 Javascript
js实现把时间戳转换为yyyy-MM-dd hh:mm 格式(es6语法)
2017/12/28 Javascript
js逆向解密之网络爬虫
2019/05/30 Javascript
Electron 调用命令行(cmd)
2019/09/23 Javascript
JS实现前端路由功能示例【原生路由】
2020/05/29 Javascript
微信小程序实现多图上传
2020/06/19 Javascript
Python 基础教程之str和repr的详解
2017/08/20 Python
关于Python数据结构中字典的心得
2017/12/04 Python
浅谈Python中重载isinstance继承关系的问题
2018/05/04 Python
Django模型修改及数据迁移实现解析
2019/08/01 Python
Python如何调用外部系统命令
2019/08/07 Python
详解Pycharm出现out of memory的终极解决方法
2020/03/03 Python
tensorflow安装成功import tensorflow 出现问题
2020/04/16 Python
Html5插件教程之添加浏览器放大镜效果的商品橱窗
2016/01/07 HTML / CSS
SmartBuyGlasses荷兰:购买太阳镜和眼镜
2020/03/16 全球购物
交通文明倡议书
2014/05/16 职场文书
广播体操比赛口号
2014/06/10 职场文书
乡镇民主生活会发言材料
2014/10/20 职场文书
少先队辅导员事迹材料
2014/12/24 职场文书
刑事法律意见书
2015/06/04 职场文书
USB TYPE-C 或将成为所有智能手机充电标准
2022/04/21 数码科技
mysql字段为NULL索引是否会失效实例详解
2022/05/30 MySQL