最近学习了迪克斯特拉算法来求解无向图的最短路径问题,简单来说该算法的核心思路就是通过每一步寻找dist列表中的最小距离的点来更新path列表。废话少说,直接上步骤。
(1)找到“最便宜”的节点(可在最短时间内到达的节点)。
(2)更新该节点的邻居节点的开销。
(3)重复这个过程,直到对图中每个节点都做了。
(4)计算最终路径。
接下来让我们来计算A到E的最短路径
先创建我们所需要的表格
dis是存储A点到每个点的距离,先设为INF
dis
A到其他点 | A | B | C | D | E |
最短距离 | INF | INF | INF | INF | INF |
用一个列表存储每个点上一跳,初始值用-1表示
(一)从A到每个点的距离来更新dis表和上一跳表,A为起始点,其上一跳不变。
dis
A到其他点 | A | B | C | D | E |
最短距离 | 0 | 4 | INF | 2 | INF |
(二)从dis表中发现D的路径最短,选取D来更新dis表和上一跳表,如果dis表中A点到B点,C点,E的距离大于A到D的距离加上D到B点,C点,E点的距离,就更新dis表。
dis
A到其他点 | A | B | C | D | E |
最短距离 | 0 | 3(4-->3) | 3(INF-->3) | 2 | 9(INF-->9) |
(三)重复上述步骤,选取B点来更新dis表和上一跳表,这里B和C的距离一样短,选择其一皆可。
(四)再选择C来更新dis表和上一跳表。
dis
A到其他点 | A | B | C | D | E |
最短距离 | 0 | 3 | 3 | 2 | 6(9-->6) |
(五)最后选取E最终确定dis表和上一跳表
此时已经得到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]