您没有跟踪访问过的节点,如果您的图不是有向无环图,这可能会导致大量时间浪费。例如,如果您的图表是
{'A': ['B', 'C', 'D', 'E'],
'B': ['A', 'C', 'D'],
'C': ['A', 'B', 'D'],
'D': ['A', 'B', 'C'],
'E': ['F'],
'F': ['G'],
'G': ['H'],
...
'W': ['X'],
'X': ['Y'],
'Y': ['Z']}
使用您的算法调用bfs(graph, 'A', 'Z')
会在最终到达 Z 之前不必要地循环通过“A”、“B”、“C”和“D”。而如果您跟踪访问过的节点,则只需添加“A”、“B”的邻居, 'C' 和 'D' 到队列中各一次。
def bfs(graph, start, end):
# maintain a queue of paths
queue = []
# push the first path into the queue
queue.append([start])
# already visited nodes
visited = set()
while queue:
# get the first path from the queue
path = queue.pop(0)
# get the last node from the path
node = path[-1]
# if node has already been visited
if node in visited:
continue
# path found
if node == end:
return path
# enumerate all adjacent nodes, construct a new path and push it into the queue
else:
for adjacent in graph.get(node, []):
# add the path only if it's end node hasn't already been visited
if adjacent not in visited
new_path = list(path)
new_path.append(adjacent)
queue.append(new_path)
# add node to visited set
visited.add(node)
使用这个版本的算法和字母图,这是队列和访问集在整个算法的 while 循环顶部的样子:
queue = [ ['A'] ]
visited = {}
queue = [ ['A', 'B'], ['A', 'C'], ['A', 'D'], ['A', 'E'] ]
visited = {'A'}
queue = [ ['A', 'C'], ['A', 'D'], ['A', 'E'], ['A', 'B', 'C'],
['A', 'B', 'D'] ]
visited = {'A', 'B'}
queue = [ ['A', 'D'], ['A', 'E'], ['A', 'B', 'C'], ['A', 'B', 'D'],
['A', 'C', 'D'] ]
visited = {'A', 'B', 'C'}
queue = [ ['A', 'E'], ['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'C', 'D'] ]
visited = {'A', 'B', 'C', 'D'}
queue = [ ['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'C', 'D'], ['A', 'E', 'F'] ]
visited = {'A', 'B', 'C', 'D', 'E'}
queue = [ ['A', 'B', 'D'], ['A', 'C', 'D'], ['A', 'E', 'F'] ]
visited = {'A', 'B', 'C', 'D', 'E'}
queue = [ ['A', 'C', 'D'], ['A', 'E', 'F'] ]
visited = {'A', 'B', 'C', 'D', 'E'}
queue = [ ['A', 'E', 'F'] ]
visited = {'A', 'B', 'C', 'D', 'E'}
queue = [ ['A', 'E', 'F', 'G'] ]
visited = {'A', 'B', 'C', 'D', 'E', 'F'}
queue = [ ['A', 'E', 'F', 'G', 'H'] ]
visited = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}
...
...
queue = [ ['A', 'E', 'F', 'G', 'H', ..., 'X', 'Y', 'Z'] ]
visited = {'A', 'B', 'C', 'D', 'E', 'F', 'G', ..., 'X', 'Y'}
# at this point the algorithm will pop off the path,
# see that it reaches the goal, and return
这比添加路径要少得多['A', 'B', 'A', 'B', 'A', 'B', ...]
。