给定带权有向图G-(V ,E),其中每条边的权是非负实数。另外,还给定V中的一个顶点,称为源。现在要计算从源到所有其他各顶点的最短路长度。这里路的长度是指路上各边权之和。这个问题通常称为单源最短路径问题。
Dijkstra基本思想:设置顶点集合S,并不断的做贪心选择来扩充集合S
运行过程:
初始化三个数组,分别是:集合S(初始点0),距离数组(inf),前面点(空)
将0的距离标记为0,搜索距离数组中最短的距离,将0加入集合S
1.每次从未标记的节点中选择距离出发点最近的节点,标记,收录到最优路径集合中
2.计算刚加入节点A的邻近节点B的距离(不包含标记的节点),若(节点A的距离+节点A到节点B的边长) <节点B的距离,就更新节点B的距离和前面点
最终结果:通过前面点进行回溯得到最短路径
时间复杂度:O(n^2)
def dijkstra(start, c):
# 已选中点
passed = [start]
# 未选中点,节点声明
nopass = [x for x in range(len(c)) if x != start]
# 从0到个节点距离,始终更新dis[0]
dis = c[start]
# 前面点初始化
pre = [0] * len(c)
pre[start] = -1
while len(nopass):
# 找出最短路径下标
idx = nopass[0]
for i in nopass:
if dis[i] < dis[idx]:
idx = i
nopass.remove(idx)
passed.append(idx)
# 更新最短距离和前面点
for i in nopass:
# 当前距离+之前距离
if dis[idx] + c[idx][i] < dis[i]:
dis[i] = dis[idx] + c[idx][i]
pre[i] = idx
return dis, pre
if __name__ == "__main__":
inf = 10086
# 邻接表
c = [[0, 1, 12, inf, inf, inf],
[inf, 0, 9, 3, inf, inf],
[inf, inf, 0, inf, 5, inf],
[inf, inf, 4, 0, 5, 15],
[inf, inf, inf, inf, 0, 4],
[inf, inf, inf, inf, inf, 0]]
# 由pre回溯得到最短路径和最短路径的距离
dis, pre = dijkstra(0, c)
print(dis, pre)