【算法】广度优先搜索

广度优先搜索(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

时间: 2024-10-03 01:52:03

【算法】广度优先搜索的相关文章

基础算法(三)——广度优先搜索

广度优先搜索(Breadth First Search),是很多重要的图的算法的原型. 重要的作用:遍历.对于图的遍历,一般有以下的基本思想: ①从图中某个顶点V0出发,并访问此顶点: ②从V0出发,访问V0的各个未曾访问的邻接点W1,W2,-,Wk;然后,依此从W1,W2,-,Wk 出发访问各自未被访问的邻接点. ③重复②,直到全部顶点都被访问为止. [例]如图1-7,按照广度优先搜索的思想遍历这张图. 正确的方法应该是: [例]编写"连连看"的简单程序 规则是:相连不超过两个弯的相

【算法导论】--C++实现广度优先搜索bfs

一.题目 根据上次随机生成的100个顶点的无向图和有向图,对其进行广度优先搜索. 二.理解广度优先搜索 广度优先搜索可以将其想象成水滴落入水面溅起了的一圈一圈的涟漪,是由一个起始点开始一圈一圈进行扩散搜索的. [课上老师是这样说的,大家想象一下,发现其实非常形象] 广度优先搜索总是从一个起始点出发,首先扩散这个点周围所有的邻居,然后邻居在去扩散邻居的邻居(*^-^*)...然后一直到最后将整张图都扩散完. 三.代码实现 对于第一次随机生成100个顶点的图进行了细节的修改,将每个顶点的类型改为了自

十大基础实用算法之深度优先搜索和广度优先搜索

深度优先搜索算法(Depth-First-Search),是搜索算法的一种.它沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点.这一过程一直进行到已发现从源节点可达的所有节点为止.如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止.DFS属于盲目搜索. 深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓扑排序表,利用拓扑排序表可以方便的解决很多相

广度优先搜索(BreadthFirstSearch)& 迪克斯特拉算法 (Dijkstra's algorithm)

BFS可回答两类问题: 1.从节点A出发,有前往节点B的路径吗? 2.从节点A出发,前往节点B的哪条路径经过的节点最少? BFS中会用到“队列”的概念.队列是一种先进先出(FIFO, first in first out)的数据结构,与栈不同,栈是后进先出(LIFO, last in first out)的数据结构. 还会用到“字典”的概念.字典在现在很多语言中都存在且广泛使用,字典中的元素是一组<键(key),值(value)>对,key的值是不可以重复的.关于字典的详细内容,网上有很多资料

算法图解之广度优先搜索

广度优先搜索的应用场景,如下:(1)编写国际跳棋AI,计算最少走多少步就可获胜;(2)编写拼写检查器,计算最少编辑多个地方就可将错拼的单词改为正确的单词,如将READED改为READER需要编辑一个地方;(3)根据你的人际关系网络找到关系最近的医生; 图简介 假设你居住在旧金山,要从双子峰前往金门大桥.你想乘公交车前往,并希望换乘最少.可乘坐的公交车如下: 由图可知,换乘最少的路线是:步行->44路公交车->28路公交车(一共三步,这种问题也被称作为最短路径问题,解决最短路径问题的算法,又称广

算法与数据结构基础 - 广度优先搜索(BFS)

BFS基础 广度优先搜索(Breadth First Search)用于按离始节点距离.由近到远渐次访问图的节点,可视化BFS 通常使用队列(queue)结构模拟BFS过程,关于queue见:算法与数据结构基础 - 队列(Queue) 最直观的BFS应用是图和树的遍历,其中图常用邻接表或矩阵表示,例如 LeetCode题目 690. Employee Importance: // LeetCode 690. Employee Importance/* class Employee { publi

算法_图的深度优先搜索和广度优先搜索

一.图的基本数据结构 图是由一组顶点和一组能够将两个顶点相互连接的边所构成的,一般使用0~V-1这样的数字形式来表示一张含有V个顶点的图.用v-w来指代一张图的边,由于是无向图,因此v-w和w-v是同一种边的两种表示方法.无向图是指边没有方向的图结构在无向图中,边仅仅表示的是两个顶点之间的连接.图的数据结构的可视化如下图所示(其中边上的箭头没有任何意义): 当两个顶点通过一条边相互连接,则称这两个顶点是相邻的.某个顶点的度数即为依附它的边的总数.当两个顶点之间存在一条连接双方的路径的时候,称为这

算法-无向图(深度优先搜索和广度优先搜索)

图中最常用到的两种搜索深度优先搜索和广度优先搜索,深度优先搜索是一种在开发爬虫早期使用较多的方法它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链接的Html文件) ,广度搜索属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果.换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止. 深度优先搜索 图中我们经常会遇到一个问题就是图的连通性,比如说从一个顶点到另外一个顶点,判断顶点和其他顶点之间的连通性,以下图为例: 搜索API定义: @interface

图算法系列-深度优先搜索与广度优先搜索

2.深度优先搜索 为了访问一个顶点,我们将它标记为已经访问过,然后递归的访问所有与子邻接的并且尚未标记的顶点,这就是深度优先搜索(DFS),DFS常用于解决路径问题. 比如下面的连通图,我们从顶点0开始对图进行探索 下面这个图显示了DFS处理时的递归调用树. DFS可以解决的问题:1)环检测:一个图中有环吗?该图是森林吗?2)简单路径:给定两个顶点,是否存在一条连接他们的路径3)简单连通性:无论何时使用DFS,都可以在线性时间内确定一个图是否连通4)顶点搜索:在给定顶点所在的同一个连通分量中有多