[总结]最短路径算法
所谓最短路径问题是指:如果从图中某一顶点(源点)到达另一顶点(终点)的路径可能不止一条,如何找到一条路径使得沿此路径上各边的权值总和(称为路径长度)达到最小。
下面我们介绍两种比较常用的求最短路径算法:
Dijkstra(迪杰斯特拉)算法
迪杰斯特拉算法思想是按路径长度递增的次序一步一步并入来求取,是贪心算法的一个应用,用来解决单源点到其余顶点的最短路径问题。另外,要注意D算法是无法解决负权重问题的,所以图的权重必须为正。
首先,我们引入一个辅助向量,它的每个分量表示当前找到的从起始节点到终点节点的最短路径的长度。它的初始态为:若从节点到节点有弧,则为弧上的权值,否则为,显然,长度为的路径就是从出发最短的一条路径,路径为。
那么,下一条长度次短的最短路径是哪一条呢?假设次短路径的终点是,则可想而知,这条路径或者是或者是。它的长度或者是从到的弧上的权值,或者是与从到的权值之和。
一般情况下,假设为已知求得的最短路径的终点集合,则可证明:一条最短路径(设其终点为)或者是弧或者是中间只经过中的顶点而最后到达顶点的路径。这可用反证法来证明,假设此路径上有一个顶点不在中,则说明存在一条终点不在中而长度比此路径短的路径。但是这是不可能的。因为,我们是按路径长度的递增次序来产生个最短路径的,故长度比此路径短的所有路径均已产生,他们的终点必定在集合中,即假设不成立。
因此,Dijkstra算法描述如下:
假设存在,源顶点为,,记录到的最短距离,记录从到的边的权值,即两点之间的距离。
1)从中选择使值最小的顶点,将加入到中;
2)更新与直接相邻顶点的dist值。
3)直到,所有顶点都包含进来了,算法停止。
图使用邻接矩阵存储,python代码如下:
# _*_ encoding:utf-8 _*_
# 辅助信息
# 图中的顶点数
V = 7
# 标记数组:used[v]值为False说明改顶点还没有访问过,在S中,否则在U中!
used = [False for _ in range(V)]
# 距离数组:distance[i]表示从源点s到i的最短距离,distance[s]=0
distance = [float('inf') for _ in range(V)]
# cost[u][v]表示边e=(u,v)的权值,不存在时设为INF
cost = [[float('inf') for _ in range(V)] for _ in range(V)]
def dijkstra(s):
distance[s] = 0
while True:
# v在这里相当于是一个哨兵,对包含起点s做统一处理!
v = -1
# 从未使用过的顶点中选择一个距离最小的顶点
for u in range(V):
if not used[u] and (v == -1 or distance[u] < distance[v]):
v = u
if v == -1:
# 说明所有顶点都维护到S中了!
break
# 将选定的顶点加入到S中, 同时进行距离更新
used[v] = True
# 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。
for u in range(V):
distance[u] = min(distance[u], distance[v] + cost[v][u])
if __name__ == '__main__':
for _ in range(12):
v, u, w = list(map(int, input().split()))
cost[v][u] = w
s = int(input('请输入一个起始点:'))
dijkstra(s)
print(distance)
Floyd(弗洛伊德)算法
Floyd算法是一个经典的动态规划算法。是解决任意两点间的最短路径(称为多源最短路径问题)的一种算法,可以正确处理有向图或无向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包。
从任意节点到任意节点的最短路径不外乎2种可能:1)直接从节点到节点,2)从节点经过若干个节点到节点。所以,我们假设为节点到节点的最短路径的距离,对于每一个节点,我们检查是否成立,如果成立,证明从节点到节点再到节点的路径比节点直接到节点的路径短,我们便设置,这样一来,当我们遍历完所有节点,中记录的便是节点到节点的最短路径的距离。
图使用邻接矩阵存储,python代码如下:
# _*_ encoding:utf-8 _*_
# 辅助信息
# 图中的顶点数
n = 4
# 距离数组:distance[i]表示从源点s到i的最短距离,distance[s]=0
matrix = [[float('inf') for j in range(n)] for i in range(n)]
def floyd(matrix,n):
for i in range(n):
for j in range(n):
for k in range(n):
matrix[j][k] = min(matrix[j][k], matrix[j][i] + matrix[i][k])
return matrix
if __name__ == '__main__':
matrix[0][1] = 3
matrix[1][2] = 1
matrix[2][3] = 1
matrix[1][3] = 4
for i in range(n):
matrix[i][i] = 0
res = floyd(matrix,n)
print(res)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)