最短路径之Dijkstra算法和Floyd-Warshall算法
最短路径算法
最短路径算法通常用在寻找图中任意两个结点之间的最短路径或者是求全局最短路径,像是包括Dijkstra、A*、Bellman-Ford、SPFA(Bellman-Ford的改进版本)、Floyd-Warshall、Johnson、BFS等等,这里要集中介绍Dijkstra
和Floyd
,前者用来处理任意两个结点之间的最短路径,后者处理图中所有的最短路径。
Dijkstra算法
理解
其思想为,我们首先纪录下每个点到原点的距离,这个距离会在每一轮遍历的过程中刷新。每一个结点到原点的最短路径是其前驱结点到原点的最短路径加上前驱结点到当前结点的路径和。
我们以下面这幅图片为例,假定起始结点为1,求该结点到其余各个结点的最短路径。
执行步骤为:
步骤 | 描述 | 前驱结点 |
---|---|---|
1 | 将当前结点到其它结点的路径都初始化为无穷大 | 无 |
2 | 依次计算每个结点的路径长度,此时可以获得结点1到其它的结点2、3、4、5、6的路径长度为[7, 9, ∞,∞,14]`,取其中最小的值7,结点2作为前驱结点 | 无 |
3 | 此时通过结点2可以到达结点4和5,并且其路径等于起始结点到前驱结点的路径加上前驱结点到目标结点的路径长度,因此此时结点1到其它结点3、4、5、6的路径长度为[17, 22, ∞, ∞],此时将现在的路径长度和之前的路径长度进行比较,取对应的较小值,得到最短距离[9, 22, ∞, 14],取其最小值9,结点3更新成前驱结点 | 2 |
4 | 同样的道理,此时结点1到其它的结点4、5、6的路径长度为[20, ∞, 11],和之前的路径长度进行比较,得到最短距离[20, ∞, 11],取最小值11,结点6作为前驱结点 | 3 |
5 | 同样的道理,得到结点1到其它的结点4, 5的路径长度为[20, 20],和之前对比,最短距离更新成[20,20] | 6 |
6 | 因为此时剩下了两个相等路径长度的结点,取任意一个结点,结果都是一样的,所以取哪个都可以 |
其伪函数如下:
function Dijkstra(G, w, s)for each vertex v in V[G] # 初始化d[v] := infinity # 將各點的已知最短距離先設成無窮大previous[v] := undefined # 各点的已知最短路径上的前趋都未知d[s] := 0 # 因为出发点到出发点间不需移动任何距离,所以可以直接将s到s的最小距离设为0S := empty setQ := set of all verticeswhile Q is not an empty set # Dijkstra演算法主體u := Extract_Min(Q)S.append(u)for each edge outgoing from u as (u,v)if d[v] > d[u] + w(u,v) # 拓展边(u,v)。w(u,v)为从u到v的路径长度。d[v] := d[u] + w(u,v) # 更新路径长度到更小的那个和值。previous[v] := u # 紀錄前趨頂點
其中的Extract_Min为提取最小值。
实现
import sys class Graph():def __init__(self, vertices):self.V = verticesself.graph = [[0 for _ in range(self.V)] for _ in range(self.V)]# 打印距离def print_distance(self, dist, parent):for node in range(self.V):print('distance')print(node, dist[node])print('path')self.print_path(parent, node)print('---------')# 打印路径def print_path(self, parent, j):if parent[j] == -1:print(j)returnself.print_path(parent, parent[j])print(j)# 找出最小距离的结点def min_distance(self, dist, sptSet):min_val = sys.maxsizemin_index = 0for v in range(self.V):if dist[v] < min_val and not sptSet[v]:min_val = dist[v]min_index = vreturn min_index# 核心算法def dijkstra(self, src):dist = [sys.maxsize] * self.Vdist[src] = 0sptSet = [False] * self.Vparent = [-1] * self.Vfor count in range(self.V):# 找出前驱结点u = self.min_distance(dist, sptSet)sptSet[u] = True# 如果某个节点的路径大于经过前驱结点的路径,则更新结果成经过前驱结点的路径for v in range(self.V):if self.graph[u][v] > 0 and not sptSet[v] and dist[v] > dist[u] + self.graph[u][v]:dist[v] = dist[u] + self.graph[u][v]parent[v] = uself.print_distance(dist, parent) g = Graph(8) g.graph = [[0, 0, 7, 7, 2, 0, 0, 0],[0, 0, 3, 8, 0, 0, 8, 0],[7, 3, 0, 0, 0, 7, 0, 0],[7, 8, 0, 0, 0, 0, 0, 0],[2, 0, 0, 0, 0, 0, 0, 8],[0, 0, 7, 0, 0, 0, 8, 0],[0, 8, 0, 0, 0, 8, 0, 6],[0, 0, 0, 0, 8, 0, 6, 0]] g.dijkstra(0)
Floyd
理解
其原理为:假定存在某个结点k在结点i和结点j之间,如果i和j之间的路径长度大于经过k到,则将其距离更新成经过结点k的路径长度。因此在实现中使用三个循环即可,但是要注意循环的顺序,最外层是结点k的遍历,这样可以避免i和j的遍历过早的把最短路径给定下来。
结果为:
实现
import copy INF = 1e9 class Graph():def __init__(self, graph):self.V = len(graph)self.graph = graph# 打印距离def print_distance(self, dist):for i in range(self.V):for j in range(self.V):print('%5s' % (dist[i][j] if dist[i][j] != INF else 'INF'), end='')print('')# 核心算法def floydwarshall(self):dist = copy.deepcopy(self.graph)for k in range(self.V):for i in range(self.V):for j in range(self.V):# 不考虑自己指向自己的情况if i == j:continuedist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])self.print_distance(dist) g = Graph([[INF, INF, 1, INF, INF, INF, INF, INF],[INF, INF, 2, 8, INF, 5, INF, INF],[9, INF, INF, INF, 2, INF, INF, INF],[INF, INF, INF, INF, INF, 2, INF, INF],[INF, INF, INF, INF, INF, INF, INF, 9],[INF, INF, INF, INF, INF, INF, INF, INF],[INF, INF, INF, INF, 1, INF, INF, INF],[INF, INF, INF, INF, INF, 7, 7, INF]]) g.floydwarshall()
转载于:https://www.cnblogs.com/George1994/p/7237473.html
最短路径之Dijkstra算法和Floyd-Warshall算法相关推荐
- 最短路径(Dijkstra算法和Floyd算法)
最短路径 在图中,不可避免要解决的一个问题就是计算两点之间的最短路径,对于图结构来说,两个点之间不一定只有一条路径,那么如何才能找出最短的那一条就是图中最短路径问题.最短路径问题在实际生活中应用十 ...
- 最短路径:Dijkstra算法和Floyd算法
一.Dijkstra算法(单个顶点到其他顶点的最短距离) 定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层 ...
- 最短路径Dijkstra算法和Floyd算法整理、
转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径-Dijkstra算法和Floyd算法 Dijks ...
- 【Java数据结构与算法】第二十章 Dijkstra算法和Floyd算法
第二十章 Dijkstra算法和Floyd算法 文章目录 第二十章 Dijkstra算法和Floyd算法 一.Dijkstra算法 1.介绍 2.代码实现 二.Floyd算法 1.介绍 2.代码实现 ...
- Dijkstra算法和Floyd算法超详解以及区别
鉴于之前我看到过非常好的博客,如果自己总结的话,大多也是按照别的博主的思路来解释,所以就直接推荐给大家这些优秀的博客: Dijkstra:最短路径dijkstra算法精品代码(超详解) Floyd:F ...
- 最短路径—Dijkstra算法和Floyd算法
Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Di ...
- Dijkstra算法和Floyd算法详解(MATLAB代码)
一.Dijkstra算法 1.算法简介 Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它应用了贪心算法模式,是目前公认的最好的求解最短路径的方法.算法解决的是有 ...
- Dijkstra算法和Floyd算法对比分析
转载:http://blog.csdn.net/liuyanling_cs/article/details/56330652 首先,Dijkstra算法与Floyd算法都是广度优先搜索的算法.都可以用 ...
- dijkstra算法和floyd算法(C语言)
dijkstra算法: /* 邻接表存储 - 无权图的单源最短路算法 *//* dist[]和path[]全部初始化为-1 */ void Unweighted ( LGraph Graph, int ...
最新文章
- tinybert华为
- Linux下getsockopt/setsockopt 函数说明
- java去掉mongodb日志_如何禁用mongoDB java驱动程序日志记录?
- React 项目--设置根目录(8)
- Python-time
- 三对角线性方程组的追赶法
- Mysql 8 group replication组复制集群单主配置图解
- 华为云MVP付健权:从机械工程师到AI开发者的华丽转身
- Golang Http Server源码阅读
- Python出现AttributeError: module ‘tkinter‘ has no attribute ‘messagebox‘,已解决
- 测试一软件测试基础知识总结
- 维护建议--数据库备份
- 正则表达式匹配连续相同字符
- python 简单的绘图
- 花花省V5淘宝客APP源码无加密社交电商自营商城系统带抖音接口
- 数据库“新增字段、删除字段、修改字段“
- 【CF633H】Fibonacci-ish II(权值线段树)(莫队)
- 清华学霸尹成Python教程
- 基于C++的钻石金字塔问题算法设计
- OpenCV-Python (官方)中文教程(部分一)
热门文章
- java 中文乱码过滤器_JAVA中文乱码过滤器(用java过滤器解决中文乱码)V0422 整理版...
- 人类赋予人工智能伦理,生物进化方向的突破是关键【刘锋博士南科大发言】
- linux启动找不到内核,linux – PXE启动 – 在TFTP服务器上找不到内核
- kafka创建topic_Kafka系列第三篇!10 分钟学会如何在 Spring Boot 程序中使用 Kafka 作为消息队列?...
- ms sql server 多条件模糊查找
- android shape 绘制气泡图,气泡图-自定义 shape
- mysql union 别名报错_MySQL中UNION和UNION ALL的使用
- Arcgis Javascript那些事儿(四)--feature access服务编辑feature本质
- SQL那些事儿(一)
- esri-leaflet入门教程(5)- 动态绘制图形