广度优先搜索主要解决两个方面的问题:
- 存不存在路径的问题(例如,从A点是否可以达到B点)
- 无权重的最短路径问题(例如,从A点到B点的最短路径)
Graph Data Structure的表示
上面这种图可以用Python表示为:
# sample graph implemented as a dictionary
graph = {'A': ['B', 'C', 'E'],
'B': ['A','D', 'E'],
'C': ['A', 'F', 'G'],
'D': ['B'],
'E': ['A', 'B','D'],
'F': ['C'],
'G': ['C']}
FIFO队列
BFS分层
类似通讯录一样,BFS搜索最短路径时,是按层级进行检索
先解决存不存在的问题
# -*- coding:utf-8 -*-
# TODO: 解决路径显示的问题
# deque函数用来创建一个双端队列
from collections import deque
# -----------------
# 使用字典来表示图
# graph = {}
# key 代表当前节点标识(例如可以是反映名字的string)
# value 代表与该节点相关的下一层节点列表
# Example:
# graph = [1:[4,2],2:[3,4],3:[4],4:[5],5:[]]
def BFS_Search(graph,startNode,stopNode):
# 创建一个待处理节点的队列
search_queue = deque()
# 将起始节点的下一层节点加入到待处理队列中
search_queue += graph[startNode]
# 创建一个检索过的列表,避免出现节点间的相互添加
searched = [startNode]
# 当队列不为空时
while search_queue:
# 从队列中取出要处理的节点
currentNode = search_queue.popleft()
# 保证只对未处理过的节点进行判断
# Ex: A的下一层包含B,B的下一层又包含A
if currentNode not in searched:
# 这里写具体的终止条件
# if 满足终止条件后return True
if currentNode == stopNode:
searched.append(stopNode)
return True
else:
# else如果当前节点没有满足终止条件
# 则将当前节点的下一层节点加到队列尾部
search_queue += graph[currentNode]
# 将检查过的节点加入到searched列表中
searched.append(currentNode)
return False
# Example One 从你身边的人脉网中找一个叫Tom的人
graph = {}
graph["Sprinkle"] = ["Alice","Claire","Bob"]
graph["Claire"]=["Sprinkle"]
graph["Alice"] = ["Peggy"]
graph["Bob"] = ["Sprinkle","Peggy","Tom"]
graph["Peggy"] =[]
graph["Tom"] = []
searched = BFS_Search(graph, "Sprinkle","Tom")
print(searched)
再解决最短路径的问题
# -*- coding:utf-8 -*-
# TODO: 解决路径显示的问题
# deque函数用来创建一个双端队列
from collections import deque
# -----------------
# 使用字典来表示图
# graph = {}
# key 代表当前节点标识(例如可以是反映名字的string)
# value 代表与该节点相关的下一层节点列表
# Example:
# graph = [1:[4,2],2:[3,4],3:[4],4:[5],5:[]]
def BFS_Search(graph,startNode,stopNode):
# 创建一个待处理节点的队列
search_queue = deque()
# 将起始节点的下一层节点加入到待处理队列中
search_queue += graph[startNode]
# 创建一个检索过的列表,避免出现节点间的相互添加
searched = [startNode]
# 当队列不为空时
while search_queue:
# 从队列中取出要处理的节点
currentNode = search_queue.popleft()
# 保证只对未处理过的节点进行判断
# Ex: A的下一层包含B,B的下一层又包含A
if currentNode not in searched:
# 这里写具体的终止条件
# if 满足终止条件后return True
if currentNode == stopNode:
searched.append(stopNode)
return searched
else:
# else如果当前节点没有满足终止条件
# 则将当前节点的下一层节点加到队列尾部
search_queue += graph[currentNode]
# 将检查过的节点加入到searched列表中
searched.append(currentNode)
return False
def BFS_ShortestPath(graph,startNode,stopNode):
searched = BFS_Search(graph,startNode,stopNode)
path = [stopNode]
# 当起始节点与目标节点不同时
while stopNode != startNode:
# 对检索过的节点进行遍历
for node in searched:
# 先找包含了目标节点的上一级节点
if stopNode in graph[node]:
# 将上一级节点加到stopNode之前
path.insert(0, stopNode)
# 将目标节点更换为node
stopNode = node
break
return path
# Example One 从你身边的人脉网中找一个叫Tom的人
graph = {}
graph["Sprinkle"] = ["Alice","Claire","Bob"]
graph["Claire"]=["Sprinkle"]
graph["Alice"] = ["Peggy"]
graph["Bob"] = ["Sprinkle","Peggy","Tom"]
graph["Peggy"] =[]
graph["Tom"] = []
path = BFS_ShortestPath(graph,"Sprinkle","Tom")
print(path)
举个例子
< Python Breath First Search Maze solving program > 未完,挖坑再补