【python3数据结构】Dijkstra’s算法(搜索最短路径问题)

 Dijkstra’s 算法
• 贪婪
• 使用优先级队列(heap)
• 列表中添加元素{元素,优先级},并从另一端删除最高优先级项
• 入队:添加一个{元素,优先级}
• 队列:删除最高优先级的元素
• 优先级队列通常使用“堆”来实现,并可以优先考虑低值(Min-Heap)或大值(Max-Heap)

缺点:边为负数,负循环等无法准确搜索。

 

 

# -*- coding: utf-8 -*-
# @Date   : 2019/12/3
# @File   : Dijkstra.py


from AdjListGraph import Graph, Vertex
import heapq

def shortest(vertex, path):
    # 使用每个节点的previous回溯
    if vertex.previous:
        path.append(vertex.getVertexID())
        shortest(vertex.previous, path)
    return


def dijkstra(G, start, destination):
    print("Dijkstra's shortest path")
    # 起始点的距离为0, 其余的默认inf
    start.setDistance(0)
    unvisitedHeap = [(v.getDistance(), v) for v in G]
    heapq.heapify(unvisitedHeap)
    while len(unvisitedHeap):
        # 第一次pop的为起始点的vertex(pop distance最小的节点)
        unvisitedTuple = heapq.heappop(unvisitedHeap)
        currentVertex = unvisitedTuple[1]
        currentVertex.setVisited() # 置为访问过

        # 遍历当前节点的neighbors. adjacent : Dict: Vertex:Weight # 当前节点的所有neighbors
        for n in currentVertex.adjacent:
            if n.visited:
                continue
            # 以当前节点为起(已经算的distance),到,邻居节点的distance(distance + weight/Edge)
            newDistance = currentVertex.getDistance() + currentVertex.getWeight(n)
            # 若这个新路径的距离小于原始neighbor的距离 则更新这个neighbor的距离
            if newDistance < n.getDistance():
                n.setDistance(newDistance)
                n.setPrevious(currentVertex) # 当前neighbor的最小距离的来源父节点
                print('Updated : current = %s next = %s newDist = %s' \
                      % (currentVertex.getVertexID(), n.getVertexID(), n.getDistance()))
            else:
                print('Not updated : current = %s next = %s newDist = %s' \
                      % (currentVertex.getVertexID(), n.getVertexID(), n.getDistance()))

        while len(unvisitedHeap):
            heapq.heappop(unvisitedHeap)

        unvisitedHeap = [(v.getDistance(), v) for v in G if not v.visited]
        heapq.heapify(unvisitedHeap)

if __name__ == '__main__':

    G = Graph(True)
    G.addVertex('a')
    G.addVertex('b')
    G.addVertex('c')
    G.addVertex('d')
    G.addVertex('e')
    G.addEdge('a', 'b', 4)
    G.addEdge('a', 'c', 1)
    G.addEdge('c', 'b', 2)
    G.addEdge('b', 'e', 4)
    G.addEdge('c', 'd', 4)
    G.addEdge('d', 'e', 4)

    for v in G:
        for w in v.getConnections():
            vid = v.getVertexID()
            wid = w.getVertexID()
            print('( %s , %s, %3d)' % (vid, wid, v.getWeight(w)))

    start = G.getVertex('a')
    destination = G.getVertex('e')
    dijkstra(G, start, destination)

    # 起始点start 到 各个节点的距离
    for v in G.vertexDict.values():
        print(start.getVertexID(), " to ", v.getVertexID(), "-->", v.getDistance())

    path = []
    shortest(destination, path)
    path = path + [start.getVertexID()]
    print('The shortest path from a to e is: %s' % (path[::-1]))

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值