算法图解(四)

一、广度优先搜索(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.对于检查过的人,务必不要再去检查,否则可能导致死循环。

原文地址:https://www.cnblogs.com/direwolf22/p/12681896.html