【问题标题】:Unable to figure out the bug in BFS无法找出 BFS 中的错误
【发布时间】:2020-08-06 07:03:52
【问题描述】:

我已经编写了两个版本的 BFS,但是其中一个有错误并且不会导致正确的结果。但我无法弄清楚错误是什么。

正确版本:

def find_all_distances(self, start_node):
    distance = {}
    marked = {}
    marked[start_node] = True
    distance[start_node] = 0
    queue = [start_node]
    while queue:
        node = queue.pop(0)
        for adj_node in self.adj[node]:
            if adj_node not in marked:
                marked[adj_node] = True
                distance[adj_node] = distance[node] + 6
                queue.append(adj_node)

越野车版本:

def find_all_distances(self, start_node):
    distance = {}
    marked = {}
    queue = [(start_node, 0)]
    while queue:
        node, dist = queue.pop(0)
        marked[node] = True
        distance[node] = dist
        for adj_node in self.adj[node]:
            if adj_node not in marked:
                queue.append((adj_node, dist + 6))

对我来说唯一明显的区别是我们标记访问的时间 - 在添加到队列之前或从队列中弹出之后。为什么会影响结果?

【问题讨论】:

    标签: algorithm debugging graph breadth-first-search


    【解决方案1】:

    由于Buggy版本导致同类节点访问两次以上,示例

    假设你从 A 开始:

    迭代 1:

    队列 Q = [A]

    标记 = {}

    迭代 2:

    节点弹出:A

    队列 Q = [B]

    标记 = {A:True}

    迭代 3:

    节点弹出:B

    队列 Q = [C,D]

    标记 = {A:True,B:True}

    迭代 4:

    节点弹出:C

    队列 = [D,D]

    标记 = {A:True,B:True,C:True}

    看看发生了什么在第 4 次迭代中,节点 D 访问了两次...因为您在弹出后标记节点

    【讨论】:

      【解决方案2】:

      顺便说一句,pop(0) 的复杂度为 O(n)。不建议使用 Python 列表作为队列。请改用collections.deque

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-12
        • 1970-01-01
        相关资源
        最近更新 更多