目录

一.宽度优先搜索(BFS)是什么?

二.图解宽搜(BFS)

三.对比与发现

四。工具——队列

五.模板

六.最后


一.宽度优先搜索(BFS)是什么?

百度百科这样说:

宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

过于理论性,不过说出了核心:

它是一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

有人这样说:

就是从根结点位置开始遍历,遍历结束后依次遍历与根节点相邻的点,相邻点遍历结束后继续遍历上轮第一个遍历结点的相邻的未遍历的点,直至所有的点都遍历结束。

generalKnowledge/基础算法/广度优先搜索.md · jimmyflower6/中山一中初中部信息竞赛 - Gitee.com

这个说的比较好,但仍然有一点生硬。

简单来说,就是:

宽度优先搜索是一种对图进行搜索的算法。假设我们一开始位于某个顶点(即起点),此 时并不知道图的整体结构,而我们的目的是从起点开始顺着边搜索,直到到达指定顶点(即终 点)。在此过程中每走到一个顶点,就会判断一次它是否为终点。广度优先搜索会优先从离起点 近的顶点开始搜索。

下面,我将用步骤图的方式,向大家介绍这种方法。


二.图解宽搜(BFS)

A为起点,G为终点。一开始我们在起点A上,此时并不知道G在哪里。

将可以从A直达的三个顶点B、C、D设为下一步的候补顶点。

从候补顶点中选出一个顶点。优先选择最早成为候补的那个顶点,如果多个顶点同时成为候补,那么可以随意选择其中一个。 (优先选择最早成为候补的那个顶点,这是一种“先进先出”的方式,后面会讲到)

此处 B、C、D 同时成为候补,所以我们随机选择了最左边的顶点B。

移动到选中的顶点B上。此时我们在B上, 所以B变为红色,同时将已经搜索过的顶点变为橙色。

此处,候补顶点是用“先入先出”(FIFO)的方式来管理的,因此可以使用“队列”这个数据结构。(这个结构将会在后面讲解,请往下翻)

将可以从B直达的两个顶点E和F设为候补 顶点。

此时,最早成为候补顶点的是C和D,我们选择了左边的顶点C。

移动到选中的顶点C上。

将可以从C直达的顶点H设为候补顶点。

重复上述操作直到到达终点,或者所有的顶点都被遍历为止。

这个示例中的搜索顺序为 A、B、C、D、E、F、 H、I、J、K。

完成了从A到I的搜索,现在在顶点J处。

到达终点G,搜索结束。

补充说明:由上可以知道,广度优先搜索的特征为从起点开始,由近及远进行广泛的搜索。因此,目标顶点离起点越近,搜索结束得就越快。


三.对比与发现

DFS和BFS的区别
bfs 遍历节点是先进先出,dfs遍历节点是先进后出
bfs是按层次访问的,dfs 是按照一个路径一直访问到底,当前节点没有未访问的邻居节点时,然后回溯到上一个节点,不断的尝试,直到访问到目标节点或所有节点都已访问。
bfs 适用于求源点与目标节点距离最近的情况,例如:求最短路径。dfs 更适合于求解一个任意符合方案中的一个或者遍历所有情况,例如:全排列、拓扑排序、求到达某一点的任意一条路径。

不过,宽度优先搜索(BFS)的先进先出如何实现呢?这里,我们运用了一个数据结构——队列。


四。工具——队列

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

我们可以用双指针标记一下,通过front指针与rear指针,对队头和队尾进行标记,然后只允许在front、rear指针的位置进行增删改查,那么这样便实现了对数组的受限。这是一种运用数组的数据结构对队列的模拟。初学者建议先用这种方式熟悉队列。

具体操作:

/*通常将front赋值为0,rear赋值为-1方便后续进队、出队以及取队首元素*/
int a[100], front=0, rear=-1;// 进队
a[++rear] = 10;// 出队
front++// 取队首元素
a[front]// 取队尾元素
a[rear]// 判断是否为空队
if(front > rear)cout << "该队列为空队";

不过,到了后期,为了节省时间,我们可以直接用c++自带的STL容器来完成操作。

具体操作如下:

// 导入queue包
#include<queue>// 申明一个queue对象
// 填入你想装填的数据类型
queue<int> qu;// 进队
int a = 10;
qu.push(a);// 出队,无返回值
qu.pop();// 取队首元素
int front = qu.front();// 取队尾元素
int rear = qu.back();// 队是否为空
if(qu.empty()) {cout << "该队列为空队";
}// 队大小,返回int
qu.size();

