迪杰斯特拉算法是一种贪心算法,先将所有的地点距离默认为无限,然后从起点出发,每次走距离起点最近的点并更新从该"最近的点"到附近所有点的距离,如果之前经历过的某个点从这里出发到那里会更近(比如例子里面的点8,0-1-2-8比0-7-8更近),更换为最近时的距离(将0到8的距离由15改为14),直到终点
因为每次选择最近的,所以到达终点时也是最近的
以此方法求得最短距离
import numpy as np
def Dijkstra(start, end, v, edges, d, get_road=False):
# 由get_road决定是否返回路径
# 出于简便,v中的点从0开始,到len(v-1)结束
# 如果问题变更,从地点1到地点2,要把地名映射成为数字
passed = np.zeros(len(v))
# 该数组记录已经通过的点,比如通过了点0,就把passed[0]改为1
distance = np.full(len(v), float('inf'))
# 默认距离全部改成无限(如果是java等语言没有办法表现为无限,就用一个足够大的final常量来表示)
distance[start] = 0
# 起点距离为0
road = np.full(len(v), -1)
# 这个数组用于记录路径,如果只是需要举例不需要路径,该数组无用
# 若需要路径,该数组记录的是到达某个点为最短距离时,该点的上一个点
# 举例:从起点0到点1最短距离是4,此时1的上一个点是0,则road[1]=0
curr = start
# 从start出发
while curr != end:
# 当到达终点时停止
temp = float('inf')
for i in range(len(distance)):
if (temp > distance[i]) & (passed[i] == 0):
temp = distance[i]
curr = i
passed[curr] = 1
for i in range(len(edges)):
(x, y) = edges[i]
if x == curr:
distance[y] = min(d[i] + distance[curr], distance[y])
if get_road & (distance[y] == d[i] + distance[curr]):
road[y] = curr
elif y == curr:
distance[x] = min(d[i] + distance[curr], distance[x])
if get_road & (distance[x] == d[i] + distance[curr]):
road[x] = curr
print(distance)
if get_road:
print_road(road, start, end)
def print_road(road, start, end):
s = []
curr = end
while curr != start:
s.append(curr)
curr = road[curr]
s.append(curr)
s.reverse()
print(s)
if __name__ == "__main__":
# 测试用例:
V = {0, 1, 2, 3, 4, 5, 6, 7, 8}
E = [(0, 1), (0, 7), (1, 7), (7, 8), (1, 2), (6, 7), (6, 8), (5, 6), (2, 8),
(2, 5), (2, 3), (3, 5), (3, 4), (4, 5)]
D = [4, 8, 11, 7, 8, 1, 6, 2, 2, 4, 7, 14, 9, 10]
# 起点 0, 终点 4
Dijkstra(start=0, end=4, v=V, edges=E, d=D, get_road=True)