《算法导论》Dijkstra算法实现

所谓单源最短路径(Single-Source-Shortest-Path)问题,就是求解从某个节点出发,到其他节点的最短距离。
求解该问题的常用算法有Bellman-Ford和Dijkstra,前者适用于一般情况如负权值边,后者适用于非负权值边。

参考《算法导论》第24章-单源最短路径的方法:
1.设置数组d存储每个节点到源节点的距离,维护一个提取最小d值的优先队列Q,Q初始化时是G的所有节点的集合
2.每次while循环取出Q中d最小节点u,添加到节点集合S,遍历当前节点u的邻居节点v,用所谓的松弛技术(Relax)更新邻居节点v的d取值(会影响下一个Q出列的节点)
3.直到Q队列为空,结束

伪代码:

Dijkstra(G, s)  
S = [ ] 
Q = [G] 
while Q:        
    u = extract_min_queue(Q)        
    S.append(u)     
    for each v in Adjacent[u]:          
        Relax(G, d, u, v)   
return d    

Relax(d, u, v)  
if d[v] > d[u] + G[u][v]:    
   d[v] = d[u] + G[u][v]       
   parent[v] = u

实现代码:

class Dijkstra(object):
    """
        Single Source Shortest Path

        G: Adajcent Matrix, 
        s: The index of source node
    """
    def __init__(self, G, s):
        self.numVertex = len(G)
        self.G = G # adjacent matrix, G[u][v]: weight of u -> v

        self.Q = range(self.numVertex) # queue for vertex, pop for each loop
        self.D = {} # distance between source and each vertex, update by relax
        self.parent = {} # store the shortest path

        for i in xrange(self.numVertex):
            self.D[i] = 2**32 - 1
            self.parent[i] = 'null'

        self.D[s] = 0 # source distance


    def extract_min_queue(self):
        """
            extract min{D} under current vertex in Q
        """
        min_dist = 2**32 - 1
        min_index = None
        for vertex in self.Q:
            if self.D[vertex] < min_dist:
                min_dist = self.D[vertex]
                min_index = vertex
        self.Q.remove(min_index)
        return min_index

    def relax(self, u, v):
        """
            update D of each vertex
        """
        if self.D[v] > self.D[u] + self.G[u][v]:
            self.D[v] = self.D[u] + self.G[u][v]
            self.parent[v] = u

    def run(self):
        while(self.Q):
            u = self.extract_min_queue() # Q.remove(u)
            for v in xrange(self.numVertex):
                if G[u][v] == 0: # v is not adjacent by u
                    continue
                self.relax(u, v)
        print 'distance:', self.D
        print 'parent:', self.parent

if __name__ == '__main__':
    G = [[0, 10, 0, 5, 0],
         [0, 0, 1, 2, 0],
         [0, 0, 0, 0, 4],
         [0, 3, 9, 0, 2],
         [7, 0, 6, 0, 0]]

    test = Dijkstra(G, 0)
    test.run()

当图的每条边权值相同,即为无权图时,单源最短路径问题等价于BFS,从源点到各顶点的最小深度即最短路径。此时优先队列退化为BFS的队列,Dijkstra算法退化为BFS。

你可能感兴趣的:(算法笔记)