五.模板

BFS的题目是有一套明显模板的,不信,我们来看看。(将展示核心代码)

八数码问题:

while(!q.empty())//q非空,可以走{for(int i=0;i<4;i++)//四个方向{ma ac=q.front();int nx = ac.x0 + dx[i];int ny = ac.y0+ dy[i];if(nx>=1&&ny>=1&&nx<=3&&ny<=3){swap(ac.a[ac.x0][ac.y0],ac.a[nx][ny]);ac.x0=nx;ac.y0=ny;//将0与目标数交换ac.ans++;//步数加1ac.kt=kt(ac);//康托判重if (!flag[ac.kt]){flag[ac.kt] = 1;q.push(ac);//加入队列if(ac.kt==mo.kt){ printf("%d",q.back().ans);exit(0);}}}}q.pop();//弹出已遍历完所有情况的矩阵}

海上救援任务:

     while(!q.empty()){for(int i=0;i<4;i++){node ne;ne.x=q.front().x+dx[i],ne.y=q.front().y+dy[i];if(bo[ne.x][ne.y]==0&&ne.x>=0&&ne.y>=0&&ne.x<=n&&ne.y<=m&&a[ne.x][ne.y]==1){ne.ans=q.front().ans+1;bo[ne.x][ne.y]=1;q.push(ne);if(ne.x==xe.x&&ne.y==xe.y){flag=true;printf("%d\n",q.back().ans);break;}}}if(flag) break;q.pop(); }

巧妙取量:

    while(scanf("%d%d%d%d",&t.a[1],&t.a[2],&t.a[3],&k)!=EOF)//多组数据{flag=false;memset(bo,0,sizeof(bo));bo[t.a[1]][t.a[2]][t.a[3]]=1;p.ans=0;p.a[1]=t.a[1];p.a[2]=p.a[3]=0;q.push(p);if(q.front().a[1]==k||q.front().a[2]==k||q.front().a[3]==k){printf("yes\n%d\n",0);continue;}//特判 while(!q.empty()){for(int i=1;i<=3;i++){if(q.front().a[i]>0){for(int j=1;j<=3;j++){node sy;sy=q.front();sy.ans ++;if(i!=j){int T=t.a[j]-sy.a[j];if(sy.a[i]>T){sy.a[j]=t.a[j];sy.a[i]=sy.a[i]-T;}else{sy.a[j]+=sy.a[i];sy.a[i]=0;}if(!bo[sy.a[1]][sy.a[2]][sy.a[3]]){bo[sy.a[1]][sy.a[2]][sy.a[3]]=1;if(sy.a[1]==k||sy.a[2]==k||sy.a[3]==k){flag=true;}q.push(sy);}}}}}//遍历每一种倒法 if(flag) break;q.pop();}if(flag){printf("yes\n%d\n",q.back().ans);}else{printf("no\n");}while(!q.empty()){q.pop();}}

我选了几道没那么相似的题目,但仔细一看,架构都是一样的。

用步骤图可表示为:

而用伪代码,则是这样表示:

