#描述
双向BFS(Bidirectional Breadth-First Search)是一种在图中寻找最短路径的算法,与传统的单向BFS不同的是,双向BFS从起点和终点同时开始搜索,直到它们的搜索路径相遇为止。是一种比较便捷的搜素方式,可以显著减少搜索空间,提高搜索效率。但是如果两个搜索路径没有相遇,则这样的搜索方式要比传统的BFS的搜索效率减少两倍。
#代码详解
from collections import deque
deque是python库函数中collections的一个模块。deque是一个双向可操作队列,就是是因为与普通队列相比,他不仅仅只能够实现“先入先出(FIFO)",他也能够实现”后入先出“这一功能。例如:I=deque(),则I.pop()#默认弹出队列后端元素,I.leftpop()可弹出队列最前端top元素。
def bidirectional_bfs(graph,start,end):
if start == end:
return [start]
定义一个函数bidirectional_bfs,接受三个参数:graph表示图的邻接列表表示法,start表示起始节点,end表示目标节点。如果起始节点和目标节点相同,直接返回包含起始节点的列表作为路径。
start_queue = deque([(start,[start])])
end_queue = deque([(end,[end])])
start_visited = set([start])
end_visited = set([end])
初始化起始节点和目标节点的队列、已访问节点集合:start_queue = deque([(start, [start])]): 起始节点队列,元素为起始节点和从起始节点到该节点的路径。 end_queue = deque([(end, [end])]): 目标节点队列,元素为目标节点和从目标节点到该节点的路径。 start_visited = set([start]): 起始节点已访问集合,用于记录已经访问过的节点。 end_visited = set([end]): 目标节点已访问集合,用于记录已经访问过的节点。
while start_queue and end_queue:
start_node, start_path = start_queue.popleft()
end_node, end_path = end_queue.popleft()
从当起始节点队列和目标节点队列都不为空时,继续搜索,并且弹出起始节点队列(start)和目标节点队列(end)中的第一个节点和路径。
neighbors=graph[start_node]
for neighbor in neighbors:
if neighbor not in start_visited:
new_path=start_path+[neighbor]
if neighbor in end_visited:
return new_path + end_path[::-1]
start_queue.append((neighbor,new_path))
start_visited.add(neighbor)
neighbors=graph[end_node]
for neighbor in neighbors:
if neighbor not in end_visited:
new_path=end_path+[neighbor]
if neighbor in start_visited:
return new_path + start_path[::-1]
end_queue.append((neighbor,new_path))
end_visited.add(neighbor)
return None
遍历起始节点和目标节点的邻居节点,如果邻居节点未被访问过,更新路径并检查是否相遇,如果邻居节点在目标节点已访问集合中,返回路径连接两个方向的路径,否则将邻居节点加入队列和已访问集合。如果未找到路径,返回None。 这段代码的主要逻辑是利用双向BFS算法同时从起始节点和目标节点开始搜索,直到两个搜索方向相遇,找到最短路径。您可以根据需要修改图的结构和起始/目标节点,然后调用这个函数来查找最短路径。
#完整代码
from collections import deque
def bidirectional_bfs(graph,start,end):
if start == end:
return [start]
start_queue = deque([(start,[start])])
end_queue = deque([(end,[end])])
start_visited = set([start])
end_visited = set([end])
while start_queue and end_queue:
start_node, start_path = start_queue.popleft()
end_node, end_path = end_queue.popleft()
neighbors=graph[start_node]
for neighbor in neighbors:
if neighbor not in start_visited:
new_path=start_path+[neighbor]
if neighbor in end_visited:
return new_path + end_path[::-1]
start_queue.append((neighbor,new_path))
start_visited.add(neighbor)
neighbors=graph[end_node]
for neighbor in neighbors:
if neighbor not in end_visited:
new_path=end_path+[neighbor]
if neighbor in start_visited:
return new_path + start_path[::-1]
end_queue.append((neighbor,new_path))
end_visited.add(neighbor)
return None
#执行和结果
graph={
'A':['B','C'],
'B':['A','D','E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
定义一个字典。
结果:
start='A'
end='E'
result=bidirectional_bfs(graph,start,end)
print(result)
['E', 'B', 'A']