【算法】广度优先搜索

广度优先搜索(breadth first search)

最短路径问题(shorterst-path problem)

解决最短路径问题的算法被称为广度优先搜索

最短路径问题解决步骤

(1) 使用来建立问题模型。

(2) 使用广度优先搜索解决问题。

图的定义

图模拟一组连接。

图由节点(node)和(edge)组成。一个节点可能与众多节点直接相连,这些节点被称为邻居。图用于模拟不同的东西是如何相连的

广度优先搜索

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

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

在广度优先搜索的执行过程中,搜索范围从起点开始逐渐向外延伸,即先检查一度关系,再检查二度关系。

广度优先搜索不仅查找从A到B的路径,而且找到的是最短的路径。

队列

需要按添加顺序进行检查。可以用队列来实现这种目的

队列类似于栈,不能随机地访问队列中的元素。

队列只支持两种操作:入队出队

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

实现图

使用散列表将键映射到值,用来实现图

示例:

>>> graph={}
>>> graph['you']=['alice','bob','claire']
>>> graph
{'you': ['alice', 'bob', 'claire']}
>>> graph['bob']=['anuj','peggy']
>>> graph['alice']=['peggy']
>>> graph['claire']=['thom','jonny']
>>> graph['anuj']=[]
>>> graph['peggy']=[]
>>> graph['thom']=[]
>>> graph['jonny']=[]
>>> graph
{'you': ['alice', 'bob', 'claire'], 'bob': ['anuj', 'peggy'], 'alice': ['peggy'], 'claire': ['thom', 'jonny'], 'anuj': [], 'peggy': [], 'thom': [], 'jonny': []}

  

键—值对的添加顺序不重要,因为散列表是无序的。

有向图(directed graph)

其中的关系是单向

无向图(undirected graph)

没有箭头,直接相连的节点互为邻居

实现算法

代码

from collections import deque  #使用函数deque来创建一个双端队列
graph={'you': ['alice', 'bob', 'claire'], 'bob': ['anuj', 'peggy'], 'alice': ['peggy'], 'claire': ['thom', 'jonny'], 'anuj': [], 'peggy': [], 'thom': [], 'jonny': []}
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

def person_is_seller(name):
    return name[-1]=='m'

search('you')

  

原理

  1. 创建一个队列,用于存储要检查的元素
  2. 从队列弹出第一个元素
  3. 检查这个元素,是否满足要求。
  4. 如果满足返回结果,否则将这个元素的所有邻居加入队列
  5. 回到第二步。继续检查这些邻居。
  6. 如果队列为空,就说明没有满足条件的元素

停止条件(满足其一):

  •   找到一个满足条件的元素
  •   队列变成空的,这意味队列的所有元素,都没有满足条件

运行时间

广度优先搜索的运行时间为O(V + E),其中V为顶点(vertice)数,E为边数

解析:

在整个图中搜索元素,就意味着将沿每条边前行(记住,边是从一个人到另一个人的箭头或连接),因此运行时间至少为O(边数)。

还使用了一个队列,其中包含要检查的每个元素。将一元素添加到队列需要的时间是固定的,

即为O(1),因此对每个元素都这样做需要的总时间为O(元素个数)。

扩展

  1. 是一种特殊的图,其中没有往后指的边。
  2. 如果任务A依赖于任务B,在列表中任务A就必须在任务B后面。这被称为拓扑排序,使用它可根据图创建一个有序列表。

小结

  •   广度优先搜索指出是否有从A到B的路径。
  •   如果有,广度优先搜索将找出最短路径。
  •   面临类似于寻找最短路径的问题时,可尝试使用图来建立模型再使用广度优先搜索解决问题。
  •   有向图中的边为箭头,箭头的方向指定了关系的方向,例如, rama→adit表示rama欠adit钱。
  •   无向图中的边不带箭头,其中的关系是双向的,例如, ross - rachel表示“ross与rachel约会,而rachel也与ross约会”。
  •   队列是先进先出( FIFO)的。
  •   栈是后进先出( LIFO)的。
  •   需要按加入顺序检查搜索列表中的元素,否则找到的就不是最短路径,因此搜索列表必须是队列
  •   对于检查过的元素,务必不要再去检查否则可能导致无限循环
原文地址:https://www.cnblogs.com/lilip/p/9541328.html