迪杰斯特拉算法的思想就是从源节点开始处理,每次从未处理的节点中选取与已经处理节点距离最短的节点作为下一个待处理节点。选取完待处理节点之后,更新从源点经由待处理节点到其邻接节点的距离,然后选取更新的距离中的最小值对应的节点作为下一个待处理节点,这样就开始了下一轮处理。
python代码实现如下
import numpy as np
def dijk(adjacent_array, source_node):
weight = adjacent_array
node_num = len(weight[0])
# path是记录相应索引值对应的节点的前驱,索引为0的只是为了占位。例如path[1]对应的值是节点1的最短前驱
path = [i for i in range(1+node_num)]
# distance记录了源节点到当前节点索引的距离如distance[3]表示的源节点到节点4的距离
distance = [float("inf") for i in range(node_num)]
distance[source_node-1] = 0
mark = source_node
# visited is a list of nodes
visited = []
while len(visited)!=node_num:
temp = float("inf")
next_mark = mark
# 根据当前Mark节点的邻接点到源点的距离,选择最小的作为下一个Mark节点
for i in range(node_num):
# 这里的i是节点索引,也即节点序号减一
if distance[i]<temp and (i+1) not in visited:
temp = distance[i]
next_mark = i+1
mark = next_mark
# 访问Mark节点,更新与Mark节点相连的邻接点到源点的距离,以及前驱
for i in range(node_num):
if weight[mark-1][i]:
# i denotes the index of node adjacent to node mark
if weight[mark-1][i]+distance[mark-1]<distance[i]:
distance[i] = weight[mark-1][i]+distance[mark-1]
path[i+1] = mark
visited.append(mark)
for i in range(len(path)):
if i == 0:
continue
pa = [i]
j = i
while path[j] != source_node:
pa.insert(0, path[j])
j = path[j]
pa.insert(0,source_node)
print("the path to %d is:" % i)
print("with cost:%f"%distance[i-1])
print(pa)
print(distance)
dist=np.array([[0,1,1,0.5,0,0],[1,0,0,1,1,0],[1,0,0,1,1,1],[0.5,1,1,0,1,0],[0,1,1,1,0,1],[0,0,1,0,1,0]])
dijk(dist, 1)
结果如下
the path to 1 is:
with cost:0.000000
[1, 1]
the path to 2 is:
with cost:1.000000
[1, 2]
the path to 3 is:
with cost:1.000000
[1, 3]
the path to 4 is:
with cost:0.500000
[1, 4]
the path to 5 is:
with cost:1.500000
[1, 4, 5]
the path to 6 is:
with cost:2.000000
[1, 3, 6]
[0, 1.0, 1.0, 0.5, 1.5, 2.0]