Floyd最短路径算法
使用带权图的邻接矩阵方法表示图并且不能有负周期。如:
g = [
[0,1,float('inf'),1,5],
[9,0,3,2,float('inf')],
[float('inf'),float('inf'),0,4,float('inf')],
[float('inf'),float('inf'),2,0,3],
[3,float('inf'),float('inf'),float('inf'),0]
]
其中g[i][j]表示i到j边的权重。
Floyd方法指的是如果要从N个结点中找一条i,j两点之间的最短路径,首先对比两点之间的距离与经过剩余N-2个结点中任意一个结点k1的距离,并取短的距离为g[i][j]:
g[i][j]=min(g[i][j], g[i][k1] + g[k1][j])
即从i到j中途经过点k1的距离与g[i][j]进行对比,选取较小的值作为中途经过一个点时的最短路径。此处的i,j代表任意两点,将图中任意两点做以上步骤后可以得到一个新的g,这个g的g[i][j]意义为经过一个点后i到j的最短路径。
在经过第一个点k1的基础上,经过两个点时两点间最短路径长为:
g[i][j] = min(g[i][j], g[i][k2] + g[k2][j])
因此我们得到一般性规律,找图中两点i,j的最短路径时,可先考虑两点加任一点k1,找出图中任意两点经过一个点的最短路径并生成经过一个点时的图的最短路径矩阵。之后计算经过两个点时的情况,由于在经过一个点的最短路径矩阵的基础上计算经过两点的最短路径,可以直接重复第一步的过程。
Python代码如下:
graph = [
[0,1,float('inf'),1,5],
[9,0,3,2,float('inf')],
[float('inf'),float('inf'),0,4,float('inf')],
[float('inf'),float('inf'),2,0,3],
[3,float('inf'),float('inf'),float('inf'),0]
]
n = len(graph)
for k in range(n): // 经过的每个点
for i in range(n):
for j in range(n):
if graph[i][j] > graph[i][k] + graph[k][j]: // 判断点i,j经过第0到第k-1个点时的最短路径
graph[i][j] = graph[i][k] + graph[k][j]
print(graph)
C++代码如下,代码中如果两个点无路时用1000近似表示无穷:
#include <iostream>
using namespace std;
void Floyd(int a[][5],int n){
for(int k = 0; k < n; k++){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(a[i][j] > a[i][k] + a[k][j]){
a[i][j] = a[i][k] + a[k][j];
}
}
}
}
}
int main(){
int graph[5][5] = {
{0, 1, 1000, 1, 5},
{9, 0, 3, 2, 1000},
{1000, 1000, 0, 4, 1000},
{1000, 1000, 2, 0, 3},
{3, 1000, 1000, 1000, 0}
};
Floyd(graph, 5);
for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){
cout << graph[i][j] << ' ';
}
cout << endl;
}
}
其中核心代码只有五行三重循环,时间复杂度为O(n³),n为输入图的边长。如果数据量很小或对时间要求不高时,可以使用此简单方法生成最短路径。
此算法还可得出从i到j两点间经过的下标最大的点,设其为p[i][j],为0时说明两点间的直接距离即为最短路径:
Python代码如下:
graph = [
[0,1,float('inf'),1,5],
[9,0,3,2,float('inf')],
[float('inf'),float('inf'),0,4,float('inf')],
[float('inf'),float('inf'),2,0,3],
[3,float('inf'),float('inf'),float('inf'),0]
]
n = len(graph)
p = []
for i in range(n):
p.append([])
for j in range(n):
p[i].append(0)
for k in range(n):
for i in range(n):
for j in range(n):
if graph[i][j] > graph[i][k] + graph[k][j]:
p[i][j] = k
graph[i][j] = graph[i][k] + graph[k][j]
print(p)
print(graph)
找出两点间最短路径经过的点(用到数组p):
def PassedNodes(q,r):
if p[q][r] != 0:
PassedNodes(q,p[q][r])
print('v{}'.format(p[q][r]),end=' ')
PassedNodes(p[q][r],r)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)