本章内容:
- 学习使用心得数据结构-图,来创建网络模型
- 学习广度优先搜索,使用图这种算法回答“到X的最短路径是什么的问题”
- 学习有向图和无向图
- 学习拓扑排序,这种排序算法指出了节点之间的依赖关系
6.1图简介
图有节点和边组成。如下图:
6.3广度优先算法
6.3.1查找最短路径
广度优先算法回答两类问题:
1、从节点A出发,有前往节点B的路径么?(在你的朋友中找芒果销售商)
2、从节点A出发,前往节点B的那条路径最短?(哪个销售商与你的关系最近)
注意:只有按条件顺序查找时,才能实现这样的目的。否则,查找到的结果并非是最近的。队列(queue)就是这样的数据结构。
6.3.2队列
队列只支持两种操作:入队和出队。
6.4实现图
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"] = []
有向图(directed graph):有箭头,关系是单向的
无向图(undirected graph):无箭头,直接相连的节点互为邻居
如下二图是等价的:
6.5实现算法
from collections import deque def person_is_seller(name): return name[-1] == 'm' #last element is m. 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): search_queue = deque() search_queue += graph[name] # This array is how you keep track of which people you've searched before. searched = [] while search_queue: person = search_queue.popleft() print person # Only search this person if you haven't already searched them. if not person in searched: if person_is_seller(person): print person + " is a mango seller!" return True else: search_queue += graph[person] # Marks this person as searched searched.append(person) else: print "skip repeatedly " + person #peggy is repeatedly return False search("you")
运行时间:广度优先搜索的运行时间为O(V+E),其中V为定点(vertice)数,E为边数。
另,树是一种特殊的图,其边是单向的。
6.6小结
- 广度优先算法之处是否有从A到B的路径
- 如果有,广度优先搜索将找出最短路径
- 如果面临类似于寻找最短路径的问题,可尝试用图来创建模型,再用广度优先搜索来解决问题
- 有向图的边为箭头,箭头的方向制定了关系的方向,如,你->我,代表你欠我钱。
- 无向图的边有箭头,关系是双向的,如你和我约会,等同我和你约会
- 队列是FIFO
- 栈是LIFO
- 搜索列表必须是有序的,否则找不到最短路径
- 检查过的,务必不要再检查,否则可能导致无限循环
广度优先算法的C语言实现: