首页 > 其他分享 >图的遍历-BFS

图的遍历-BFS

时间:2024-04-05 18:13:08浏览次数:16  
标签:遍历 队列 BFS 访问 邻接 顶点 取出

1. BFS遍历

BFS 算法的思想:对一个无向连通图,在访问图中某一起始顶点 v 后,由 v 出发,依次访问 v 的所有未访问过的邻接顶点 w1, w2, w3, …wt;然后再顺序访问 w1, w2, w3, …wt 的所有还未访问过的邻接顶点;再从这些访问过的顶点出发,再访问它们的所有还未访问过的邻接顶点, ……,如此直到图中所有顶点都被访问到为止。 

接下来以下图(a)所示的无向连通图为例解释 BFS 搜索过程。 假设在多个未访问过的邻接顶点中进行选择时,按顶点序号从小到大的顺序进行选择。

对上图(a)所示的无向连通图,采用 BFS 思想搜索的过程为:

  1. 访问顶点 A,这是第一层;
  2. 访问顶点 A 的 3 个邻接顶点 B、 D 和 E,这是第二层;
  3. 访问顶点 B 的未访问过的邻接顶点(即顶点 C), 访问顶点 D 的未访问过的邻接顶点(即  顶点 F),顶点 E 没有未访问过的邻接顶点,这是第三层;
  4. 访问顶点 C 的未访问过的邻接顶点(即顶点 G), 访问顶点 F 的未访问过的邻接顶点(即顶点 H),这是第四层;
  5. 顶点 G 没有未访问过的邻接顶点,访问顶点 H 的未访问过的邻接顶点(即顶点 I),这是第五层。 

2. BFS 算法的实现 

与深度优先搜索过程一样,为避免重复访问,也需要一个状态数组 visited[n],用来存储各顶点的访问状态。如果 visited[i] = 1,则表示顶点 i 已经访问过;如果 visited[i] = 0,则表示顶点 i 还未访问过。初始时,各顶点的访问状态均为 0。 

  • 访问顶点 A,然后把顶点 A 入队列;
  • 取出队列头的顶点,即顶点 A,然后依次访问顶点 A 的 3 个邻接顶点 B、 D 和 E,并把这 3 个顶点入队列;
  • 取出此时队列头的顶点,即顶点 B, 然后访问顶点 B 的未访问过的邻接顶点, 即顶点 C,并把顶点 C 入队列;
  • 取出此时队列头的顶点, 即顶点 D, 然后访问顶点 D 的未访问过的邻接顶点, 即顶点 F,并把顶点 F 入队列;
  • 取出此时队列头的顶点,即顶点 E,而顶点 E 已经没有未访问过的邻接顶点;
  • 取出此时队列头的顶点, 即顶点 C, 然后访问顶点 C 的未访问过的邻接顶点, 即顶点 G,并把顶点 G 入队列; 
  • 取出此时队列头的顶点, 即顶点 F, 然后访问顶点 F 的未访问过的邻接顶点, 即顶点 H,并把顶点 H 入队列;
  • 取出此时队列头的顶点,即顶点 G,而顶点 G 已经没有未访问过的邻接顶点;
  • 取出此时队列头的顶点,即顶点 H,然后访问顶点 H 的未访问过的邻接顶点,即顶点 I,并把顶点 I 入队列;
  • 取出此时队列头的顶点,即顶点 I,而顶点 I 已经没有未访问过的邻接顶点;至此,队列为空, BFS 搜索执行完毕。

BFS 执行过程中,各顶点的访问顺序依次为: A→B→D→E→C→F→G→H→I 。

如果用邻接表存储图,则 BFS 算法实现的伪代码如下: 

BFS( 顶点 i ) //从顶点 i 进行广度优先搜索
{
    visited[ i ] = 1; //将顶点 i 的访问标志置为 1
    将顶点 i 入队列;
    while( 队列不为空 )
    {
        取出队列头的顶点,设为 k
        p = 顶点 k 的边链表表头指针
        while( p 不为空 )
        {
            //设指针 p 所指向的边结点所表示的边的另一个顶点为顶点 j
            if( 顶点 j 未访问过 )
            {
                将顶点 j 的访问标志置为 1
                将顶点 j 入队列
            }
            p = p->nextarc; //p 移向下一个边结点
        } //end of while
    } //end of while
} //end of BFS

如果用邻接矩阵存储图(设顶点个数为 n),则 BFS 算法实现的伪代码如下: 

BFS( 顶点 i ) //从顶点 i 进行广度优先搜索
{
    visited[ i ] = 1; //将顶点 i 的访问标志置为 1
    将顶点 i 入队列;
    while( 队列不为空 )
    {
        取出队列头的顶点,设为 k
        for( j=0; j<n; j++ ) //对其他所有顶点 j
        {
            //j 是 k 的邻接顶点,且顶点 j 没有访问过
            if( Edge[k][j]==1 && !visited[j] )
            {
                将顶点 j 的访问标志置为 1
                将顶点 j 入队列
            }
        } //end of for
    } //end of while
} //end of BFS

3.  BFS 算法的复杂度分析 

