广度优先搜索的概念

 广度优先搜索(BFS)类似于二叉树的层序遍历算法,它的基本思想是:首先访问起始顶点v,然后由v出发,依次访问v的各个未被访问过的邻接顶点w1,w2,w3….wn,然后再依次访问w1,w2,…,wi的所有未被访问过的邻接顶点,再从这些访问过的顶点出发,再访问它们所有未被访问过的邻接顶点….以此类推,直到途中所有的顶点都被访问过为止。类似的想法还将应用与Dijkstra单源最短路径算法和Prim最小生成树算法。(这个过程我觉得可以举个这样的例子来理解:比如要从你开始介绍你的家人,可以先从你开始,然后一个一个介绍和你有直接血缘关系的这一层亲属(爸爸妈妈儿子女儿),当把你所有的这些第一层亲属全都遍历完之后再从你的妈妈开始遍历(也可以从爸爸或儿子),把你妈妈的有直接血缘关系的亲戚先遍历一遍,然后再从爸爸开始,以此类推,直到全部都遍历完成)。

 广度优先搜索是一种分层的查找过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有回退的情况(另一篇博客会介绍),因此它不是一个递归的算法,为了实现逐层的访问,算法必须借助一个辅助队列并且以非递归的形式来实现。

算法伪代码

其伪代码如下:

 

bool visited[MAX_VERTEX_NUM];//访问数组,也就是顶点个数

void BFSTraverse(Graph G)
//外层的函数,为准备实现遍历做一些准备工作。
{
 for(int i=0;i<G.vexnum;++i)
 visited[i]=false;//先将所有的顶点都设置为没有被访问过
InitQueue(Q);//初始化辅助队列方便遍历顶点
for(int i=0;i<G.vexnum;++i)
if(!visited[i])
BFS(G,i);
//外层循环使用if语句来调用BFS的原因是为了防止有的顶点它不能从初始顶点出发而遍历到,所以这里需要一个完全的循环来避免这种极端情况。
} void BFS(Graph G,int v)
//从顶点v出发,广度优先遍历图G,算法借助了一个辅助队列Q
visit(v);//visit函数访问这个顶点的信息
visited[v]=true;//访问过了这个顶点之后就将这个顶点设置为已访问,即true
Enqueue(Q,v);//将顶点v入队列,这样就可以从队列中出队并访问它的相邻顶点
while(!isEmpty(Q)){
DeQueue(Q,v);//将队头的元素出队列存储在v
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))//这一步是检查v的所有邻接顶点
if(!visited[w]){
visit(w);
visited[w]=true;
EnQueue(Q,w);
//如果w没有被访问过,那么访问这个顶点,并把它入队
}
}

实例以及解析



  假设从a顶点开始访问,a先入队。此时队列非空,取出队头元素a,由于b,c和a直接相邻且未被访问过,于是依次访问b,c,并且b,c依次入队。队列非空,取出队头元素b,依次访问与b相邻且未被访问的顶点d,e,并且将d,e入队(注意:a与b也邻接,但是a已经访问过,就不会再访问了)。此时队列非空,取出队头元素c,访问与c邻接且未被访问过的顶点f,g,并且将f,g入队。此时,取出队头元素d,但与d邻接且为被访问的顶点为空,故不再进行任何操作,继续取出对头元素e,将h入队….当最后取出队头元素h后,队列为空,从而循环自动跳出,遍历的结果为abcdefgh。

BFS算法性能分析

  无论是邻接表还是邻接矩阵的存储访问,BFS算法都需要借助一个辅助队列Q,n个顶点都需要入队依次,在最坏的情况下,空间复杂度为O(|V|)。

  当采用邻接表存储方式时,每个顶点均需要搜索依次(或入队依次),故时间复杂度为O(|V|),再搜索任一顶点时,每条边至少访问依次,故时间复杂度为O(|E|),算法的总时间复杂度为O(|V|+|E|);当采用邻接矩阵存储方式的时候,查找每个顶点的邻接点所需时间为O(|V|),故算法总的时间复杂度为O(|V|²)。

BFS算法求单源最短路径问题

  如果图G=(V,E)为非带权图。定义从顶点u到顶点v的最短路径d(u,v)为从u到v的任何路径中最少的边数;如果从u到v没有通路,则d(u,v)=∞。

  使用BFS,我们可以求解一个满足上述定义的非带权图的单源最短路径问题,这是由广度优先搜索总是按照距离由近到远来遍历图中每个顶点的性质决定的(这让我想到:在2d游戏中计算两个位置的最短路径是否可以采用BFS算法来求出呢?)

  BFS算法求解单源最短路径问题的算法如下:

  

void BFS_MIN_Distance(Graph G,int u){
//d[i]表示从u到i结点的最短路径
for(i=0;i<G.vexnum;++i)
d[i]=∞; //初始化路径长度
visited[u]=true;
d[u]=0;
while(!isEmpty(Q)){
DeQueue(Q,u);
for(w=FirstNeighbor(G,u);w>=0;w=NextNeighbor(G,u,w))
if(!visited[w]){//w为u未曾访问的邻接顶点
visited[w]=true;//设为已经访问
d[w]=d[u]+1;//路径长度+1
EnQueque(Q,w);//w顶点入队
} }
}

[数据结构]广度优先搜索算法(Breadth-First-Search,BFS)的更多相关文章

  1. 广度优先搜索(Breadth First Search, BFS)

    广度优先搜索(Breadth First Search, BFS) BFS算法实现的一般思路为: // BFS void BFS(int s){ queue<int> q; // 定义一个 ...

  2. 【2018.07.30】(广度优先搜索算法/队列)学习BFS算法小记

    一些BFS参考的博客: https://blog.csdn.net/ldx19980108/article/details/78641127 https://blog.csdn.net/u011437 ...

  3. ZH奶酪:【数据结构与算法】搜索之BFS

    1.目标 通过本文,希望可以达到以下目标,当遇到任意问题时,可以: 1.很快建立状态空间: 2.提出一个合理算法: 3.简单估计时空性能: 2.搜索分类 2.1.盲目搜索 按照预定的控制策略进行搜索, ...

  4. python 递归深度优先搜索与广度优先搜索算法模拟实现

    一.递归原理小案例分析 (1)# 概述 递归:即一个函数调用了自身,即实现了递归 凡是循环能做到的事,递归一般都能做到! (2)# 写递归的过程 1.写出临界条件2.找出这一次和上一次关系3.假设当前 ...

  5. python 递归,深度优先搜索与广度优先搜索算法模拟实现

    一.递归原理小案例分析 (1)# 概述 递归:即一个函数调用了自身,即实现了递归 凡是循环能做到的事,递归一般都能做到! (2)# 写递归的过程 1.写出临界条件 2.找出这一次和上一次关系 3.假设 ...

  6. AI广度优先搜索算法,项目实战北京地图/贪心学院

    广度优先搜索算法详解地铁路线 北京很大,附上地铁图,不要迷路!!! 作为一个程序员,在北京,你很有可能住在回龙观地区,经常从龙泽上地铁,然后畅游北京. 当有一天,你老家的朋友来北京了,希望你能够带她去 ...

  7. [数据结构]深度优先搜索算法(Depth-First-Search,DFS)

    深度优先搜索算法的概念 与广度优先搜索算法不同,深度优先搜索算法类似与树的先序遍历.这种搜索算法所遵循的搜索策略是尽可能"深"地搜索一个图.它的基本思想如下:首先访问图中某一个起始 ...

  8. javascript实现的图数据结构的广度优先 搜索(Breadth-First Search,BFS)和深度优先搜索(Depth-First Search,DFS)

    最后一例,搞得快.三天之内走了一次.. 下一步,面象对像的javascript编程. function Dictionary(){ var items = {}; this.has = functio ...

  9. 数据结构之 图论---基于邻接矩阵的广度优先搜索遍历(输出bfs遍历序列)

    数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory limit: 65536K 题目描述 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索( ...

随机推荐

  1. 驱动开发:内核监视LoadImage映像回调

    在笔者上一篇文章<驱动开发:内核注册并监控对象回调>介绍了如何运用ObRegisterCallbacks注册进程与线程回调,并通过该回调实现了拦截指定进行运行的效果,本章LyShark将带 ...

  2. 【神经网络】丢弃法(dropout)

    丢弃法是一种降低过拟合的方法,具体过程是在神经网络传播的过程中,随机"沉默"一些节点.这个行为让模型过度贴合训练集的难度更高. 添加丢弃层后,训练速度明显上升,在同样的轮数下测试集 ...

  3. 十七、Job与Cronjob

    Job 与 Cronjob 一.Job ​Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束. 特殊说明: 1.spec.template 格式同 Pod ​2 ...

  4. vulnhub靶场之NOOB: 1

    准备: 攻击机:虚拟机kali.本机win10. 靶机:NOOB: 1,网段地址我这里设置的桥接,所以与本机电脑在同一网段,下载地址:https://download.vulnhub.com/noob ...

  5. Spring Cloud Loadbalancer

    Spring Cloud Loadbalancer---客户端负载均衡器 springcloud 2020.0.1 版本之后 删除了eureka中的ribbon,替代ribbon的是spring cl ...

  6. 2022春每日一题:Day 9

    题目:IncDec Sequence 思维题,差分好题,每次区间操作,对应差分a[l]+=v,a[r+1]-=v,在差分数组中一定有一个正负号抵消,那么我们求出差分数组中正数(负数)和,记做s1,s2 ...

  7. Go语言核心36讲30

    你好,我是郝林,今天我继续分享条件变量sync.Cond的内容.我们紧接着上一篇的内容进行知识扩展. 问题 1:条件变量的Wait方法做了什么? 在了解了条件变量的使用方式之后,你可能会有这么几个疑问 ...

  8. uboot引导应用程序

    uboot默认是支持执行应用程序的,就像引导内核一样,我们也可以自己写一个应用程序,让uboot启动时引导. 在uboot examples/standalone 目录下,有hello_world.c ...

  9. python-opencv实现抖动算法

    抖动算法简单介绍 简单说就是牺牲分辨率来提高颜色数量. 通过黑点的疏密程度来进行灰度的显示. 例如墨水屏幕只能显示黑白,那么我们可以取样一部分区域矩,例如2x2的一个矩阵,来显示5个级别的灰度,用4个 ...

  10. form enctype="multipart/form-data" ajax 文件上传

    <form method="post" enctype="multipart/form-data" id="resource"> ...