【问题标题】:Error in python implementation of Dijkshtra's algorithmDijkshtra算法的python实现错误
【发布时间】:2020-06-27 13:30:04
【问题描述】:
def Dijkshtra(self, root):

    if self.flag == 0:
        # NOTE Run this Function only once
        self.initialize(root)
    self.flag = 1

    while len(self.visited) != 0:
        for neighbour in self.graph[root]:
            self.parent[neighbour] = root
            if self.shortestDist[neighbour] > self.shortestDist[self.parent[neighbour]] + self.weight[neighbour, self.parent[neighbour]]:
                self.shortestDist[neighbour] = self.shortestDist[self.parent[neighbour]] + self.weight[neighbour, self.parent[neighbour]]
                self.parent[neighbour] = root

        # NOTE Sort Shortest Distance dictionary 
        self.shortestDist = {k: v for k, v in sorted(self.shortestDist.items(), key=lambda item: item[1])}


        for key in self.shortestDist.keys():
            if self.shortestDist[key] != float('inf'):
                self.visited.add(key)

        # NOTE Since we've calculated the DIRECT shorted distance
        #      of all it's neighbour from the parent Node
        print(self.shortestDist)
        
        # NOTE STOP Recursion, once we've processed all Nodes in the Graph
        root = self.visited.pop()

我已经借助 namedtuple 来存储每个节点的权重 还初始化了 shortestDist 和一个 defaultdict 以存储每个节点的最短距离,它会随着遍历图而更新。 Stackoverflow是因为下面的for循环引起的

for key in self.shortestDist.keys():
    if self.shortestDist[key] != float('inf'):
        self.visited.add(key)

【问题讨论】:

  • 详细发布代码的整个最终版本和错误回溯。
  • 我在代码中看不到任何可能导致堆栈溢出的内容。唯一被调用的用户定义函数是initialise,没有更深层次的函数调用,更不用说会有递归了……检查你得到的异常跟踪,在那里你可以看到调用的堆栈,以及这些调用中存在循环的地方。
  • codeshare.io/arppJZ 您可以点击此链接查看完整代码
  • 您的算法与 Dijkstra 的算法不同。它缺少队列的概念。您似乎将“已访问”集的概念与该队列混淆了。你需要两者。您的算法正在循环运行,访问您之前已经访问过的节点。它应该在一秒钟内完成。您为什么不实现它,就像它在互联网上的许多地方都可用一样?

标签: python algorithm stack-overflow dijkstra


【解决方案1】:

您的算法循环运行:它不止一次地访问节点。这是可能的,因为您从 visited 集合中删除访问过的节点,这意味着它们可以再次访问。这是错误的。

您的算法中缺少的主要成分是优先级队列。此外,它缺乏将节点分为三类(已访问、未访问、前沿),仅提供两种(已访问或未访问)。

Wikipedia 上的算法大纲解释了在每次迭代的最后一步中使用此优先级队列:

  1. 否则,选择标记为最小暂定距离的未访问节点,设置为新的“当前节点”,返回步骤3。

您的代码中目前没有选择距离最小的访问节点的机制。相反,它从visited 中选择一个任意 节点(因为在Python 中set 是无序的),更糟糕的是,它visited 中删除它。

要更正您的代码,请查阅同一维基百科页面上提供的伪代码,我建议您使用变体 with priority queue

在 Python 中,您可以使用 heapq 对优先级队列(heappushheappop)执行操作。

【讨论】:

  • TYSM,我点击了链接,发现该算法非常有用。我不知道我在做什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多