最短路径问题
最短路径是图论中一个重要的知识点,在一个有向图中,如何求出两个节点之间的最短路径?上学期学了python,然后期末做了一个旅途咨询系统,这学期刚学了图论,所以将最短路径问题整理了一下。这样一个旅途资询系统(当然旅途咨询系统不是重点)需要解决单源最短路径问题,单源最短路径问题解决后得到的是从源节点到其他节点的最短路径,用到的是Dijkstra算法,但如果是想知道一个节点到其他某一个节点的最短路径,比较好用的就是floyd算法了。
接下来我会分三个步骤讲解这两个算法,如果有理解错的地方,欢迎指正。这三个步骤是:算法思想、算法复杂度和特点以及具体实现。
有关最短路径问题的一篇文章,很多很详细
算法思想
前提:得到一个邻接矩阵,这个矩阵中的元素就是对应边的长度,或者说权重
-
Dijkstra算法
(1)选定一个节点V作为源节点,并用一个dist数组来记录该节点到其他节点的最短路径的距离,再用两个集合visited和T分别表示已经确定了最短路径的终点和其他节点,起初,visited中只有源节点;
(2)在T中选择出一个到源节点路径最短的节点A,并以节点A作为中转节点,然后将A从T移到visited中,接着调整T中节点经过中转节点A到达源节点src的最短路径,调整原则是取dist[end] 与 dist[A][end]+dist[A]的最小值;
(3)再从T中选出一个到源节点路径最短的节点B,然后将B从T移到visited中,并进行(2)中操作,依次类推直到T中没有节点为止,最后得到的是一个数组,dist[end]的值就是src到end的最短路径的距离了.。 -
floyd(弗洛伊德)算法
(1)从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
(2)对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比u到v的路径更短。如果是就更新最短路径。
两种算法的算法复杂度和特点
- 算法复杂度
先简单说一下算法复杂度,算法复杂度分为时间复杂度和空间复杂度,时间复杂度等于所有语句的运行次数之和,通常用时间复杂度的渐进上界来衡量时间复杂度即O(f(n)),空间复杂度指在运行过程中占用了多少存储空间,主要是辅助空间,依旧是O(f(n))来衡量空间复杂度,递归栈就是需要被算入辅助空间。那么这两种算法的算法复杂度如何?
Dijkstra算法的时间复杂度为O(n^2),空间复杂度为:O(n);
floyd(弗洛伊德)算法的时间复杂度为O(n^3), 空间复杂度为O(n^2) - 算法特点:
1、floyd(弗洛伊德)算法时间复杂度比较高,不适合计算大量数据;
2、更为重要的是:dijkstra算法使用的前提是图中路径长度必须大于等于0;但是floyd算法则仅仅要求没有总和小于0的环路就可以了,因此floyd算法应用范围比dijkstra算法要广。;
3、dijkstra算法返回的是一个数组,而floyd直接返回两个节点在图中的最短路径。
实现
- Dijkstra算法(使用的python,这里只有部分代码)
import sys
Max=sys.maxsize
Min=sys.maxsize
src_node=int(input("输入起始节点,节点1输入0,节点2输入1,依次类推")) #src_node=1表示源节点为节点2
dis=weight_matrix[src_node] #weight_matrix代表邻接矩阵,里面的元素是相应边的权重
src_node+=1
u=0
book = [0 for i in range(7)]
for i in range(6):
Min=Max
for j in range(7):
if book[j]==0 and dis[j]<Min:
Min=dis[j]
u=j
book[u]=1 #一旦一个节点做了一次中转节点就为其进行标记
for j in range(7):
if weight_matrix[u][j]<Max and dis[j]>dis[u]+weight_matrix[u][j]:
dis[j]=dis[u]+weight_matrix[u][j]
for i in range(7):
print("节点"+str(src_node)+"到达"+str(i+1)+"节点的最短路径"+str(dis[i]))
- floyd(弗洛伊德)算法
for a in range(7):
for b in range(7):
for c in range(7):
weight_matrix[b][c]=min(weight_matrix[b][c],weight_matrix[b][a]+weight_matrix[a][c])#weight_matrix代表邻接矩阵,里面的元素是相应边的权重
weights1=weight_matrix[2][4]
print("节点3到节点5的最短路径为:",weights1)
weights2=weight_matrix[3][6]
print("节点4到节点7的最短路径为:",weights2)