图
什么是图?
图由节点和边组成。一个节点可能与众多节点直接相连,这些节点也被称为邻居。
图用于模拟一组连接。
例如从双子峰到金门大桥的出行路线图:
由上面这个图,我们要找出从双子峰到金门大桥的最短换乘路线,这个问题被称为最短路径问题,而解决最短路径问题的算法被称为广度优先搜索。
广度优先搜索
广度优先搜索是一种用于图的查找算法。
它可用于解决两类问题:
1、从某节点出发,有去往下一节点的路径吗?
2、从某节点出发,前往下一节点的哪条路径最短?
想要实现广度优先搜索首先我们要解决优先顺序的实现问题,很显然,在这里使用队列是很明智的选择。
然后我们需要实现图,图由多个节点组成,很显然,在这里我们可以使用散列表去表示图的关系,将节点映射到其所有的邻居。
运行时间
将一个元素添加到队列需要的时间是固定的,为O(1),因此对每个元素都这样做需要的总时间为O(元素个数),在图里面从一个节点到另一个节点需要的时间是O(边数)。所以广度优先搜索的运行时间为O(元素个数 + 边数),这通常写作O(V + E),其中V为顶点数,E为边数。
树是一种特殊的图,其中没有往后指的边。
代码
这里以经营芒果农场需要将芒果卖给芒果销售商为例,我们需要通过Facebook去查找芒果销售商:
# 首先创建表示人际关系的图
graph = {}
graph['you'] = ['alice', 'bob', 'claire']
graph['bob'] = ['angel', 'peggy']
graph['alice'] = ['peggy']
graph['claire'] = ['tom', 'jonny']
graph['angel'] = []
graph['peggy'] = []
graph['tom'] = []
graph['jonny'] = []
# 然后创建一个队列,我们可以使用双端队列deque
from collections import deque
def search_mango(name):
search_queue = deque()
# 将‘你’的邻居都加入到这个搜索队列中
search_queue += graph['you']
# 创建一个数组用于记录检查过的人
searched = []
# 只要队列不为空,就取出其中的第一个人
while search_queue:
person = search_queue.popleft()
# 检查这个人是否是芒果销售商,函数person_is_seller可以自己尝试去实现一下
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')