zoukankan      html  css  js  c++  java
  • 【算法】广度优先搜索

    广度优先搜索(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)的。
    •   需要按加入顺序检查搜索列表中的元素,否则找到的就不是最短路径,因此搜索列表必须是队列
    •   对于检查过的元素,务必不要再去检查否则可能导致无限循环
  • 相关阅读:
    c# web开发
    向wp8开发进军
    练毛笔字的心得
    刚开通博客园
    DevExpress Asp.net(3) ASPxCallback组件
    DevExpress Asp.net(2) ASPxObjectContainer说明
    DevExpress Asp.net(1) ASPxButton的基本使用
    JavaMail学习笔记(四)、使用POP3协议接收并解析电子邮件(全)
    Java正则表达式(一)、抓取网页email地址实例
    JavaMail学习笔记(五)、使用IMAP协议接收并解析电子邮件
  • 原文地址:https://www.cnblogs.com/lilip/p/9541328.html
Copyright © 2011-2022 走看看