【算法】算法图解笔记_广度优先搜索

你常常须要解决最短路径问题(shorterst-path problem)。解决最短路径问题的算法被称为广度优先搜索。广度优先搜索算法最先由Edward F. Moore 1959年在“如何从迷宫中寻找出路”这一问题中提出。node

广度优先搜索让你可以找出两样东西之间的最短距离。使用广度优先搜索能够:python

  1. 编写国际跳棋AI,计算最少走多少步就可获胜;
  2. 编写拼写检查器,计算最少编辑多少个地方就可将错拼的单词改为正确的单词,如将READED改成READER须要编辑一个地方;
  3. 根据你的人际关系网络找到关系最近的医生。

要解决最短路径问题,须要两个步骤。算法

  1. 使用图来创建问题模型。
  2. 使用广度优先搜索解决问题。

图是什么

图用于模拟不一样的东西是如何相连的。图由节点(node)和(edge)组成。一个节点可能与众多节点直接相连,这些节点被称为邻居。树是一种特殊的图,其中没有日后指的边。网络

在图中,边用来表示节点之间的关系,若关系是有方向的,则图为有向图(directed graph),此时图中的边有箭头。若关系没有方向,则图为无向图(undirected graph),此时图中的边没有箭头,直接相连的节点互为邻居。
图片描述
如上图是有向图,Rama是Alex的邻居。数据结构

广度优先搜索

广度优先搜索是一种用于图的查找算法,可帮助回答两类问题。app

  • 第一类问题:从节点A出发,有前往节点B的路径吗?
  • 第二类问题:从节点A出发,前往节点B的哪条路径最短?

两类问题并无本质区别,在实现层面仅仅第二类须要携带路径的信息,由于最终一般须要返回这个路径。spa

示例:假设你经营着一个芒果农场,须要寻找芒果销售商,以便将芒果卖给他。在Facebook,你与芒果销售商有联系吗?为此,你可在朋友中查找。code

算法原理
(1)建立一个朋友名单。
(2)依次检查名单中的每一个人,看看他是不是芒果销售商。
(3)假设你没有朋友是芒果销售商,那么你就必须在朋友的朋友中查找。检查名单中的每一个人时,你都将其朋友加入名单。blog

若找到,则表示你与芒果销售商有联系;因为在广度优先搜索的执行过程当中,搜索范围从起点开始逐渐向外延伸,即先检查一度关系,再检查二度关系,咱们找到的芒果销售商也是关系最近的。队列

执行过程当中,一度关系在二度关系以前加入查找名单,因此咱们优先检查一度关系,而后才到二度,依次进行。这须要存储名单的数据结构有“先进先出”的特性,这种数据结构就是队列(queue)。

队列

相似于栈,队列也是一种操做受限的数据结构,你不能随机地访问队列中的元素。队列只支持两种操做:入队出队
图片描述

队列是一种先进先出(First In First Out,FIFO)的数据结构,而栈是一种后进先出(Last In First Out,LIFO)的数据结构。图片描述

实现图

使用散列表存储每一个节点与邻近节点关系。
图片描述

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"] = []

实现算法

算法的工做原理:
图片描述
一点须要注意:检查一我的以前,要确认以前没检查过他,这很重要,由于有可能会致使无限循环。

完整算法以下:

from collections import deque

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 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 not person 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(V + E),其中V为顶点(vertice)数,E为边数。

请继续关注个人公众号文章
图片描述

相关文章
相关标签/搜索