最短路:Floyd算法(Python实现)

Floyd-Warshall算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权(但不可存在负权回路)的最短路径问题。Floyd算法的根本原理是动态规划
在这里插入图片描述

算法描述

开始:对于每一对顶点 v v v v ′ v' v,从 v v v v ′ v' v图中不经过任何其他顶点,如果 v v v v ′ v' v存在边,那么长度就是该边的权,如果没边就设长度为无穷大

k = 0 k=0 k=0:即对于每一对顶点v和v’,途径顶点的下标不大于 k k k,实际上这里只能经过 v 0 v_0 v0,该路径可分为两段,即 < v , v 0 > <v,v_0> <v,v0> < v 0 , v ′ > <v_0,v'> <v0,v>,这一长度就是两段路径的长度之和,比较这一新路径和之前的路径 < v , v ′ > <v,v'> <v,v>,就可以确定 v v v v ′ v' v途经下标不大于k的最短路径

k = 1 k=1 k=1:同理,该路径可拆成 < v , … , v 1 > <v,… ,v_1> <v,,v1> < v 1 , … , v ′ > <v_1,…,v'> <v1,,v>两段,这两段的长度在 k = 0 k=0 k=0的时候就确定了,再比较新路径和前面已知的路径 < v , v ′ > <v,v'> <v,v>就可以确定途经下标不大于 k k k的最短路径,此时 k = 1 k=1 k=1
重复以上步骤,直到 k = n − 1 k=n-1 k=n1为止,此时已经确定了从 v v v v ′ v' v所有可能的最短路径

代码实现

在这里插入图片描述
对于上图,可以用邻接字典表表示,然后Floyd算法需要将其转为邻接矩阵形式:

graph = {'A': [(7, 'A', 'B'), (5, 'A', 'D')], 
         'B': [(7, 'B', 'A'), (8, 'B', 'C'), (9, 'B', 'D'), (7, 'B', 'E')], 
         'C': [(8, 'C', 'B'), (5, 'C', 'E')],
         'D': [(5, 'D', 'A'), (9, 'D', 'B'), (15, 'D', 'E'), (6, 'D', 'F')], 
         'E': [(7, 'E', 'B'), (5, 'E', 'C'), (15, 'E', 'D'), (8, 'E', 'F'), (9, 'E', 'G')], 
         'F': [(6, 'F', 'D'), (8, 'F', 'E'), (11, 'F', 'G')],
         'G': [(9, 'G', 'E'), (11, 'G', 'F')]
        }
def graph2adjacent_matrix(graph):
    vnum = len(graph)
    dict = {'A':0,'B':1,'C':2,'D':3,'E':4,'F':5,'G':6}
    adjacent_matrix = [[0 if row==col else float('inf') for col in range(vnum)] for row in range(vnum)]
    vertices = graph.keys()
    for vertex in vertices:
        for edge in graph[vertex]:
            w,u,v = edge
            adjacent_matrix[dict.get(u)][dict.get(v)]=w
    return adjacent_matrix

然后运用floyd算法:

def floyd(adjacent_matrix):
    vnum = len(adjacent_matrix)
    a = [[adjacent_matrix[row][col] for col in range(vnum)] for row in range(vnum)]
    nvertex = [[-1 if adjacent_matrix[row][col]==float('inf') else col for col in range(vnum)] for row in range(vnum)]
    # print(adjacent_matrix)
    for k in range(vnum):
        for i in range(vnum):
            for j in range(vnum):
                if a[i][j]>a[i][k]+a[k][j]:
                    a[i][j]=a[i][k]+a[k][j] 
                    nvertex[i][j] = nvertex[i][k]
    return nvertex, a

adjacent_matrix = graph2adjacent_matrix(graph)
nvertex, a = floyd(adjacent_matrix)
### 打印原邻接矩阵 ###
for i in range(len(adjacent_matrix)):
    for j in range(len(adjacent_matrix[0])):
        print(adjacent_matrix[i][j],end="\t")
    print()#打印一行后换行
### 打印经过的顶点 ###
print()
for i in range(len(nvertex)):
    for j in range(len(nvertex[0])):
        print(nvertex[i][j],end="\t")
    print()#打印一行后换行
### 打印彼此之间的最短距离 ###
print()
for i in range(len(a)):
    for j in range(len(a[0])):
        print(a[i][j],end="\t")
    print()#打印一行后换行

其中a表示最短距离矩阵,即a[0][6]表示点AG之间的最短距离,而nvertex矩阵中的nvertex[i][j]表示 v i v_i vi v j v_j vj之间最短路中 v i v_i vi的后继顶点,根据该矩阵可以之后任意最短路中间经过的顶点,如下给出该矩阵:
在这里插入图片描述
我们找出A到G最短路中间经过的顶点,A对应0,G对应6,我们找到nvertex[0][6]=3,也就是A到G的最短路A的后继是D,即A->D->…->G,我们在找D和G,即nvertex[3][6]=5,即D的后继是F,然后找nvertex[5][6]=6,F的后继是G,最后A到G的最短路就是A->D->F->G。

最短路算法Python中有多种实现方式,其中一种是Dijkstra算法。以下是一个用Python实现的Dijkstra算法的示例代码: ```python def dijkstra(graph, start): INF = float('inf') dist = [INF * len(graph) # 源点到其他顶点的距离 visited = [False * len(graph) # 是否已经纳入顶点集合 path = [start * len(graph) # 路径 count = [0 * len(graph) # 统计最短路径数量 dist[start = 0 count[start = 1 while True: u = -1 min_dist = INF for i in range(len(graph)): if not visited[i and dist[i < min_dist: u = i min_dist = dist[i] if u == -1: return dist visited[u = True for v in range(len(graph)): if not visited[v and graph[u][v != INF: if dist[u + graph[u][v < dist[v]: dist[v = dist[u + graph[u][v] path[v = u count[v = count[u] elif dist[u + graph[u][v == dist[v and count[u > count[v]: count[v = count[u] path[v = u ``` 这段代码实现了Dijkstra算法,通过传入一个图(graph)和起始顶点(start),计算出从起始顶点到其他顶点的最短路径(dist),并返回该最短路径数组。 请注意,这只是Dijkstra算法的一种实现方式,还有其他算法,如Floyd算法等。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python实现dijkstra最短路算法](https://download.csdn.net/download/weixin_38676851/12865010)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [最短路算法 算法 python实现](https://blog.csdn.net/weixin_43792889/article/details/115432053)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值