一、广度优先搜索(breadth-first search)(寻找最短路径问题)
前往朋友家的最短路径?象棋中走最少步数获胜?人际网络中关系最近的摄影师?
最近3步从双子峰到金门大桥。
二、图的概念:节点和边
三、有路径否?哪条路径最短?
人际网络:
在广度优先搜索的执行过程中,搜索范围从起点开始逐渐向外延伸,即先检查一度关系,再检查二度关系。且按照顺序添加到队列中。
也就是说,一级关系先入队列,二级关系后入队列,但同一层级顺序可随意安排。但要避免重复。
四、算法实现
1.创建一个队列,用于存储要检查的人(一级);
2.从队列中弹出一个人,检查是否符合条件;
3.符合,大功告成,退出;
4.不符合,将这个人的所有邻居加入队列(二级);
5.回到第2步;
6.如果队列为空,说明你的关系网中没有符合条件的人。
1 from collections import deque 2 3 graph = {} 4 graph["you"] = ["alice","bob","claire"] 5 graph["alice"] = ["peggy"] 6 graph["bob"] = ["anuj","peggy"] 7 graph["claire"] = ["thom","jonny"] 8 graph["anuj"] = [] 9 graph["peggy"] = [] 10 graph["thom"] = [] 11 graph["jonny"] = [] 12 13 def search(name): 14 search_queue = deque() #创建一个队列 15 search_queue += graph[name] #添加你的邻居到搜索队列 16 searched = [] #用于记录检查过的人 17 18 while search_queue: #只要队列不空 19 person = search_queue.popleft() #取出第一个人 20 if not person in searched: #仅当这个人没有被检查过时才检查 21 if person_is_seller(person): #检查是否符合要求 22 print(person,"is a mango seller!") 23 return True 24 else: 25 search_queue += graph[person] #不符合要求,将这个人的朋友加入搜索队列 26 searched.append(person) 27 return False 28 29 def person_is_seller(name): 30 return name[-1] == "m" #条件假如是名字最后一个字母是m 31 32 search("you")
thom is a mango seller! Out[5]: True
判断过的应当记录并且下次不再检查,否则会陷入死循环。
广度优先搜索的运行时间为O(顶点数+边数)=O(V+E)
注意:
1.你需要按加入顺序检查搜索列表中的人,否则找到的就不是最短路径,因此搜索列表必须是队列。
2.对于检查过的人,务必不要再去检查,否则可能导致死循环。