搜索算法 BFS (python实现)
一、综述
遍历算法中最基础的就是 BFS 和 DFS 算法。本文将使用python,介绍BFS的中心思想和代码实现。后续将介绍各种遍历算法。
二、BFS
1.实现过程
BFS又称广度优先搜索,顾名思义,就是搜索注重广度。
例如下图:
假设有一只鹰在起始点A,“他”视野宽广,雄姿英发,正准备去寻找一只雌鸟喜结连理。但是雌鸟太胖飞不动,深藏草丛之中,所以它只能找遍所有的地方。这只鸟,每前进一次,就会将与他所在地相连的所有的地方全部找完。这里用涂色来代表他遍历的顺序。·
下面我们深入分析一下其中的实现过程,这里我引用“queue(队)”这个概念,队讲究先来后到,所以第一个排队的也就第一个出来。即先进先出原则。
对于上图,以下是具体实现过程
- 让A排进队中
- 与A相连的B,C,D排进队中
- 与B,C,D 其中一点相连的元素放入队中
(例如选择D,与D相连的则是E点) - 与B,C点的相连的元素放入队中。
- 以此类推…直到找到他的新娘,或者队中没有元素(那么这是只孤鹰)
产生的队列就是这样----
A-B-C-D-E-F
由以上步骤可知,BFS的遍历是多种多样的。
2.代码实现
(1)遍历全图
graph = {'A':['B','C'],
'B':['D','A'],
'D':['B','C'],
'C':['D','E','A'],
'E':['D','C','F'],
'F':['E']}
#首先使用字典创建一个图
def BFS(graph,start):#函数以图和起点作为变量
queue = [start]#起点首先排进队列
alreadyTraverse = {start}#年轻的鹰的记性好,不会走相同的地方
while (len(queue)>0):#不断遍历直到队中没有元素
node=queue.pop(0)#取出队中的一个元素
print(node)
for neighbour in graph[node]:#对于选中元素的所有邻居进行遍历
if neighbour not in alreadyTraverse:#集合在python中是hashing判断快
alreadyTraverse.add(neighbour)
queue.append(neighbour)#继续排队
print(node)
(2) 找到最短路径(假设全部路径长度一样)
graph = {'A':['B','C'],
'B':['D','A'],
'D':['B','C'],
'C':['D','E','A'],
'E':['D','C','F'],
'F':['E']}
#首先使用字典创建一个图
def BFS(graph,start,end):#函数以图和起点以及中点作为变量
queue = [[start,[start]]]#起点首先排进队列,这里加入一个列表进行记录路径
alreadyTraverse = {start}#年轻的鹰的记性好,不会走相同的地方
while (len(queue)>0):#不断遍历直到队中没有元素
node,path=queue.pop(0)#取出队中的一个元素,分别赋给节点和路径
for neighbour in graph[node]:#对于选中元素的所有邻居进行遍历
if neighbour not in alreadyTraverse:#集合在python中是hashing判断速度快
alreadyTraverse.add(neighbour)
queue.append([neighbour,path+[neighbour]])#继续排队
if neighbour == end:
return path+[neighbour]
(3)找到全部路径
graph = {'A':['B','C'],
'B':['D','A'],
'D':['B','C'],
'C':['D','E','A'],
'E':['D','C','F'],
'F':['E']}
def BFS(graph,start,end):#函数以图和起点以及中点作为变量
queue = [[start,[start]]]#起点首先排进队列,这里加入一个列表进行记录路径
alreadyTraverse = {start}#年轻的鹰的记性好,不会走相同的地方
allPath=[]#这个列表进行记录
while (len(queue)>0):#不断遍历直到队中没有元素
node,path=queue.pop(0)#取出队中的一个元素,分别赋给节点和路径
for neighbour in graph[node]:#对于选中元素的所有邻居进行遍历
if neighbour not in alreadyTraverse:#集合在python中是hashing判断速度快
alreadyTraverse.add(neighbour)
queue.append([neighbour,path+[neighbour]])#继续排队
if neighbour == end:
allPath.append(path+[neighbour])#找到之后不停止
return allPath
(4)找路径(方法二)
除了使用以上方法还可以建立一棵树进行倒序查找,从目标节点不断地寻找父节点。
graph = {'A':['B','C'],
'B':['D','A'],
'D':['B','C'],
'C':['D','E','A'],
'E':['D','C','F'],
'F':['E']}
#首先使用字典创建一个图
def BFS(graph,start):#函数以图和起点作为变量
queue = [start]#起点首先排进队列
alreadyTraverse = {start}#年轻的鹰的记性好,不会走相同的地方
parent={}#记录每一个节点的父节点
while (len(queue)>0):#不断遍历直到队中没有元素
node=queue.pop(0)#取出队中的一个元素
for neighbour in graph[node]:#对于选中元素的所有邻居进行遍历
if neighbour not in alreadyTraverse:#集合在python中是hashing判断快
parent[neighbour]=node
alreadyTraverse.add(neighbour)
queue.append(neighbour)#继续排队
return parent
def allPath(parent,start,end):
path=[]
while (start != end) :#使用while循环不断地找到end前面的元素
path.append(end)
end = parent[end]
print(path)
path+=[start]
path.reverse()#由于是倒序查找所以需要倒序排列
return path