一、Dijkstra
1、算法原理:
- 指定起点s,引进两个集合S和U。
S:是记录已求出最短路径的顶点(以及相应的最短路径长度)
U:记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。 - Step1,S中只有起点s,从U中找出路径最短的顶点,将其加入到S中
- Step2,更新U中的顶点和顶点对应的路径
- 重复Step1和Step2 直到遍历完所有顶点
重复Step1,即更新S:从U中找出路径最短的顶点,加入到S中;
重复Step2,即更新U中的顶点和顶点对应的路径
比如我们想要计算从D到其他城市的最短距离:
Step1,S={D(0)}, U={A(∞),B(∞),C(3),E(4),F(∞),G(∞)}
Step2 通过C,更新从D到其他城市的最短距离
S={D(0),C(3)},
B(∞)=C(3)+10=13
F(∞)=C(3)+6=9
E(4)=C(3)+5=8(不更新)
U={A(∞),B(13),E(4),F(9),G(∞)}
Step3通过E,更新从D到其他城市的最短距离:
S={D(0),C(3),E(4)},
F(9)=E(4)+2=6
G(∞)=E(4)+8=12
U={A(∞),B(13),F(6),G(12)}
Step4通过F,更新从D到其他城市的最短距离
S={D(0),C(3),E(4),F(6)},
B(13)=F(6)+7=13 (不更新)
G(12)=F(6)+9=15 (不更新)
A(∞)=F(6)+16=22
U={A(22),B(13),G(12)}
Step5通过G,更新从D到其他城市的最短距离
S={D(0),C(3),E(4),F(6),G(12)},
A(22)=G(12)+14=26 (不更新)
U={A(22),B(13)}
Step6通过B,更新从D到其他城市的最短距离
S={D(0),C(3),E(4),F(6),G(12),B(13)},
A(22)=B(13)+12=25 (不更新)
U={A(22)}
最终,得到从D到其他城市的最短距离:
S={D(0),C(3),E(4),F(6),G(12),B(13),A(22)}
二、Floyd算法
初始的距离矩阵:
Floyd算法原理:
- 使用了动态规划的思想,将图中顶点编号为1-n
- 以两点之间最短距离经过的顶点中最大的顶点编号作为阶段,两点间目前算出的最短路径作为状态的值
- 假设 为顶点编号i和j两点经过 最大顶点编号不超过k的最短路径长度,那么:
代码样例:
import numpy as np
a = np.array([[0, 12, 999, 999, 999, 16, 14],
[12, 0, 10, 999, 999, 7, 999],
[999,10, 0, 3, 5, 6, 999],
[999,999,3, 0, 4, 999,999],
[999,999,5, 4, 0, 2, 8],
[16, 7, 6, 999, 2, 0, 9],
[14, 999,999,999, 8, 9, 0]])
n=7
# 使用Floyd算法
for k in range(0, n): # 阶段
for i in range(0, n): # 起点
for j in range(0, n): # 终点
if a[i][k] + a[k][j] < a[i][j]:
a[i][j] = a[i][k] + a[k][j]
# 输出结果
print('各城市之间的最短距离:', a)
print('城市D到其他城市的最短距离:', a[3])
使用networkx 里面的Dijkstra算法和Flody算法
import networkx as nx
import matplotlib.pyplot as plt
G=nx.read_gml('./football.gml')
nx.draw(G,with_labels=True)
#plt.show()
print(nx.shortest_path(G, source='Buffalo', target='Kent'))
print(nx.shortest_path(G, source='Buffalo', target='Rice'))
# Dijkstra算法
print(nx.single_source_dijkstra_path(G, 'Buffalo'))
print(nx.multi_source_dijkstra_path(G, {'Buffalo', 'Rice'}))
# Flody算法
print(nx.floyd_warshall(G, weight='weight'))