Dijkstra的理解和实现

Dijkstra理解:

1、单点按照距离递增辐射出去;
2、辐射到的点会被放进优先级队列,距离远的点可能会先放到队列里;
3、距离近的,可能会后放进队列,但是肯定会先出去;
4、每一个放进优先级队列的点,需要记录:自己,自己的前继节点,自己到起点的距离,会被用到的。

容易的误解不是简单的每次走最近的点,是逐步(按照已确定的点不断传染辐射方式,保证最近的点一定在候选区)添加点到候选区,选出距离起点最近的点,再次辐射

优化:

把邻居放进候选区,没必要把全部邻居都放进去,需要有2个条件:

1、邻居不在已确定最近的点集合里面,也就是不在visited里面;
2、邻居通过当前点到起点距离要小于之前记录的距离,也就是这个邻居前一次进入备选区时的距离,要不然进去了,也会被自己比下去;

代码实现

import heapq
import numpy as np

def dijkstra(graph,start):
    pqueue = []
    heapq.heappush(pqueue,(0.0,start))
    
    visit = set()
    parent = {start:None}
    distance = {vertex:np.Inf for vertex in graph}
    distance[start] = 0.0
    
    
    
    while pqueue:
        pair = heapq.heappop(pqueue)        
        dist = pair[0]
        vertex = pair[1]
        visit.add(vertex)
        
        edges = graph[vertex]
        for v in edges:
            if v not in visit:
                if dist + graph[vertex][v] < distance[v]:
                    heapq.heappush(pqueue,(dist + graph[vertex][v],v))
                    distance[v] = dist + graph[vertex][v]
                    parent[v] = vertex 
                    
    return parent,distance

另外一种代码实现,这里的循环条件while count < vnum and,非常体现功力:

def dijkstra2(graph,start):
    vnum = len(graph)
    pqueue = []
    heapq.heappush(pqueue,(0.0,None,start))
    paths = {vertex : None for vertex in graph}
    count = 0
    
    while count < vnum and pqueue:
        pair = heapq.heappop(pqueue)
        distance = pair[0]
        parent = pair[1]
        vertex = pair[2]
        if paths[vertex]:
            continue
        paths[vertex] = (parent,distance)
        edges = graph[vertex]
        for v in edges:
            if paths[v] is None:
                heapq.heappush(pqueue,(distance + graph[vertex][v],vertex,v))
        count += 1
    return paths

运行结果:

    #%%
    g = {'A':{'B':1,'C':2},
         'B':{'A':1,'C':3,'D':4},
         'C':{'A':2,'B':3,'D':5,'E':6},
         'D':{'B':4,'C':5,'E':7,'F':8},
         'E':{'C':6,'D':7,'G':9},
         'F':{'D':8},
         'G':{'E':9}
        }
    i,j=dijkstra(g,'A')
    print i
    print j
    t=dijkstra2(g,'A')
    print t


{'A': None, 'C': 'A', 'B': 'A', 'E': 'C', 'D': 'B', 'G': 'E', 'F': 'D'}
{'A': 0.0, 'C': 2.0, 'B': 1.0, 'E': 8.0, 'D': 5.0, 'G': 17.0, 'F': 13.0}
{'A': (None, 0.0), 'C': ('A', 2.0), 'B': ('A', 1.0), 'E': ('C', 8.0), 'D': ('B', 5.0), 'G': ('E', 17.0), 'F': ('D', 13.0)}
点赞