很喜欢qiao的第一个回答!
这里唯一缺少的是将顶点标记为已访问。
为什么我们需要这样做?
让我们假设有另一个节点 13 从节点 11 连接。现在我们的目标是找到节点 13。
运行一段时间后,队列将如下所示:
[[1, 2, 6], [1, 3, 10], [1, 4, 7], [1, 4, 8], [1, 2, 5, 9], [1, 2, 5, 10]]
请注意,最后有两条节点编号为 10 的路径。
这意味着来自节点号 10 的路径将被检查两次。在这种情况下,它看起来并没有那么糟糕,因为 10 号节点没有任何子节点。但它可能真的很糟糕(即使在这里,我们也会无缘无故地检查该节点两次。)
节点号 13 不在这些路径中,因此程序在到达最后节点号为 10 的第二条路径之前不会返回。我们将重新检查它。
我们所缺少的只是一组标记访问过的节点而不是再次检查它们..
这是qiao修改后的代码:
graph = {
1: [2, 3, 4],
2: [5, 6],
3: [10],
4: [7, 8],
5: [9, 10],
7: [11, 12],
11: [13]
}
def bfs(graph_to_search, start, end):
queue = [[start]]
visited = set()
while queue:
# Gets the first path in the queue
path = queue.pop(0)
# Gets the last node in the path
vertex = path[-1]
# Checks if we got to the end
if vertex == end:
return path
# We check if the current node is already in the visited nodes set in order not to recheck it
elif vertex not in visited:
# enumerate all adjacent nodes, construct a new path and push it into the queue
for current_neighbour in graph_to_search.get(vertex, []):
new_path = list(path)
new_path.append(current_neighbour)
queue.append(new_path)
# Mark the vertex as visited
visited.add(vertex)
print bfs(graph, 1, 13)
程序的输出将是:
[1, 4, 7, 11, 13]
没有不必要的重新检查..