python实现狄克斯特拉算法


Posted in Python onJanuary 17, 2019

一、简介

是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止

二、步骤

(1) 找出“最便宜”的节点,即可在最短时间内到达的节点。
(2) 更新该节点的邻居的开销,其含义将稍后介绍。
(3) 重复这个过程,直到对图中的每个节点都这样做了。
(4) 计算最终路径。

三、图解

python实现狄克斯特拉算法

上图中包括5个节点,箭头表示方向,线上的数字表示消耗时间。
首先根据上图做出一个初始表(父节点代表从哪个节点到达该节点):

python实现狄克斯特拉算法

然后从“起点”开始,根据图中的信息更新一下表,由于从“起点”不能直接到达“终点”节点,所以耗时为∞(无穷大):

python实现狄克斯特拉算法

有了这个表我们可以根据算法的步骤往下进行了。

第一步:找出“最便宜”的节点,这里是节点B:

python实现狄克斯特拉算法

第二步:更新该节点的邻居的开销,根据图从B出发可以到达A和“终点”节点,B目前的消耗2+B到A的消耗3=5,5小于原来A的消耗6,所以更新节点A相关的行:

python实现狄克斯特拉算法

同理,B目前消耗2+B到End的消耗5=7,小于∞,更新“终点”节点行:

python实现狄克斯特拉算法

B节点关联的节点已经更新完成,所以B节点不在后面的更新范围之内了:

python实现狄克斯特拉算法

找到下一个消耗最小的节点,那就是A节点:

python实现狄克斯特拉算法

根据A节点的消耗更新关联节点,只有End节点行被更新了:

python实现狄克斯特拉算法

这时候A节点也不在更新节点范围之内了:

python实现狄克斯特拉算法

最终表的数据如下:

python实现狄克斯特拉算法

根据最终表,从“起点”到“终点”的最少消耗是6,路径是起点->B->A->终点.

四、代码实现

# -*-coding:utf-8-*-
# 用散列表实现图的关系
# 创建节点的开销表,开销是指从"起点"到该节点的权重
graph = {}
graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2

graph["a"] = {}
graph["a"]["end"] = 1

graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["end"] = 5
graph["end"] = {}

# 无穷大
infinity = float("inf")
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["end"] = infinity

# 父节点散列表
parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["end"] = None

# 已经处理过的节点,需要记录
processed = []


# 找到开销最小的节点
def find_lowest_cost_node(costs):
 # 初始化数据
 lowest_cost = infinity
 lowest_cost_node = None
 # 遍历所有节点
 for node in costs:
 # 该节点没有被处理
 if not node in processed:
  # 如果当前节点的开销比已经存在的开销小,则更新该节点为开销最小的节点
  if costs[node] < lowest_cost:
  lowest_cost = costs[node]
  lowest_cost_node = node
 return lowest_cost_node


# 找到最短路径
def find_shortest_path():
 node = "end"
 shortest_path = ["end"]
 while parents[node] != "start":
 shortest_path.append(parents[node])
 node = parents[node]
 shortest_path.append("start")
 return shortest_path


# 寻找加权的最短路径
def dijkstra():
 # 查询到目前开销最小的节点
 node = find_lowest_cost_node(costs)
 # 只要有开销最小的节点就循环(这个while循环在所有节点都被处理过后结束)
 while node is not None:
 # 获取该节点当前开销
 cost = costs[node]
 # 获取该节点相邻的节点
 neighbors = graph[node]
 # 遍历当前节点的所有邻居
 for n in neighbors.keys():
  # 计算经过当前节点到达相邻结点的开销,即当前节点的开销加上当前节点到相邻节点的开销
  new_cost = cost + neighbors[n]
  # 如果经当前节点前往该邻居更近,就更新该邻居的开销
  if new_cost < costs[n]:
  costs[n] = new_cost
  #同时将该邻居的父节点设置为当前节点
  parents[n] = node
 # 将当前节点标记为处理过
 processed.append(node)
 # 找出接下来要处理的节点,并循环
 node = find_lowest_cost_node(costs)
 # 循环完毕说明所有节点都已经处理完毕
 shortest_path = find_shortest_path()
 shortest_path.reverse()
 print(shortest_path)
