【算法】python实现最短路径Dijkstra算法

# -*- 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

你可能感兴趣的:(python算法实践)