实验六:最短路径 Dijstra 与 Floyd-Warshal 算法实现
- 实验目的和要求
实验目的:理解掌握常用的单源和多源最短路径算法的基本原理和方法。
实验要求:
(1).借助已有平台基于 Dijkstra 算法求解最短路径,要求图形化显 示并文本输出相关路径。
(2).借助已有平台基于 Floyd-Warshall 算法求解最短路径,要求图 形化显示并文本输出相关路径。
2. 实验环境和工具
开发环境:PyCharm
3. 实验结果
3.1 程序流程图
①Dijstra
②Floyd-Warshal
3.2 程序代码(仅供参考,水平有限,有错请指出)
①Dijstra
G = {
1: {1: 0, 2: 4, 3: 8},
2: {1: 4, 2: 0, 3: 11, 4: 8},
3: {1: 8, 3: 0, 5: 1},
4: {2: 8, 4: 0, 5: 8, 6: 7, 7: 4},
5: {3: 1, 4: 8, 5: 0, 7: 2},
6: {4: 7, 6: 0, 7: 14, 8: 9},
7: {4: 4, 5: 2, 6: 14, 7: 0, 8: 10},
8: {6: 9, 7: 10, 8: 0}
}
def Dijkstra(G, v0, INF=999): # 999表示该结点到起始点的距离还没有一个确切的值
dis = dict((i, INF) for i in G.keys()) # 初始化一个距离表,这个表记录着起始结点v0到图中各个点的距离(为inf)
current = v0 # 一开始,当前点设置为起始点v0
dis[v0] = 0 # 初始点到自己的距离自然为0
visited = [] # 用来记录已经遍历过的结点,当把所有的结点都存入的时候,算法结束
###
path = dict((i, []) for i in G.keys()) # 初始化一个路径表,这个表记录着起始结点到途中各个点的最短路径
path[v0] = str(v0) # 初始点到自己的路径自然为自己
###
while len(G) > len(visited): # 图的结点还没被遍历完时执行循环以继续遍历
visited.append(current) # 当前点正在被遍历,所以把当前点放入visited表中
for k in G[current]: # 遍历当前点的所有相邻点
if dis[current] + G[current][k] < dis[k]: # 如果(起始点到当前点的距离+当前点到相邻点k的距离)小于(起始点到当前点的相邻点k的距离)
dis[k] = dis[current] + G[current][k] # 则(起始点到当前点的相邻点k的距离)更新为(起始点到当前点的距离+当前点到相邻点k的距离)
seq = (path[current], str(k))# 更新路径
sym = '-'
path[k] = sym.join(seq) # 起始点到(当前点的相邻点k)的最短路径,以'-'来连接seq中的两个字符串
# 接着来选下一个当前点(current)
# 从剩下未遍历的点中,选取与当前点的距离最小的那个点作为下一个当前点
new = INF
for node in dis.keys():
if node in visited:
continue
if dis[node] < new:
new = dis[node]
current = node
return dis, path
v0=1
dis, path = Dijkstra(G, v0)
print("%s 到各个结点的最短距离:"%(str(v0)),dis)
print("最短路径为:",path)
②Floyd-Warshal
import sys as s
s.setrecursionlimit(100000000)
# 弗洛伊德算法
def floyd():
n = len(graph)
for k in range(n):
for i in range(n):
for j in range(n):
if graph[i][k] + graph[k][j] < graph[i][j]:
graph[i][j] = graph[i][k] + graph[k][j]#更新距离
parents[i][j] = parents[k][j] # 更新父结点
# 打印路径
def print_path(i, j):
if i != j:
print_path(i, parents[i][j]-1)
print(j+1, end='->')
datas = [
[1, 2, 9],[1, 3, 3],
[2, 1, 9],[2, 4, 4],
[3, 1, 3],[3, 2, 2],[3, 4, 8],[3, 5, 2],[3, 6, 7],
[4, 2, 1],[4, 3, 8],[4, 7, 5],[4, 10, 9],
[5, 3, 2],[5, 6, 8],[5, 7, 6],[5, 8, 4],
[6, 3, 7],[6, 5, 9],[6, 8, 2],
[7, 4, 5],[7, 5, 6],[7, 8, 1],[7, 9, 2],[7, 10, 3],
[8, 5, 4],[8, 6, 1],[8, 7, 3],[8, 9, 6],
[9, 7, 2],[9, 8, 6],[9, 10, 5],
[10, 7, 3],[10, 9, 5],
]
n = 10
# 定义无穷大
inf = 9999999999
# 初始图的权值数据
graph = [[(lambda x: 0 if x[0] == x[1] else inf)([i, j]) for j in range(n)] for i in range(n)]
parents = [[i+1] * n for i in range(n)] # 关键地方,i-->j 的父结点初始化都为i
for u, v, c in datas:
graph[u-1][v-1] = c # 因为是有向图,边权只赋给graph[u][v]
#graph[v][u] = c # 如果是无向图,要加上这条。
floyd()
'''
print('Weight:')
for row in graph:
for e in row:
print('∞' if e == inf else e, end='\t')
print()
print()
print('Path:')
'''
for i in range(n):
for j in range(n):
print('Path({}->{}): '.format(i+1, j+1), end='')
print_path(i, j)
print(' Weight:', graph[i][j])
3.3 运行结果
其他作业:
合肥工业大学2021离散数学上机实验一https://blog.csdn.net/qq_52791068/article/details/122654230合肥工业大学2021离散数学上机实验四https://blog.csdn.net/qq_52791068/article/details/122656507
合肥工业大学2021离散数学上机实验八https://mp.csdn.net/mp_blog/creation/editor/122663212