您的位置:首页 > 其它

《算法图解》第六章广度优先搜索学习心得

2018-03-31 16:50 190 查看
1、图简介
最短路径问题(shorterst-path problem),如前往朋友家的最短路径, 也可能是国际象棋中把对方将死的最少步数。 解决

最短路径问题的算法被称为广度优先搜索 。 解决最短路径问题需要两个步骤:

使用图来创建问题模型。
使用广度优先搜索解决问题。
图仿真一组连接。 图由节点 (node) 和边 (edge)组成。一个节点可能与众多节点直接相连,这些节点被称为邻居 。

有向图 (directedgraph)的关系是单向的。无向图 (undirected graph) 没有箭头, 直接相连的节点互为邻居。



2、广度优先搜索
广度优先搜索解决两类问题:

第一类问题: 从节点A出发, 有前往节点B的路径吗?
第二类问题: 从节点A出发, 前往节点B的哪条路径最短?
广度优先搜索不仅查找从A到B的路径, 而且找到的是最短的路径。
3、队列(queue)队列只支持两种操作: 入队和出队 。队列类似于栈, 你不能随机地访问队列中的元素。队列是一种先进先出 (First In First Out, FIFO) 的数据结构, 而栈是一 种后进先出 (Last In First Out, LIFO) 的数据结构。 如下图



4、算法实现
实现下图,需要用到散列表(python中为字典)



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"] = []你的人际关系网中搜索芒果销售商的算法:def search(name):
#使用函数deque 来创建一个双端队列
from collections import deque
search_queue=deque()#创建一个队列
search_queue += graph["you"]#将你的邻居都加入到这个搜索队列中
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#如果到达了这里, 就说明队列中没人是芒果销售商
#判断一个人是不是芒果销售商
def person_is_seller(name):
'''这个函数检查人的姓名是否以m结尾: 如果是, 他就是芒果销售商。 这种判断方法有点搞笑, 但就这个示例而言是可行的。
'''
return name[-1]=="m"5、运行时间

广度优先搜索的运行时间为O (人数 + 边数), 这通常写作O (V + E ), 其中V 为顶点(vertice) 数, E 为边数。
6、拓扑排序
如果任务A依赖于任务B, 在列表中任务A就必须在任务B后面。 这被称为拓扑排序 , 使用它可根据图创建一个有序列表。 

7、小结

广度优先搜索指出是否有从A到B的路径。
如果有, 广度优先搜索将找出最短路径。
面临类似于寻找最短路径的问题时, 可尝试使用图来创建模型, 再使用广度优先搜索来解决问题。
有向图中的边为箭头, 箭头的方向指定了关系的方向, 例如,rama→adit表示rama欠adit钱。
无向图中的边不带箭头, 其中的关系是双向的, 例如, ross - rachel表示“ross与rachel约会, 而rachel也与ross约会”。
队列是先进先出(FIFO) 的。
栈是后进先出(LIFO) 的。
你需要按加入顺序检查搜索列表中的人, 否则找到的就不是最短路径, 因此搜索列表必须是队列
对于检查过的人, 务必不要再去检查, 否则可能导致无限循环。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息