BFS(广度优先搜索)
广度优先搜索(Breadth First Search,又称宽度优先搜索算法)是最简便的图的搜索算法之一。
这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,
属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
BFS在树的情况下的执行过程
从A出发,搜索A的第二层,发现有B,C,D(一般从左到右搜索),再搜索B的第二层,发现B的第二层没有节点,再搜索C的第二层,发现有E,F,放置于D后面,再搜索D的第二层,发现有G,放置于F后面,再往下搜索E,F,G,发现只有G有第二层H和I,所以最后得到:A B C D E F G H I
BFS在图的情况下的执行过程
我们引入一个queue表示待检索队列;seen表示已经检索的顶点,也就是顶点遍历的顺序。
假设从A顶点出发,
把A从queue弹出,查看A顶点的邻接顶点,发现有B和C,因此把B和C,压入queue中,最后将A顶点放入seen中,表示A顶点我们检索过了;
把B从queue弹出,查看B顶点的邻接顶点,发现有A、D和C,因此把A、D和C,压入queue中,但是,因为queue中有C,seen中有A,因此只压入D,最后将B顶点放入seen中,表示B顶点我们检索过了;
把C从queue弹出,查看C顶点的邻接顶点,发现有A、B、D和E,因此把A、B、D和E,压入queue中,但是,因为queue中有D,seen中有A、B,因此只压入E,最后将B顶点放入seen中,表示C顶点我们检索过了;
...依次类推,所以最后得到:A B C D E F
注意:不同的起始点的路径不同
实现代码
# 用字典的映射图
graph = {
'A': ['B', 'C'],
'B': ['A', 'C', 'D'],
'C': ['A', 'B', 'D', 'E'],
'D': ['B', 'C', 'E', 'F'],
'E': ['C', 'D'],
'F': ['D']
}
# input一个graph和起始点star
def BFS(graph, star):
# 创建队列,用于存放 【待检查的顶点】
queue = []
# 将起始点s放入队列,假设起始点为‘A’
queue.append(star)
# set():创建一个无序不重复元素集,删除重复数据
seen = set()
# 'A'我们检索过,放入seen
seen.add(star)
# 当队列不是空的时候
while len(queue) > 0:
# 将队列的第一个元素读出来,即‘A’顶点
vertex = queue.pop(0)
# graph['A']就是A的相邻点:['B','C'],将其储存到nodes
nodes = graph[vertex]
# 遍历nodes中的元素,即遍历A的邻接顶点['B','C']
for next in nodes:
if next not in seen: # 如果 w 没有被检索过,待检索,即不在seen中
queue.append(next) # 把接下来待检索的顶点压入queue中
seen.add(next) # 加入seen表示w我们看见过了
print("BFS 此时,queue:{},seen:{}, 当前遍历的顶点是:{}".format(queue, seen, vertex))
if __name__ == '__main__':
BFS(graph, 'A')
输出:
BFS 此时,queue:['B', 'C'],seen:{'B', 'A', 'C'}, 当前遍历的顶点是:A
BFS 此时,queue:['C', 'D'],seen:{'D', 'B', 'A', 'C'}, 当前遍历的顶点是:B
BFS 此时,queue:['D', 'E'],seen:{'B', 'C', 'E', 'A', 'D'}, 当前遍历的顶点是:C
BFS 此时,queue:['E', 'F'],seen:{'B', 'C', 'E', 'F', 'A', 'D'}, 当前遍历的顶点是:D
BFS 此时,queue:['F'],seen:{'B', 'C', 'E', 'F', 'A', 'D'}, 当前遍历的顶点是:E
BFS 此时,queue:[],seen:{'B', 'C', 'E', 'F', 'A', 'D'}, 当前遍历的顶点是:F
参考:
[1]https://blog.csdn.net/Huangkaihong/article/details/106131950