# 测试
dijkstra()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python编码时应该注意的几个情况
Mar 04 Python
Python中设置变量作为默认值时容易遇到的错误
Apr 03 Python
ubuntu系统下 python链接mysql数据库的方法
Jan 09 Python
利用python批量给云主机配置安全组的方法教程
Jun 21 Python
python difflib模块示例讲解
Sep 13 Python
Python Series从0开始索引的方法
Nov 06 Python
Python实现个人微信号自动监控告警的示例
Jul 03 Python
python如何求100以内的素数
May 27 Python
Python3 搭建Qt5 环境的方法示例
Jul 16 Python
使用django自带的user做外键的方法
Nov 30 Python
pytorch 一行代码查看网络参数总量的实现
May 12 Python
分析Python list操作为什么会错误
Nov 17 Python
在PyCharm下使用 ipython 交互式编程的方法
Jan 17 #Python
python最小生成树kruskal与prim算法详解
Jan 17 #Python
解决PyCharm不运行脚本,而是运行单元测试的问题
Jan 17 #Python
在PyCharm导航区中打开多个Project的关闭方法
Jan 17 #Python
Python设计模式之模板方法模式实例详解
Jan 17 #Python
Python设计模式之外观模式实例详解
Jan 17 #Python
Python pycharm 同时加载多个项目的方法
Jan 17 #Python
You might like
php 远程关机操作的代码
2008/12/05 PHP
使用PHP备份MYSQL数据的多种方法
2014/01/15 PHP
smarty中js的调用方法示例
2014/10/27 PHP
php使用Image Magick将PDF文件转换为JPG文件的方法
2015/04/01 PHP
php使用标签替换的方式生成静态页面
2015/05/21 PHP
Yii2框架制作RESTful风格的API快速入门教程
2016/11/08 PHP
php 如何禁用eval() 函数实例详解
2016/12/01 PHP
php实现的中文分词类完整实例
2017/02/06 PHP
Yii框架中用response保存cookie,用request读取cookie的原理解析
2019/09/04 PHP
19个很有用的 JavaScript库推荐
2011/06/27 Javascript
JavaScript自动设置IFrame高度的小例子
2013/06/08 Javascript
struts2+jquery组合验证注册用户是否存在
2014/04/30 Javascript
javascript如何创建对象
2016/08/29 Javascript
ES6(ECMAScript 6)新特性之模板字符串用法分析
2017/04/01 Javascript
微信小程序checkbox组件使用详解
2018/01/31 Javascript
Vue动画事件详解及过渡动画实例
2019/02/09 Javascript
微信小程序图表插件wx-charts用法实例详解
2019/05/20 Javascript
JS实现点击发送验证码 xx秒后重新发送功能
2019/07/30 Javascript
Vue+elementui 实现复杂表头和动态增加列的二维表格功能
2019/09/23 Javascript
mpvue实现左侧导航与右侧内容的联动
2019/10/21 Javascript
vue输入框使用模糊搜索功能的实现代码
2020/05/26 Javascript
Python实现抓取百度搜索结果页的网站标题信息
2015/01/22 Python
解决pyqt中ui编译成窗体.py中文乱码的问题
2016/12/23 Python
Python3单行定义多个变量或赋值方法
2018/07/12 Python
Python 实现两个服务器之间文件的上传方法
2019/02/13 Python
pandas 数据结构之Series的使用方法
2019/06/21 Python
Python中的正则表达式与JSON数据交换格式
2019/07/03 Python
TensorFlow设置日志级别的几种方式小结
2020/02/04 Python
解决PyCharm不在run输出运行结果而不是再Console里输出的问题
2020/09/21 Python
个人简历自我评价
2014/01/06 职场文书
物业工作计划书
2014/01/10 职场文书
劲霸男装广告词
2014/03/21 职场文书
2014小学一年级班主任工作总结
2014/12/05 职场文书
2015年政风行风工作总结
2015/04/21 职场文书
教师个人师德工作总结2015
2015/05/12 职场文书
详解Vue的options
2021/05/15 Vue.js