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多线程扫描端口示例
Jan 16 Python
python删除过期文件的方法
May 29 Python
python安装numpy&amp;安装matplotlib&amp; scipy的教程
Nov 02 Python
Django+Ajax+jQuery实现网页动态更新的实例
May 28 Python
Python实现的个人所得税计算器示例
Jun 01 Python
python通过Windows下远程控制Linux系统
Jun 20 Python
Flask框架通过Flask_login实现用户登录功能示例
Jul 17 Python
Python类的继承、多态及获取对象信息操作详解
Feb 28 Python
Python3中编码与解码之Unicode与bytes的讲解
Feb 28 Python
python实现简单学生信息管理系统
Apr 09 Python
Python3之乱码\xe6\x97\xa0\xe6\xb3\x95处理方式
May 11 Python
详细分析Python collections工具库
Jul 16 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&amp;MYSQL留言板源码
2020/07/19 PHP
用php简单实现加减乘除计算器
2014/01/06 PHP
php显示指定目录下子目录的方法
2015/03/20 PHP
Zend Framework动作助手Url用法详解
2016/03/05 PHP
javascript返回顶部效果(自写代码)
2013/01/06 Javascript
博客侧边栏模块跟随滚动条滑动固定效果的实现方法(js+jquery等)
2013/03/24 Javascript
node.js中的fs.readFile方法使用说明
2014/12/15 Javascript
在JavaScript中使用对数Math.log()方法的教程
2015/06/15 Javascript
js实现表单检测及表单提示的方法
2015/08/14 Javascript
JS+CSS实现类似QQ好友及黑名单效果的树型菜单
2015/09/22 Javascript
基于jQuery实现的美观星级评论打分组件代码
2015/10/30 Javascript
JavaScript弹出对话框的三种方式
2016/03/23 Javascript
AngularJs解决跨域问题案例详解(简单方法)
2016/05/19 Javascript
JS 实现导航菜单中的二级下拉菜单的几种方式
2016/10/31 Javascript
仿iframe效果Aajx文件上传实例
2016/11/18 Javascript
如何判断出一个js对象是否一个dom对象
2016/11/24 Javascript
使用Vue.js创建一个时间跟踪的单页应用
2016/11/28 Javascript
JS中检测数据类型的几种方式及优缺点小结
2016/12/12 Javascript
老生常谈js-react组件生命周期
2017/05/02 Javascript
Angular.js中ng-include用法及多标签页面的实现方式详解
2017/05/07 Javascript
浅谈NodeJs之数据库异常处理
2017/10/25 NodeJs
如何实现双向绑定mvvm的原理实现
2019/05/28 Javascript
python实现发送邮件及附件功能
2021/03/02 Python
浅谈python for循环的巧妙运用(迭代、列表生成式)
2017/09/26 Python
Python 创建新文件时避免覆盖已有的同名文件的解决方法
2018/11/16 Python
深入浅析Python中的迭代器
2019/06/04 Python
python程序 创建多线程过程详解
2019/09/23 Python
python 对任意数据和曲线进行拟合并求出函数表达式的三种解决方案
2020/02/18 Python
如何在Python 游戏中模拟引力
2020/03/27 Python
Python发送邮件实现基础解析
2020/08/14 Python
我想声明一个指针并为它分配一些空间, 但却不行。这些代码有什么 问题?char *p; *p = malloc(10);
2016/10/06 面试题
为什么会有内存对齐
2016/10/10 面试题
职业规划实施方案
2014/06/10 职场文书
诗词赏析-(浣溪沙)
2019/08/13 职场文书
Spring Cloud Gateway去掉url前缀
2021/07/15 Java/Android
MySQL表类型 存储引擎 的选择
2021/11/11 MySQL