广度优先搜索是一种用于图查找算法,可帮助回答两类问题?
第一类问题:从节点A出发,有前往节点B的路径吗? 第二类问题:从节点A出发,前往节点B的哪条路径最短? 2、举例假设M经营一个鱼塘,需要找销售商,以便卖掉养好的鱼。这时,M联系销售商有两种方式:
1、通过M的通讯录联系,看是否有销售商。 2、通过M的通讯录联系朋友,是否有销售方的联系方式。假设,M的通讯录有A,B,C的联系方式,A有M,N,G的联系方式,B有M,N的联系方式,C有M,P,K的联系方式。
M | A, B, C |
---|---|
A | M, N, G |
B | M, N |
C | M, P, K |
那此时M怎么找到销售商呢?(假设K是销售商)
假设,朋友是一度关系,朋友的朋友是二度关系。
对于M来说,M将在一度关系查找,再到二度关系中查找,因此这样找到的是关系最近的销售商。对于广度优先遍历不仅能查找从A到B的路径还能找到最短路径。 使用广度优先搜索再好不过了。为了能够顺序一一检查是否为销售商,有一种数据结构可以解决这个问题——队列。队列是一种先进先出的数据结构,而栈是一种后进先出的数据结构。
散列表能能映射人与人之间的关系,且查找速率快,并且是无序的,不用考虑你的通讯录中先查验谁。散列表可以参考:散列表,表示这种映射关系的Python代码如下:
graph = {}
graph['M'] = ['A','B','C']
graph['A'] = ['M', 'N', 'G']
graph['B'] = ['M', 'N']
graph['C'] = ['M', 'P', 'K']
graph['N'] = []
graph['G'] = []
graph['P'] = []
graph['K'] = []
由此看出人与人之间的映射关系构建了一个有向图,人是节点,映射关系是边。
算法实现:from collections import deque
graph = {}
graph['M'] = ['A','B','C']
graph['A'] = ['M', 'N', 'G']
graph['B'] = ['M', 'N']
graph['C'] = ['M', 'P', 'K']
graph['N'] = []
graph['G'] = []
graph['P'] = []
graph['K'] = []
#以上内容也可以使用字典存放
def person_is_seller(person):
return person == 'K'
def search(name):
search_queue = deque() #创建一个队列
search_queue += graph[name] #将name的邻居都加入到这个搜索队列中
searched = [] #用于记录已经检查过的人
while search_queue:
person = search_queue.popleft() #取出其中第一个人
if person not in searched:
if person_is_seller(person):
print(person,'是销售者')
return True
else:
search_queue += graph[person]
searched.append(person) # 将这个人标记为检查过
return False
if __name__ == '__main__':
search('M')
算法的运行时间到底是一个什么量级呢?
通过整个人际关系网中搜索销售商,就意味着将沿着每条边前行,因此运行时间最少为O(边数),除此之外,还使用了一个队列,其中包含要检查的每个人。将一个人添加到队列的时间是固定的,即为O(1),因此对每个人都是这样做需要的总时间为O(人数),所以广度优先搜索的运行时间为O(人数+边数)O(人数+边数)O(人数+边数),通常写作O(V+E)O(V+E)O(V+E),其中V为顶点数,E为边数。
补充词汇:拓扑排序,可以这么理解如果任务A依赖任务B,在列表中A就必须在任务B前面。