图算法——广度优先搜索 (breadth-first search,BFS)。广度优先搜索让你能够找出两样东西之间的最短距离。
图
你经常要找出最短路径
,这可能是前往朋友家的最短路径,也可能是国际象棋中把对方将死的最少步数。解决最短路径问题的算法被称为广度优先搜索
。
图是什么?
图由节点和边组成。一个节点(node)可能与众多节点(edge)直接相连,这些节点被称为邻居
图
广度优先搜索可回答两类问题。
第一类问题:从节点A出发,有前往节点B的路径吗?
第二类问题:从节点A出发,前往节点B的哪条路径最短?
在你看来,一度关系胜过二度关系,二度关系胜过三度关系,以此类推。因此,你应先在一度关系中搜索,确定其中没有芒果销售商后,才在二度关系中搜索。广度优先搜索就是这样做的!在广度优先搜索的执行过程中,搜索范围从起点开始逐渐向外延伸,即先检查一度关系,再检查二度关系。
队列
队列只支持两种操作:入队 和出队 。
队列是一种先进先出 (First In First Out,FIFO)的数据结构
实现图
首先,需要使用代码来实现图。图由多个节点组成。
的一种结构让你能够表示这种关系,它就是散列表 !
散列表让你能够将键映射到值。在这里,你要将节点映射到其所有邻居。
graph = {}
graph["you"] = ["alice", "bob", "claire"]
graph["bob"] = ["anuj", "peggy"]
graph["alice"] = ["peggy"]
graph["claire"] = ["thom", "jonny"]
graph["anuj"] = []
graph["peggy"] = []
graph["thom"] = []
graph["jonny"] = []
散列表是无序的,因此添加键—值对的顺序无关紧要
无向图
(undirected graph)没有箭头,直接相连的节点互为邻居。
实现算法
def search(name):
search_queue = deque()
search_queue += graph[name]
searched = [] # 这个数组用于记录检查过的人
while search_queue:
person = search_queue.popleft()
if person not in searched:
# 仅当这个人没检查过时才检查
if person_is_seller(person):
print person +" is a mango seller!"
return True
else:
search_queue += graph[person]
searched.append(person) # 将这个人标记为检查过
return False search("you")
,广度优先搜索的运行时间为O (人数 + 边数),这通常写作O (V + E ),其中V 为顶点(vertice)数,E 为边数。
拓扑排序
如果任务A依赖于任务B,在列表中任务A就必须在任务B后面。这被称为拓扑排序。