int BFS(Node start, Node target) {入队(初始状态);visited[初始状态] = true;while(!空队) {for() { // 状态转换Node node = 队首元素;对node的处理,生成新node状态;if (visited[node] == true)continue;if (node == target) {输出答案;return 0;}v[node] = true;入队(node);}出队();}}

这,就是BFS问题的模板!!!

六.最后

没什么,如果喜欢的话,给个三连吧!您的支持是我最大的动力!

宽度优先搜索算法(BFS)详解(超级详细讲解,附有大图)相关推荐

  1. 广度/宽度优先搜索(BFS)详解

    1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略.因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,故得名. 一般可以用它做什么呢?一 ...

  2. 算法导论:dfs深度优先搜索算法及基于dfs的拓扑排序以及宽度优先搜索算法bfs

    1.dfs深度优先搜索算法 算法导论中是通过三种标记颜色来介绍dfs的,white代表还没被搜过,grey代表被搜了一些,还没结束,white表示已经搜索完成的状态. c/c++复现dfs代码 #in ...

  3. Redis五种数据类型应用场景详解(超级详细版)

    目录 NoSQL:一类新出现的数据库(not only sql) 特征 NoSQL和SQL数据库的比较: 电商场景解决方案 Redis简介 Redis特性 Redis 优势 Redis应用场景 官方文 ...

  4. 树上分治详解 超级详细(附带例题 poj1741(给了题目))

    例题大概意思就是有一颗有 n 个顶点的树,其中连接顶点 a_i 和 b_i 的边 i 的长度为 l ,然后统计最短距离不超过 k 的顶点的对数 (虽然篇幅比较长,但是看完会有收获的) 树上的分治,与其 ...

  5. 平面分治详解 超级详细(附带例题 最近点对问题(给了题目))(UVA10245,P1257,P1429)

    最近点对问题,大概意思平面有n个点,求距离最近的两个点对的距离(可用平面分治解决绝大部分情况) 首先如果一个一个比较,那就是n的二次方复杂度,那很多情况都会超时 我们考虑使用分治法,大概思路就是将这个 ...

  6. 强连通分量分解详解 超级详细

    (写的有点小多,慢慢看,会有收获的) (1) 首先我们得了解,什么是强连通? 如果在一个有向图顶点子集内,任取两个点 u 和 v ,都能找到一条路径从 u 到 v ,则称该子集为强连通 (2) 其次我 ...

  7. Spring AOP全面详解(超级详细)

    如果说IOC 是 Spring 的核心,那么面向切面编程AOP就是 Spring 另外一个最为重要的核心@mikechen AOP的定义 AOP (Aspect Orient Programming) ...

  8. Java基本注解详解(超级详细)

    原文链接: 今日头条 Java注解是一个很重要的知识点,用于对代码进行说明,可以对包.类.接口.字段.方法参数.局部变量等进行注解. 掌握好Java注解有利于学习框架底层实现.@mikechen Ja ...

  9. 最小路径覆盖详解 超级详细(附带例题 Stock Charts(给了题目))

    最小路径覆盖定义:在图G中找出一些路径,每条路径从起点走到终点,使所有点均被覆盖,且只被覆盖一次,选出的这些路径组成路径覆盖.如果找出最少的路径成为一个路径覆盖,则称为最小路径覆盖. 对于不包含圈的有 ...

  10. kickstart详解(超级详细)

    一.kickstart是什么   许多系统管理员宁愿使用自动化的安装方法来安装红帽企业 Linux.为了满足这种需要,红帽创建了kickstart安装方法.使用kickstart,系统管理员可以创建一 ...

最新文章

  1. MindSpore布道师队伍招募开始,助力小白成为大牛!
  2. POJ 1806 Manhattan 2025
  3. 检测到磁盘可能为uefi引导_【可QQ无偿协助】无法安装windows 因为这台电脑的磁盘布局不受UEFI固件支持...
  4. python固定数据类型_Python的数据类型
  5. Octave添加搜索路径
  6. windows密钥连接linux,windows使用密钥登录linux
  7. GPU Shader 编程基础
  8. 经典:区间dp-合并石子
  9. mysql----innodb统计信息
  10. MySQL选择数据库
  11. python opencv用法中文教程
  12. LINUX删除指定子目录下所有指定文件名
  13. 硕士研究生毕业论文书写格式总结
  14. PS如何更改图片部分颜色
  15. 整流二极管的细节分析
  16. 亮度键消失、亮度键失灵且电脑亮度为最大 | 小米 | win11 | 解决办法最最最全合集
  17. 友盟统计,h5 API
  18. css 隐藏滚动条 竖向y滚动,横向x不滚动
  19. Netty游戏服务器实战开发(12):线程任务组件开发
  20. 报名成功冲向高级软件工程师之路开始了

热门文章

  1. 【汇编综合应用】大小写字母的转换、2号、9号和10号DOS系统功能调用、分支、循环程序结构、子程序、寄存器传递参数,宏定义、宏调用,观察宏展开。
  2. Python 3.8 有什么新变化
  3. 课程设计:通讯录管理系统
  4. 关于西瓜视频加密算法的总结
  5. SGAME的日志系统
  6. tfidf+java+权重,使用scikit-learn tfidf计算词语权重
  7. python check module_Python 的 module 机制(重要)
  8. 北邮矩阵论- 第1章 1.1线性空间
  9. 经纬度度与度分格式转化
  10. 世界杯小组赛积分的所有可能