Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。
问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)
S集合 | U集合 |
---|---|
选A为起点,S={A} 此时的最短路径 A->A=0 以A为中心点,从A开始查找 |
U={B, C, D, E, F} A->B=10 A->D=4 A->{E, F, C}=\(\infty\) d(AD)最短 |
选入D,此时S={A, D} 此时最短路径 A->A=0 A->D=4 以D为中间点,从A->D这条最短路径进行查找 |
U={B, C, E, F} A->D->B=6 < 10 A->D->E=10 A->D->C=19 A->D->F=\(\infty\) d(ADB)最短 |
选入B,此时S={A, D, B} 此时最短路径 A->A=0 A->D=4 A->D->B=6 以B为中间点,从A->D->B这条路径进行查找 |
U={C, E, F} A->D->B->C=14<19 A->D->B->E=12>10 A->D->B->F=\(\infty\) d(ADE)最短 |
选入E,此时S={A, D, B, E} 此时最短路径 A->A=0 A->D=4 A->D->B=6 A->D->E=10 以E为中间点,从A->D->E这条路径进行查找 |
U={C, F} A->D->E->C=11<14 A->D->E->F=22 d(ADEC)最短 |
选入C,此时S={A, D, B, E, C} 此时最短路径 A->A=0 A->D=4 A->D->B=6 A->D->E=10 A->D->E->C=11 以C为中间点,从A->D->E->C这条路径进行查找 |
U={F} A->D->E->C->F=16 发现最短路径为A->D->E->C->F |
选入F,此时S={A, D, B, E, C, F} 此时最短路径 A->A=0 A->D=4 A->D->B=6 A->D->E=10 A->D->E->C=11 A->D->E->C->F=16 以F为中间点,从A->D->E->C->F这条路径进行查找 |
集合为空,查找完毕 |
最后,我们得出
路径 | 距离 |
---|---|
A->A | 0 |
A->D | 4 |
A->D->B | 6 |
A->D->E | 10 |
A->D->E->C | 11 |
A->D->E->C->F | 16 |
我们使得与节点有直接接触的节点的距离为确定值,没有直接接触的节点为无穷大,然后构建一个二维矩阵
A | B | C | D | E | F | |
---|---|---|---|---|---|---|
A | 0 | 10 | \(\infty\) | 4 | \(\infty\) | \(\infty\) |
B | 10 | 0 | 8 | 2 | 6 | \(\infty\) |
C | \(\infty\) | 8 | 0 | 15 | 1 | 5 |
D | 4 | 2 | 15 | 0 | 6 | \(\infty\) |
E | \(\infty\) | 6 | 1 | 6 | 0 | 12 |
F | \(\infty\) | \(\infty\) | 5 | \(\infty\) | 12 | 0 |
#!/usr/bin/env python # -*- coding: UTF-8 -*- __author__ = "A.L.Kun" __file__ = "demo02.py" __email__ = "liu.zhong.kun@foxmail.com" MAX = float('inf') def dijkstra(matrix, start_node): matrix_length = len(matrix) # 矩阵一维数组的长度,即节点的个数 used_node = [False] * matrix_length # 访问过的节点数组 distance = [MAX] * matrix_length # 最短路径距离数组 distance[start_node] = 0 # 初始化,将起始节点的最短路径修改成0 # 将访问节点中未访问的个数作为循环值,其实也可以用个点长度代替。 while used_node.count(False): min_value = MAX min_value_index = -1 # 在最短路径节点中找到最小值,已经访问过的不在参与循环。 # 得到最小值下标,每循环一次肯定有一个最小值 for index in range(matrix_length): if not used_node[index] and distance[index] < min_value: min_value = distance[index] min_value_index = index # 将访问节点数组对应的值修改成True,标志其已经访问过了 used_node[min_value_index] = True # 更新distance数组。 # 以B点为例:distance[x] 起始点达到B点的距离。 # distance[min_value_index] + matrix[min_value_index][index] 是起始点经过某点达到B点的距离,比较两个值,取较小的那个。 for index in range(matrix_length): distance[index] = min(distance[index], distance[min_value_index] + matrix[min_value_index][index]) return distance matrix_ = [ [0,10,MAX,4,MAX,MAX], [10,0,8,2,6,MAX], [MAX,8,10,15,1,5], [4,2,15,0,6,MAX], [MAX,6,1,6,0,12], [MAX,MAX,5,MAX,12,0] ] ret = dijkstra(matrix_, 0) print(ret)