简体   繁体   English

Dijkstra在Python中的算法实现-它如何工作?

[英]Dijkstra's Algorithm Implementation in Python - How Does it Work?

I can use the following English algorithm to find shortest paths using Dijkstra's Algorithm on paper: 我可以在纸上使用Dijkstra的算法使用以下英语算法来查找最短路径:

  • Step 1: Assign permanent label and order to starting node 步骤1:将永久标签和顺序分配给起始节点

  • Step 2: Assign temporary labels to all nodes directly reached by starting node 步骤2:将临时标签分配给起始节点直接到达的所有节点

  • Step 3: Select the lowest temporary label and make it permanent 步骤3:选择最低的临时标签并将其永久化

  • Step 4: Assign an order to the node 步骤4:将订单分配给节点

  • Step 5: Update and assign temporary labels for nodes directly reached from the new permanent node 步骤5:为从新的永久节点直接到达的节点更新并分配临时标签

  • Step 6: Repeat steps 3, 4 & 5 until the destination node is made permanent 步骤6:重复步骤3、4和5,直到将目标节点设为永久节点

I have searched for a Python implementation and many are quite complex or use data structures I'm not familiar with. 我已经搜索了Python实现,其中许多都非常复杂或使用了我不熟悉的数据结构。 Eventually I found the one below. 最终我找到了下面的那个。 I have spent quite some time tracing it's execution in a Python visualizer, and I can get a sense of how it works but it has not yet clicked for me. 我花了很多时间在Python可视化工具中追踪它的执行情况,我可以大致了解它的工作原理,但对我来说还没有点击。

Could someone please explain how the code relates to the English algorithm? 有人可以解释一下代码与英语算法的关系吗? For example, how does the notion of "predecessors" relate to the "permanent labels" in the English version? 例如,“前辈”的概念与英文版中的“永久标签”有何关系?

from math import inf

graph = {'a':{'b':10,'c':3},'b':{'c':1,'d':2},'c':{'b':4,'d':8,'e':2},'d':{'e':7},'e':{'d':9}}


def dijkstra(graph,start,goal):
    shortest_distance = {}
    predecessor = {}
    unseenNodes = graph
    infinity = inf
    path = []
    for node in unseenNodes:
        shortest_distance[node] = infinity
    shortest_distance[start] = 0

    # Determine which is minimum node. What does that mean?
    while unseenNodes:
        minNode = None
        for node in unseenNodes:
            if minNode is None:
                minNode = node
            elif shortest_distance[node] < shortest_distance[minNode]:
                minNode = node

        for edge, weight in graph[minNode].items():
            if weight + shortest_distance[minNode] < shortest_distance[edge]:
                shortest_distance[edge] = weight + shortest_distance[minNode]
                predecessor[edge] = minNode
        unseenNodes.pop(minNode)

    currentNode = goal
    while currentNode != start:
        try:
            path.insert(0,currentNode)
            currentNode = predecessor[currentNode]
        except KeyError:
            print('Path not reachable')
            break
    path.insert(0,start)
    if shortest_distance[goal] != infinity:
        print('Shortest distance is ' + str(shortest_distance[goal]))
        print('And the path is ' + str(path))


dijkstra(graph, 'a', 'b')

Dijkstra's algorithm same to prim's algorithm for minimum spanning tree. Dijkstra的算法与prim的最小生成树算法相同。 Like Prim's MST, we generate a shortest path tree with given source as root. 像Prim的MST一样,我们以给定源作为根生成最短路径树。 We maintain two sets, one set contains vertices included in shortest path tree, other set includes vertices not yet included in shortest path tree. 我们维护两组,一组包含最短路径树中包含的顶点,另一组包含尚未包含在最短路径树中的顶点。 At every step of the algorithm, we find a vertex which is in the other set (set of not yet included) and has a minimum distance from the source. 在算法的每个步骤中,我们都找到一个顶点,该顶点在另一个集合中(尚未包括在内),并且与源的距离最小。

import sys

class Graph():

    def __init__(self, vertices):
        self.V = vertices
        self.graph = [[0 for column in range(vertices)]
                  for row in range(vertices)]

    def printSolution(self, dist):
        print("Vertex tDistance from Source")
        for node in range(self.V):
            print(node, "t", dist[node])

    def minDistance(self, dist, sptSet):

        min = sys.maxint

        for v in range(self.V):
            if dist[v] < min and sptSet[v] == False:
                min = dist[v]
                min_index = v

        return min_index

    def dijkstra(self, src):

        dist = [sys.maxint] * self.V
        dist[src] = 0
        sptSet = [False] * self.V

        for cout in range(self.V):

            u = self.minDistance(dist, sptSet)

            sptSet[u] = True

            for v in range(self.V):
                if self.graph[u][v] > 0 and sptSet[v] == False and \
                    dist[v] > dist[u] + self.graph[u][v]:
                    dist[v] = dist[u] + self.graph[u][v]

        self.printSolution(dist)

g = Graph(9)
g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
           [4, 0, 8, 0, 0, 0, 0, 11, 0],
           [0, 8, 0, 7, 0, 4, 0, 0, 2],
           [0, 0, 7, 0, 9, 14, 0, 0, 0],
           [0, 0, 0, 9, 0, 10, 0, 0, 0],
           [0, 0, 4, 14, 10, 0, 2, 0, 0],
           [0, 0, 0, 0, 0, 2, 0, 1, 6],
           [8, 11, 0, 0, 0, 0, 1, 0, 7],
           [0, 0, 2, 0, 0, 0, 6, 7, 0]]
g.dijkstra(0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM