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的Django框架安装全攻略
Jul 15 Python
Google开源的Python格式化工具YAPF的安装和使用教程
May 31 Python
Python基于分水岭算法解决走迷宫游戏示例
Sep 26 Python
python实现壁纸批量下载代码实例
Jan 25 Python
python安装pil库方法及代码
Jun 25 Python
python 绘制拟合曲线并加指定点标识的实现
Jul 10 Python
Python 元组操作总结
Sep 18 Python
Pytorch的mean和std调查实例
Jan 02 Python
Python小白不正确的使用类变量实例
May 29 Python
python使用bs4爬取boss直聘静态页面
Oct 10 Python
python画图时设置分辨率和画布大小的实现(plt.figure())
Jan 08 Python
使用python求解迷宫问题的三种实现方法
Mar 17 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中的字符串函数
2006/10/09 PHP
PHP版自动生成文章摘要
2008/07/23 PHP
apache和PHP如何整合在一起
2015/10/12 PHP
Laravel SQL语句记录方式(推荐)
2016/05/26 PHP
Laravel 5.3 学习笔记之 配置
2016/08/28 PHP
Yii2框架RESTful API 格式化响应,授权认证和速率限制三部分详解
2016/11/10 PHP
一个对于Array的简单扩展
2006/10/03 Javascript
JQuery 前台切换网站的样式实现
2009/06/22 Javascript
js和jquery批量绑定事件传参数一(新猪猪原创)
2010/06/23 Javascript
jquery获取div宽度的实现思路与代码
2013/01/13 Javascript
ECMAScript6快速入手攻略
2016/07/18 Javascript
使用JavaScript判断用户输入的是否为正整数(两种方法)
2017/02/05 Javascript
深入浅析Vue 中 ref 的使用
2019/04/29 Javascript
3分钟读懂移动端rem使用方法(推荐)
2019/05/06 Javascript
JS数据类型STRING使用实例解析
2019/12/18 Javascript
微信小程序swiper组件实现抖音翻页切换视频功能的实例代码
2020/06/24 Javascript
JavaScript检测是否开启了控制台(F12调试工具)
2020/10/02 Javascript
[40:03]DOTA2上海特级锦标赛主赛事日 - 1 败者组第一轮#1EHOME VS Archon
2016/03/02 DOTA
python在windows下实现备份程序实例
2014/07/04 Python
python文件操作之目录遍历实例分析
2015/05/20 Python
Python的Django中django-userena组件的简单使用教程
2015/05/30 Python
python中int与str互转方法
2018/07/02 Python
python代码实现TSNE降维数据可视化教程
2020/02/28 Python
基于python requests selenium爬取excel vba过程解析
2020/08/12 Python
微信html5页面调用第三方位置导航的示例
2018/03/14 HTML / CSS
世界首屈一指的在线男士内衣权威:HisRoom
2017/08/05 全球购物
HolidayLettings英国:预订最好的度假公寓、别墅和自助式住宿
2019/08/27 全球购物
小车司机岗位职责
2013/11/25 职场文书
党员思想汇报范文
2013/12/30 职场文书
小学国旗下的演讲稿
2014/08/28 职场文书
学习十八大标语
2014/10/09 职场文书
2014年教学工作总结
2014/11/13 职场文书
学生病假条怎么写
2015/08/17 职场文书
老干部局2015年度工作总结
2015/10/22 职场文书
关于办理居住证的介绍信模板
2019/11/27 职场文书
python装饰器代码解析
2022/03/23 Python