# -*- coding: utf-8 -*-
# /usr/bin/python
# 作者:kimicr
# 实验日期:20190827
# Python版本:3.6.3
# 解决边的权重非负的最短路径问题的经典Dijkstra算法(适用范围:有向图、非负权重)
# 注意:最小路径不唯一
from collections import deque
import math
inf = math.inf
class DijkstraSP(object):
def __init__(self,Graph,s):
self.Graph = Graph
self.edgeTo = [] #用来存储路径结束的横切边(即最短路径的最后一条边的两个顶点)
self.distTo = [] #用来存储到每个顶点的最短路径
self.s = s #起点start
#打印顶点S到某一点的最短路径
def PrintPath(self,end):
temp = [end]
while self.edgeTo[end] != None:
temp.insert(0,self.edgeTo[end])
end = self.edgeTo[end]
return temp
def dijkstra(self):
d = deque() #导入优先队列(队列性质:先入先出)
for i in range(len(self.Graph[0])): #初始化横切边与最短路径-“树”
self.distTo.append(inf)
self.edgeTo.append(None)
self.distTo[self.s] = 0 #将顶点s加入distTo中
#print(self.edgeTo,self.distTo)
count = 0 #计数标志
d.append(self.Graph[self.s].index(min(self.Graph[self.s]))) #将直接距离顶点S最近的点加入队列
for i in self.Graph[self.s]: #将除直接距离顶点S的点外的其他顶点加入队列
if i != inf and count not in d:
d.append(count)
count += 1
for j in d: #处理刚加入队列的顶点
self.edgeTo[j] = self.s
self.distTo[j] = self.Graph[self.s][j]
#print(d,self.edgeTo,self.distTo)
while d:
count = 0
self.s = d.popleft() #弹出将该点作为顶点S,重复操作,直到队列为空
for i in self.Graph[self.s]: #进行边的松弛技术
if i != inf and self.distTo[self.s] + i <= self.distTo[count]:
self.distTo[count] = self.distTo[self.s] + i
self.distTo[count] = round(self.distTo[count],2)
self.edgeTo[count] = self.s
if count in d:
pass
else:
d.append(count)
elif i != inf and self.distTo[self.s] + i > self.distTo[count]:
self.Graph[self.s][count] = inf #删除该无用边
if count in d:
pass
else:
d.append(count)
count += 1
#打印结果
print(self.edgeTo,self.distTo)
for i in range(len(self.Graph[0])):
print("0->%d最短路径:" %(i),end="")
path = self.PrintPath(i)
for i in path[:-1]:
print(i,'-> ',end = "")
print(path[-1],',',self.distTo[path[-1]])
if __name__ == "__main__":
Graph = [[inf,inf,0.26,inf,0.38,inf,inf,inf],
[inf,inf,inf,0.29,inf,inf,inf,inf],
[inf,inf,inf,inf,inf,inf,inf,0.34],
[inf,inf,inf,inf,inf,inf,0.52,inf],
[inf,inf,inf,inf,inf,0.35,inf,0.37],
[inf,0.32,inf,inf,0.35,inf,inf,0.28],
[0.58,inf,0.40,inf,0.93,inf,inf,inf],
[inf,inf,inf,0.39,inf,0.28,inf,inf],
]
Graph1 = [[inf,0,5,inf,inf,inf],
[inf,inf,inf,30,35,inf],
[inf,inf,inf,15,20,inf],
[inf,inf,inf,inf,inf,20],
[inf,inf,inf,inf,inf,10],
[inf,inf,inf,inf,inf,inf],
]
F = DijkstraSP(Graph,0)
F.dijkstra()
[None, 5, 0, 7, 0, 4, 3, 2] [0, 1.05, 0.26, 0.99, 0.38, 0.73, 1.51, 0.6]
0->0最短路径:0 , 0
0->1最短路径:0 -> 4 -> 5 -> 1 , 1.05
0->2最短路径:0 -> 2 , 0.26
0->3最短路径:0 -> 2 -> 7 -> 3 , 0.99
0->4最短路径:0 -> 4 , 0.38
0->5最短路径:0 -> 4 -> 5 , 0.73
0->6最短路径:0 -> 2 -> 7 -> 3 -> 6 , 1.51
0->7最短路径:0 -> 2 -> 7 , 0.6
Process finished with exit code 0