狄克斯特拉(Dijkstra)算法原理详细解释与实现(python)
目录
写在前面
1. 简介
2. 原理
2.1 找出最便宜的节点
2.2 计算前往该节点的各个邻居的开销
2.3 重复上面的步骤
实现
总结
写在前面
本文原理摘自《算法图解》这本书。
其实Dijkstra算法是广度优先搜索基础上扩展来的。无非是广度优先搜索按照层次关系,每一层级每一个节点都进行重复操作,直到找到合适的解法,接着进入下一层级。
Dijkstra算法是对每一层级每一个节点找到其符合条件解法,然后进行更新,接着进行下一层级。
1. 简介
广度优先算法可以找出段数最少的路径,但是对于路径上带权重的图,想要找出最快的路径,则需要使用狄克斯特拉算法。
2. 原理
为了说明狄克斯特拉算法的原理,使用换钢琴的的例子来做说明.
假设Rama想拿自己的乐谱换架钢琴:
Alex说:“这是我最喜欢的乐队Destroyer的海报,我愿意拿它换你的乐谱。
如果你再加5美元,还可拿乐谱换我这张稀有的Rick Astley黑胶唱片。”
Amy说:“哇,我听说这张黑胶唱片里有首非常好听的歌曲,我愿意拿我的吉他或架子鼓换这张海报或黑胶唱片。
Beethoven惊呼:“我一直想要吉他,我愿意拿我的钢琴换Amy的吉他或架子鼓。”
商品兑换的关系如下:
现在需要确定,Rama如何才能以最少的钱换到他想要的钢琴。
狄克斯特拉算法解决问题的思路主要包括以下四步:
找出最便宜的节点,即可用最便宜的价格可前往的节点。
对于该节点的邻居,检查是否有前往它们的更短路径,如果有,就更新其开销。
重复这个过程,直到对图中的每个节点都这样做了。
计算最终路径
下面结合狄克斯特拉的算法步骤,对该问题进行推算。
2.1 找出最便宜的节点
对于乐谱而言,可以直接兑换唱片和海报,所需的费用分别为5和0.
为了观察的算法过程中数据的变化情况,使用一个表格来计算兑换的开销以及父节点的情况,对于目前开销的未知的节点用无穷大来表示,经过该步骤后,数据的情况如下:
父节点 | 节点 | 成本 |
---|---|---|
乐谱 | 唱片 | 5 |
乐谱 | 海报 | 0 |
– | 吉他 | ∞ |
– | 架子鼓 | ∞ |
– | 钢琴 | ∞ |
2.2 计算前往该节点的各个邻居的开销
通过步骤1的处理,得知从乐谱->海波的开销是最小的。此时计算从海报到达各邻居节点的开销,如果邻居节点的开销变少了,则更新其开销和父节点。最终的结果如下:
父节点 | 节点 | 成本 |
---|---|---|
乐谱 | 唱片 | 5 |
乐谱 | 海报 | 0 |
海报 | 吉他 | 30 |
海报 | 架子鼓 | 35 |
– | 钢琴 | ∞ |
2.3 重复上面的步骤
接下来还没有被遍历的节点中,最便宜的兑换商品为唱片,此时计算从唱片到达各邻居节点的开销,通过计算,从唱片到达吉他只需20,从唱片到达架子鼓只需25,因此需要更新结果表中吉他和架子鼓的父节点以及成本,最终结果如下:
父节点 | 节点 | 成本 |
---|---|---|
乐谱 | 唱片 | 5 |
乐谱 | 海报 | 0 |
唱片 | 吉他 | 20 |
唱片 | 架子鼓 | 25 |
– | 钢琴 | ∞ |
接下来最便宜的节点是吉他,从吉他这个路径走,到钢琴的价格为40.接z最后是架子鼓,从架子鼓这个路径走,到钢琴的价格为35. 于是最终结果如下:
父节点 | 节点 | 成本 |
---|---|---|
乐谱 | 唱片 | 5 |
乐谱 | 海报 | 0 |
唱片 | 吉他 | 20 |
唱片 | 架子鼓 | 25 |
架子鼓 | 钢琴 | 35 |
通过上述表格反推,花费最小的兑换路径为:乐谱–>唱片–>架子鼓–>钢琴,需要花费35.
实现
代码的实现中,需要维护三个散列表:
graph:用来描述顶点与边的关系,为了简单演示,可以直接使用字典的形式表示顶点与边。
costs:用来记录途径顶点的开销
parents:用来记录各顶点的父顶点情况
python代码如下:
# -*- coding:utf-8 -*-
# @Author:sunaihua
'''
使用Dijkstra算法得到带权图的最短路径
'''#graph 结构
graph={}
graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2
graph["a"] = {}
graph["a"]["fin"] = 1
graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["fin"] = 5
graph["fin"] = {}# 成本数据
infinity = float("inf")
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["fin"] = infinity
# parent数据
parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["fin"] = None
# 已经处理过的节点
processed = []def find_lowest_cost_node(costs):lowest_cost = float("inf")lowest_cost_node = Nonefor node in costs:cost = costs[node]if cost < lowest_cost and node not in processed:lowest_cost = costlowest_cost_node = nodereturn lowest_cost_nodedef dijkstra():node = find_lowest_cost_node(costs)while node is not None:cost = costs[node]neighbors = graph[node]for n in neighbors.keys():new_cost = cost + neighbors[n]if costs[n] > new_cost:costs[n] = new_costparents[n] = nodeprocessed.append(node)node = find_lowest_cost_node(costs)# 更具parents中的fin,向前反推,就可以得到最终的路径print parentsif __name__ == '__main__':dijkstra()
总结
- 广度优先搜索用于在非加权图中查找最短路径。
- 狄克斯特拉算法用于在加权图中查找最短路径。
- 仅当权重为正时狄克斯特拉算法才管用。
- 如果图中包含负权边,请使用贝尔曼-福德算法。
关于最短路径求解:
最短路径的常用解法有迪杰克斯特拉算法Dijkstra Algorithm, 弗洛伊德算法Floyd-Warshall Algorithm, 和贝尔曼福特算法Bellman-Ford Algorithm,其中,Floyd算法是多源最短路径,即求任意点到任意点到最短路径,而Dijkstra算法和Bellman-Ford算法是单源最短路径,即单个点到任意点到最短路径。
狄克斯特拉(Dijkstra)算法原理详细解释与实现(python)相关推荐
- 狄克斯特拉(Dijkstra)算法详解
1.前言 最近在看<算法图解>,其中第七章狄克斯特拉算法个人感觉并没有讲的清楚,比如看完7.1节给人的感觉是狄克斯特拉算法会遍历图中的每一条边,后续狄克斯特拉不适用负权边的说法就站不住脚了 ...
- 数据结构_图_最短路径_狄杰斯特拉(Dijkstra)算法
此算法没有采用<数据结构C语言版>中的存储结构,而是采用邻接表的方法存储图,经过改进,还能输出最短路径. "Dijkstra.h" #include<iostre ...
- 算法快学笔记(十三):狄克斯特拉(Dijkstra)算法原理与实现
1. 简介 广度优先算法可以找出段数最少的路径,但是对于路径上带权重的图,想要找出最快的路径,则需要使用狄克斯特拉算法. 2. 原理 为了说明狄克斯特拉算法的原理,使用换钢琴的的例子来做说明. 假设R ...
- Python查找算法之狄克斯特拉算法
目录 简介 加权图 非加权图 思路 实例 代码步骤 代码示例 运行结果 简介 狄克斯特拉算法解决了耗时最短(总权重最小)问题狄克斯特拉算法适用于加权图,并且图为有向无环图(DAG),而且权重不能为负数 ...
- 狄克斯特拉算法(Dijkstra)详细解释
文章目录 算法用途(目的) 算法思想与本质 图文解释 代码解析 算法用途(目的) 狄克斯特拉算法的用途或者说是目的是计算单源最短路径.单源最短路径的意思是从一个点出发到另外一个点最为的容易.举个例子解 ...
- 最短路径--狄克斯特拉(Dijkstra)算法
最短路径 从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径 Dijkstra算法 算法来源 Dijkstra算法是由一个叫Dijkstra的荷兰人发明的,故称此算法 ...
- 最短路径--Dijkstra(狄克斯特拉)算法
最短路径 路径的概念: 在一个无权的图中,若从一顶点到另一顶点存在着一条路径,则称该路径长度为该路径上所经过的边的数目,它等于该路径上的顶点数减 1 . 由于从一顶点到另一顶 ...
- 狄克斯特拉(Dijkstra)算法求一个顶点到其余各个顶点的最短路径
不要自卑,去提升实力 互联网行业谁技术牛谁是爹 如果文章可以带给你能量,那是最好的事!请相信自己 加油o~ 1.狄克斯特拉(Dijkstra)算法 采用狄克斯特拉(Dijkstra)算法可以求带权图( ...
- Dijkstra(狄克斯特拉) 算法
文章目录 加权图 算法步骤 算法实现: 适用场景: 负权边 该算法是一种计算有向无环图最短路径的算法. 加权图 其中每个数字表示时间.要计算非加权图中的最短路径,可使用广度优先搜索.要计算加权图中的最 ...
最新文章
- 什么BRIEF算法?BRIEF算法详解
- int 和integer的区别
- Access restriction: The type BASE64Encoder is not accessible due to restrict
- Logistic Regression:最基础的神经网络
- 安卓自定义View进阶-分类与流程
- C++函数模板5分钟入门
- PHP匿名在线聊天室系统源码 自适应PC+WAP端
- Vue-组件之间的数据共享
- Android注解编程的第一步---模仿ButterKnife的ViewBinder机制
- kernel or user oops信息定位步骤
- Java小游戏之飞翔的小鸟
- 算法设计与分析基础——假币问题(三分法)
- Premiere 视频基本调色
- 想学python网课哪个好-推荐书单(网课)-人生/编程/Python/机器学习-191本
- php+laravel 扫码二维码签到
- 重启Oracle数据库的操作步骤
- Designing Data-Intensive Applications翻译
- window内置对象和js内置对象与方法
- 陈老师排课12A(6天上4下4)小学专用版使用方法
- 计算机网络的安全性在哪里,计算机网络面临的安全性威胁可分为哪两类分别包含..._安全工程师_帮考网...