【问题标题】:How to track and show visited nodes that are in the same level?如何跟踪和显示同一级别的访问节点?
【发布时间】:2020-05-25 05:19:03
【问题描述】:

我对图上的 bfs 算法有疑问。如下图所示,我想找到从“C”到“L”的路径,并以正确的顺序获取所有展开的节点。我从下面显示的代码中得到了正确的结果,但我找不到跟踪/显示访问节点的方法 - 这是节点 (D) 和 (H)。

到目前为止,我想到的解决方案是获取同一级别拳头中的所有节点,然后在将其放入队列之前进行排序。

注意:

  1. 决胜局是按字母顺序排列的:我可以使用 itemgettere 来实现。
  2. 你可以找到blhsinghere发布的原始代码。
import collections
from operator import itemgettere

class graph:


    def __init__(self, path=None):
        self.graph = {'A': ['B', 'C', 'D', 'E'], 'B': ['A', 'F'], 'F': ['B', 'J'], 'J': ['F', 'K'], 'C': ['A', 'G'],
                      'G': ['C', 'H', 'K'], 'K': ['G', 'J'], 'D': ['A', 'H'], 'H': ['D', 'G', 'L'], 'L': ['H'],
                      'E': ['A', 'I'], 'I': ['E', 'M'], 'M': ['I']}

    def bfs(self, graph, root, goal):
        seen, queue = {root}, collections.deque([(root, 0)])
        visit_order = []
        levels = []

        while queue:

            vertex, level = queue.popleft()

            # Stop when the goal is reached
            if goal in visit_order:
                break

            visit_order.append(vertex)
            levels.append(level)

            for node in graph.get(vertex):
                if node not in seen:
                    seen.add(node)
                    queue.append((node, level + 1))

            # sort queue by level, then alphabetically
            temp_queue = list(queue)
            temp_queue.sort(key=itemgetter(1, 0))
            queue = collections.deque(temp_queue)

        print(visit_order)
        print(levels)


g = graph()
g.bfs(g.graph, 'C', 'L')

#output = ['C', 'A', 'G', 'B', 'D', 'E', 'H', 'K', 'F', 'I', 'J', 'L']
#[0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3]

【问题讨论】:

  • 如果我能代替你,我会做深度优先搜索。每次递归调用时,将访问过的节点添加到列表中以维护到目前为止的路径。如果到达最后一个节点,则路径已准备就绪。如果没有,只需从列表中弹出节点,然后继续搜索。
  • 如果要使用 bfs,请将路径上的节点列表排入队列。就像队列条目看起来像 | {C,A}, {C, G} |.

标签: python algorithm graph-traversal


【解决方案1】:

澄清一下,这个图没有方向,所以当你在节点'A'时,它的邻居实际上是{B,C,D,E},而不仅仅是{B,D,E},除非您明确排除了前一个节点“C”。

我认为这个问题的棘手部分是你想找出一个节点是否曾经被访问过,但又想排除当前节点的前一个节点之前肯定被访问过的节点。

我修改了示例代码,如下所示。 我逐级遍历图表,因此我不需要明确跟踪级别信息,但我将其留在那里以防万一。

class graph:
    def __init__(self, path=None):
        self.graph = {'A': ['B', 'C', 'D', 'E'], 'B': ['A', 'F'], 'F': ['B', 'J'], 'J': ['F', 'K'], 'C': ['A', 'G'],
                      'G': ['C', 'H', 'K'], 'K': ['G', 'J'], 'D': ['A', 'H'], 'H': ['D', 'G', 'L'], 'L': ['H'],
                      'E': ['A', 'I'], 'I': ['E', 'M'], 'M': ['I']}

    def bfs(self, graph, root, goal):
        seen, currentLevel = set(), [(None, None, root)]
        visit_order = []
        level = 0 # you can use the level info if needed
        while currentLevel:
            nextLevel = []
            for v0, v1, v2 in currentLevel:
                if v2 not in seen:
                    visit_order.append(v2)
                    seen.add(v2)
                    for v3 in graph[v2]:
                        nextLevel.append((v1, v2, v3))
                elif v2 != v0:
                    visit_order.append(f"({v2})")
            level += 1

            # Stop when the goal is reached
            if goal in seen:
                break

            # all nodes in nextLevel are at the same level already. Just sort alphabetically
            currentLevel = sorted(nextLevel, key=lambda p: p[2])

        print(visit_order)

g = graph()
g.bfs(g.graph, 'C', 'L')
# output = ['C', 'A', 'G', 'B', 'D', 'E', 'H', 'K', '(D)', 'F', '(H)', 'I', 'J', 'L']

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多