图解算法(六)
广度优先搜索
1.图简介
我们在生活中经常要解决最短路径问题,解决最短路径问题的算法被称为广度优先搜索。
要确定如何从西直门到东直门,需要两个步骤:
- 使用图来建立问题模型
- 使用广度优先搜索解决问题
2.图是什么
图模拟一组连接。例如,假设你与朋友玩牌,并要模拟谁欠谁钱,可用图来表示
图由节点和边组成。一个节点可能与众多节点直接相连,这些节点被称为邻居。
图用于模拟不同的东西是如何相连的。
3.广度优先搜索
广度优先搜索是一种用于图的查找算法,可帮助回答两类问题。
- 第一类:从节点A出发,有前往节点B的路径吗?
- 第二类:从节点A出发,前往节点B的哪条路径最短?
假设你经营着一个芒果农场,需要寻找芒果销售商,以便将芒果卖给他。为此,你可以在朋友中查找。首先创建一个朋友名单。然后,依次检查名单中的每个人,看看他是否是芒果销售商。假设你没有朋友是芒果销售商,那么你就必须在朋友的朋友中查找。这样一来,你不仅在朋友中查找,还在朋友的朋友等中查找。使用这种算法将搜遍你的整个人际关系网,直到找到芒果销售商。这就是广度优先搜索算法。
3.1 查找最短路径
在广度优先搜索的执行过程中,搜索范围从起点开始逐渐向外延伸,即先检查一度关系,再检查二度关系,你按顺序一次检查名单中的每个人,看看他是否是芒果经销商。广度优先搜索不仅查找从A到B的路径,而且找到的是最短的路径。
注意,只有按添加的顺序查找时,才能实现这样的目的。有一个可以实现这种目的的数据结构,那就是队列(queue)。
3.2 队列
队列的工作原理与现实生活中的队列完全相同。假设你与朋友一起在公交站排队,如果你排在他的前面,你将先上车。队列类似于栈,不能随机的访问队列中的元素。队列只支持两种操作:入队和出队。
队列是一种先进先出的数据结构,而栈是一种后进先出的数据结构。
4.实现图
首先,需要使用代码来实现图。图有多个节点组成。
每个节点都与邻近节点相连,如何表示“你->邻近点”这样的关系呢,使用散列表。
graph = {} graph["you"] = ["alice","bob","claire"]
注意,“you”被映射到一个数组,因此graph["you"]是一个数组,其中包含了“you”的所有邻近点。
进而拓展更大的图
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"] = []
5.实现算法
首先,创建一个队列。在Python中,可使用函数deque来创建一个双端队列。
from collections import deque search_queue = deque() search_queue += graph["you"]
while search_queue: person = search_queue.popleft() if person_is_seller(person): print person + " is a mango seller!" return True else: search_queue += graph[person] return False def person_is_seller(name): return name[-1] == 'm'
最终代码
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")