设无向图有 n 个顶点,有 m 条边。

如果使用邻接表存储图, 对从队列头取出来的每个顶点 k, 首先要取出该顶点的边链表头指针,然后沿着该顶点的边链表中的每个边结点,把未访问过的邻接顶点入队列。在这个过程每个顶点访问各一次, 2m 个边结点各访问一次,所以总的时间代价为 O(n+2m)。

如果用邻接矩阵存储图,由于在邻接矩阵中只是间接地存储了边的信息,所以对从队列头取出来的每个顶点 k,要循环检测无向图中的其他每个顶点 j(不管是否与顶点 k 相邻),判断 j 是否跟 k 相邻且是否访问过;另外,每个顶点都要入队列,都要从队列头取出,进行判断,所以总的时间代价为 O(n2)。 

 

标签:遍历,队列,BFS,访问,邻接,顶点,取出
From: https://www.cnblogs.com/love-9/p/18116024

相关文章

  • (Java)数据结构——图(第三节)BFS的实现
    前言本博客是博主用于复习数据结构以及算法的博客,如果疏忽出现错误,还望各位指正。广度优先搜索的原理好了,还是这张图,不过是广度优先搜索不难看出,就是“一层一层”搜这次咱从A开始,因为如果从B开始的话,只需要一次,搜索过程就是B直接搜完,入队ACDE,isVistied全部ture,结束......
  • 栈的应用之二叉树的中序遍历
    中序遍历一、实例要求给定一个二叉树的根节点root,返回它的中序遍历;二、实例分析1、首先定义了二叉树的结构TreeNode,以及栈的结构Stack和相关操作;2、然后实现了中序遍历函数inorderTraversal,在遍历过程中使用栈来辅助实现;3、最后释放了内存;三、示例代码/**......
  • 图的遍历-DFS
    1.DFS遍历DFS算法的思想:对一个无向连通图,在访问图中某一起始顶点v后,由v出发,访问它的某一邻接顶点w1;再从w1出发,访问与w1邻接但还没有访问过的顶点w2;然后再从w2出发,进行类似的访问;…;如此进行下去,直至到达所有邻接顶点都被访问过的顶点u为止;接着,回退一步,回退到前一......
  • 11.python的字典dict(下) 遍历字典,结构优化
    11.python的字典dict(下)遍历所有的键值对items()方法是字典的一个内置方法,用于返回字典中所有键值对的视图(view)。它返回一个可迭代的对象,每个元素都是一个包含键和对应值的元组。下面用一个例子来说明items()方法的用法:dict1={'name':'John','age':25,'job':'En......
  • 【算法】BFS、并查集和拓扑排序
    最近刷到了两道关于图论很有意思的题目()。做法颇有相似之处,因此记录一下吧AcWing2069.网络分析标签:dfs、并查集题目描述题目大意是,有一个\(n\)个顶点的网络,初始状态图中没有边。有两种操作:操作1将节点\(a\)和节点\(b\)连接起来;操作2使节点\(p\)的值加\(t\),\(t\)值会沿着网......
  • 二叉树的高效非递归层次遍历:一种O(n)时间复杂度与固定空间复杂度的解决方案
    @TOC在计算机科学中,二叉树是一种非常重要的数据结构,它在算法设计和问题解决中扮演着关键角色。本文将探讨如何使用非递归方法遍历一个给定的二叉树,并在不修改树结构的前提下,输出每个节点的关键字。这个过程将在O(n)的时间复杂度内完成,并且只使用固定量的额外存储空间。1.......
  • python 遍历字典
    在Python中,遍历字典(dictionary)通常涉及遍历字典的键(keys)、值(values)或者同时遍历键和值。以下是几种常见的遍历字典的方法:遍历字典的键(keys):pythonmy_dict={'a':1,'b':2,'c':3}forkeyinmy_dict.keys():print(key)遍历字典的值(values):pythonforvalue......
  • 15天【代码随想录算法训练营34期】第六章 二叉树 part02(● 层序遍历 10 ● 226.翻
    层序遍历10102.二叉树的层序遍历(opensnewwindow)#Definitionforabinarytreenode.#classTreeNode:#def__init__(self,val=0,left=None,right=None):#self.val=val#self.left=left#self.right=rightclassSolution......
  • 文件下载中的目录遍历漏洞与解决
    安全组觉得我们文件下载不够安全。给了份修复方案1、净化数据:对用户传过来的文件名参数进行硬编码或统一编码,对文件类型进行白名单控制,对包含恶意字符或者空字符的参数进行拒绝。2、web应用程序可以使用chroot环境包含被访问的web目录,或者使用绝对路径+参数来访问文件目录,时使其......
  • 代码随想录算法训练营第14天 | 二叉树 | 二叉树的遍历 | 迭代遍历 |统一风格的迭代(待
    理论基础二叉树的存储方式:可以链式也可以顺序用数组顺序存储二叉树的遍历递归遍历递归算法三要素确定递归函数的参数和返回值确定终止条件确定单层递归的逻辑风格不统一的迭代遍历(前后和中序的不同)前序遍历(根左右)//递归版voidtraversal(TreeNode*......