最短路径之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的最小距离设为0
- S := empty set
- Q := set of all vertices
- while 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 = vertices
- self.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)
- return
- self.print_path(parent, parent[j])
- print(j)
- # 找出最小距离的结点
- def min_distance(self, dist, sptSet):
- min_val = sys.maxsize
- min_index = 0
- for v in range(self.V):
- if dist[v] < min_val and not sptSet[v]:
- min_val = dist[v]
- min_index = v
- return min_index
- # 核心算法
- def dijkstra(self, src):
- dist = [sys.maxsize] * self.V
- dist[src] = 0
- sptSet = [False] * self.V
- parent = [-1] * self.V
- for 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] = u
- self.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:
- continue
- dist[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()
最短路径之Dijkstra算法和Floyd-Warshall算法的更多相关文章
- 最短路径—大话Dijkstra算法和Floyd算法
Dijkstra算法 算法描述 1)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , ...
- 最短路径——Dijkstra算法和Floyd算法
Dijkstra算法概述 Dijkstra算法是由荷兰计算机科学家狄克斯特拉(Dijkstra)于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图(无 ...
- 最短路径Dijkstra算法和Floyd算法整理、
转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijks ...
- 【转】最短路径——Dijkstra算法和Floyd算法
[转]最短路径--Dijkstra算法和Floyd算法 标签(空格分隔): 算法 本文是转载,原文在:最短路径-Dijkstra算法和Floyd算法 注意:以下代码 只是描述思路,没有测试过!! Di ...
- 【转载】Dijkstra算法和Floyd算法的正确性证明
说明: 本文仅提供关于两个算法的正确性的证明,不涉及对算法的过程描述和实现细节 本人算法菜鸟一枚,提供的证明仅是自己的思路,不保证正确,仅供参考,若有错误,欢迎拍砖指正 ----------- ...
- Dijkstra算法和Floyd算法的正确性证明
说明: 本文仅提供关于两个算法的正确性的证明,不涉及对算法的过程描述和实现细节 本人算法菜鸟一枚,提供的证明仅是自己的思路,不保证正确,仅供参考,若有错误,欢迎拍砖指正 ------------- ...
- 最短路径—Dijkstra算法和Floyd算法
原文链接:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最后边附有我根据文中Dijkstra算法的描述使用jav ...
- 最短路径—Dijkstra算法和Floyd算法【转】
本文来自博客园的文章:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html Dijkstra算法 1.定义概览 Dijk ...
- 图的最短路径——dijkstra算法和Floyd算法
dijkstra算法 求某一顶点到其它各个顶点的最短路径:已知某一顶点v0,求它顶点到其它顶点的最短路径,该算法按照最短路径递增的顺序产生一点到其余各顶点的所有最短路径. 对于图G={V,{E}};将 ...
随机推荐
- Coursera 机器学习笔记(七)
主要为第九周内容:异常检测.推荐系统 (一)异常检测(DENSITY ESTIMATION) 核密度估计(kernel density estimation)是在概率论中用来估计未知的密度函数,属于非 ...
- asp.net core 教程(七)-异常处理、静态文件
Asp.Net Core-异常处理 Asp.Net Core-异常处理 在这一章,我们将讨论异常和错误处理.当 ASP.NET Core应用程序中发生错误时,您可以以各种不同的方式来处理.让我们来看看 ...
- 补:关于man关于SEE ALSO(参见)中代号与vim下常用命令
1.查阅/etc/issue文件时,使用man issue发现manual中see also出现motd(5), agetty(8), mingetty(8)字样.以及文档行首的issue(5)究竟是 ...
- html <input type="text" />加上readonly后在各种浏览器的差异。
<html> <body> <p>Name:<input type="text" name="email" /> ...
- 各开放平台API接口通用 SDK 前言
最近两年一直在做API接口相关的工作,在平时工作中以及网上看到很多刚接触API接口调用的新人一开始会感到很不适应,包括自己刚开始做API接口调用的相关工作时,也是比较抓狂的,所有写一序列文章把之前的工 ...
- JavaScript面向对象轻松入门之继承(demo by ES5、ES6)
继承是面向对象很重要的一个概念,分为接口继承和实现继承,接口继承即为继承某个对象的方法,实现继承即为继承某个对象的属性.JavvaScript通过原型链来实现接口继承.call()或apply()来实 ...
- JS面向对象一
面向对象分为三大类 封装,继承,多态! 封装就是在一个函数方法中嵌套另外一个函数方法,外层函数方法返回内层函数方法里面的结果,其中内层函数要调用外层函数定义的局部变量 每个函数方法就是一个局部作用域, ...
- iis部署wcf服务过程
一.在iis网站中添加wcf服务,一直添加到web.config目录即可 二.点击基本设置-->连接为-->特定用户.填写登入电脑的用户名和密码. 三.点击身份验证 四.控制面板,设置防火 ...
- 6.javaweb之respose对象
1.respose的生成的outer对象要优先于内置的out对象输出 response.setContentType("text/html;charaset=utf-8");//设 ...
- 一个简单的python选课系统
下面介绍一下自己写的python程序,主要是的知识点为sys.os.json.pickle的模块应用,python程序包的的使用,以及关于类的使用. 下面是我的程序目录: bin是存放一些执行文件co ...