合肥工业大学2021离散数学上机实验六

实验六:最短路径 Dijstra 与 Floyd-Warshal 算法实现

  1. 实验目的和要求

        实验目的:理解掌握常用的单源和多源最短路径算法的基本原理和方法。

        实验要求:

         (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

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值