迪克斯特拉算法

  • 前言

        最近学习了迪克斯特拉算法来求解无向图的最短路径问题,简单来说该算法的核心思路就是通过每一步寻找dist列表中的最小距离的点来更新path列表。废话少说,直接上步骤。

  • 步骤:

(1)找到“最便宜”的节点(可在最短时间内到达的节点)。

(2)更新该节点的邻居节点的开销。

(3)重复这个过程,直到对图中每个节点都做了。

(4)计算最终路径。

接下来让我们来计算A到E的最短路径

先创建我们所需要的表格

dis是存储A点到每个点的距离,先设为INF

dis
A到其他点ABCDE
最短距离INFINFINFINFINF

用一个列表存储每个点上一跳,初始值用-1表示

上一跳
ABCDE
上一跳-1-1-1-1-1

(一)从A到每个点的距离来更新dis表和上一跳表,A为起始点,其上一跳不变。

dis
A到其他点ABCDE
最短距离04INF2INF
上一跳
ABCDE
上一跳-1A-1A-1

(二)从dis表中发现D的路径最短,选取D来更新dis表和上一跳表,如果dis表中A点到B点,C点,E的距离大于A到D的距离加上D到B点,C点,E点的距离,就更新dis表。

dis
A到其他点ABCDE
最短距离03(4-->3)3(INF-->3)29(INF-->9)
上一跳
ABCDE
上一跳-1DDAD

(三)重复上述步骤,选取B点来更新dis表和上一跳表,这里B和C的距离一样短,选择其一皆可。

dis
A到其他点ABCDE
最短距离03329
上一跳
ABCDE
上一跳-1DDAD

(四)再选择C来更新dis表和上一跳表。

 

dis
A到其他点ABCDE
最短距离03326(9-->6)
上一跳
ABCDE
上一跳-1DDAC

 (五)最后选取E最终确定dis表和上一跳表

dis
A到其他点ABCDE
最短距离03326
上一跳
ABCDE
上一跳-1DDAC

        此时已经得到A点到每个点的最短距离,我们还需要创建一个path表存放路径。先将E点放入path表中,再将E的上一跳C放入path表,再将C的上一跳D放入path表,再将D的上一跳A放入表中,A的上一跳为-1,所以结束。pah={E,C,D,A},因为是倒着放进去的,将path的元素倒置一下就ok了。

代码部分:

def Dijkstra(nenwork, s, d):
    path = []  # 存s-d的最短路径
    n = len(nenwork)
    fmax = float('inf')
    w = [[0 for _ in range(n)] for j in range(n)]

    book = [0 for _ in range(n)]  # 是否已经是最小的标记列表
    dis = [fmax for i in range(n)]  # s到其他节点的最小距离
    midpath = [-1 for i in range(n)]  # 上一跳列表

    for i in range(n):
        for j in range(n):
            if nenwork[i][j] != -1:
                w[i][j] = nenwork[i][j]
            else:
                w[i][j] = fmax
            if i == s - 1 and nenwork[i][j] != -1:  # 直连节点最小距离就是network[i][j]
                dis[j] = nenwork[i][j]
                if j != s - 1:
                    midpath[j] = i + 1

    for i in range(n - 1):
        m = fmax
        for j in range(n):
            if book[j] == 0 and dis[j] < m:
                m = dis[j]
                u = j
        book[u] = 1
        for v in range(n):
            if dis[v] > dis[u] + w[u][v]:
                dis[v] = dis[u] + w[u][v]
                midpath[v] = u + 1  # 上一跳更新
        # print("midpath", midpath)
    j = d - 1
    path.append(d)  # 因为存储的是上一跳,所以先加入目的节点d,最后倒置
    while (midpath[j] != -1):
        path.append(midpath[j])
        j = midpath[j] - 1
    # path.append(s)
    path.reverse()  # 倒置列表
    dic = {"-1": "-1", "1": "A", "2": "B", "3": "C", "4": "D", "5": "E"}
    path1 = [dic[str(e)] for e in path]
    midpath1 = [dic[str(e)] for e in midpath]
    print("dis:", dis)
    print("midpath", midpath1)
    print("path:", path1)
    print("book", book)

if __name__ == "__main__":
    w1 = [[0, 4, -1, 2, -1],
          [4, 0, 4, 1, -1],
          [-1, 4, 0, 1, 3],
          [2, 1, 1, 0, 7],
          [-1, -1, 3, 7, 0]]
    Dijkstra(w1, 1, 5)

最终结果:

path: ['A', 'D', 'C', 'E']
dis: [0, 3, 3, 2, 6]
midpath ['-1', 'D', 'D', 'A', 'C']
book [1, 1, 1, 1, 0]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值