当前位置: 首页 > news >正文

【算法】队列 + 宽度优先搜索

目录

宽度优先搜索的核心思想

算法实现步骤

BFS的特点和应用场景

BFS 在树结构的应用


宽度优先搜索的核心思想

想象一下你在玩一个迷宫游戏,你站在起点,想知道最快到达终点的路线。BFS的策略是:

首先探索所有起点直接相连的位置(第一层)。

然后探索所有与第一层位置直接相连的、且未被访问过的位置(第二层)。

接着探索所有与第二层位置直接相连的、且未被访问过的位置(第三层)。

... 以此类推,直到找到终点或者遍历完所有能到达的点。

这种“由近及远”的搜索方式,保证了一旦找到目标,所用的步数(或路径长度)一定是最短的。

算法实现步骤

BFS通常使用一个队列(Queue) 这种数据结构来辅助实现。队列的特点是“先进先出”(FIFO),这正好符合我们“先访问的节点,其邻居也先被访问”的需求。

步骤分解:

初始化:选择一个起始节点,将其标记为“已访问”。将该起始节点放入队列。

循环执行以下步骤,直到队列为空:
a. 出队:从队列的头部取出一个节点(我们称它为“当前节点”)。
b. 处理:访问该节点(例如,检查它是否是目标节点,或者进行其他操作)。
c. 探索邻居:检查当前节点的所有“未访问”的邻居节点。
* 将每一个未访问的邻居节点标记为“已访问”。
* 将这些邻居节点依次放入队列的尾部。

结束:当队列为空时,说明所有从起点可达的节点都已经被访问过了,算法结束。

一个生动的例子

    0/ \1   2/ \   \
3   4   5

步骤模拟:

步骤队列状态 (队首<- ... <-队尾)当前节点访问顺序动作说明
初始[0]--将起点0放入队列
1[1, 2]00取出0,访问它。将0的未访问邻居1, 2加入队列。
2[2, 3, 4]11取出1,访问它。将1的未访问邻居3, 4加入队列。
3[3, 4, 5]22取出2,访问它。将2的未访问邻居5加入队列。
4[4, 5]33取出3,访问它。3没有未访问的邻居。
5[5]44取出4,访问它。4没有未访问的邻居。
6[]55取出5,访问它。5没有未访问的

最终的访问顺序(BFS遍历序列)是:0, 1, 2, 3, 4, 5。你可以看到,这正是一层一层输出的结果。

BFS的特点和应用场景

特点:

完备性:如果解存在,BFS一定能找到。

最优性:在无权图中,BFS找到的路径一定是最短路径。

空间复杂度高:在最坏情况下,需要存储一整层的节点,对于分支因子为b的树,第d层有b^d个节点,空间复杂度为O(b^d)。

应用场景:

图的连通性:判断两个节点是否连通。

最短路径:在无权图中求两点间的最短路径。

迷宫求解:找到从起点到终点的最短路径。

社交网络:查找“度”关系(例如,寻找三度好友)。

序列变换(如单词接龙问题)。

树的层序遍历。

BFS 在树结构的应用

层序遍历

题目链接

解析:采用深度优先搜索,但难点是不知道每层具体有多少结点,也就不知道要把多少结果放在数组的同一行,解决方法是在遍历队列之前用一个变量先记录一下队列的长度,然后执行长度次访问队头的操作,执行完后,再次记录队列的长度,下一次遍历队列时就访问长度次......以此类推。

class Solution {
public:vector<vector<int>> levelOrder(Node* root) {queue<Node*> q;vector<vector<int>> ret;if(root) q.push(root);int i = 0;while(!q.empty()){ret.resize(i + 1); // 为下一次记录结果开辟空间int sz = q.size(); // 记录这一层的结点个数while(sz--) {// 访问对头ret[i].push_back((q.front())->val); // 把对头的子结点加入队列for(auto j : (q.front())->children){q.push(j);}// 对头已经访问完了,出队列q.pop();}i++;}return ret;}
};

题目链接

解析:先进行二叉树的层序遍历,最后将结果数组的对应部分进行逆序

class Solution {
public:vector<vector<int>> zigzagLevelOrder(TreeNode* root) {vector<vector<int>> ret;queue<TreeNode*> q;int sz = 0;int i = 0;if(root) q.push(root);while(!q.empty()){sz = q.size();ret.resize(i + 1);while(sz--){TreeNode* top = q.front();ret[i].push_back(top->val);q.pop();if(top->left) q.push(top->left);if(top->right) q.push(top->right);}i++;}for(int j = 1; j < ret.size(); j += 2){reverse(ret[j].begin(),ret[j].end());}return ret;}
};

题目链接

解析:以从左到右,从上到下,从根结点开始为 1,依次对非空结点进行编号,可以发现如果根结点的编号为 n ,那么它的左孩子和右孩子的编号分别为 2*n 和 2*n + 1,树某行的宽度 = 最右边的结点编号 - 最左边结点编号 + 1。对树进行层序遍历,队列中每个元素存储结点和结点的编号。

lass Solution {
public:int widthOfBinaryTree(TreeNode* root) {queue<pair<TreeNode*,unsigned int>> q;if(root) q.push(make_pair(root,1));unsigned maxlen = 0;while(!q.empty()){pair<TreeNode*,unsigned int> front = q.front();pair<TreeNode*,unsigned int> back = q.back();if(back.second - front.second + 1 > maxlen) maxlen = back.second - front.second + 1;int sz = q.size();while(sz--){pair<TreeNode*,unsigned int> front = q.front();if((front.first)->left) q.push(make_pair((front.first)->left,front.second * 2));if((front.first)->right) q.push(make_pair((front.first)->right,front.second * 2 + 1));q.pop();}}return maxlen;}
};

http://www.dtcms.com/a/504701.html

相关文章:

  • 机器学习周报十八
  • C# 参数详解:从基础传参到高级应用
  • 棠下网站建设jsp如何进行购物网站开发
  • 惠州做网站公司部门门户网站建设请示
  • 分析一下Xshell效率实战——SSH管理秘籍
  • 怎么做卖橘子的网站做网站编辑我能力得到提升
  • 支付通道网站怎么做网页设计代码计算器
  • 做价值投资有哪些网站企业集团网站建设与运营
  • 大型网站开发团队分析杭州高端网站建设开发的区别
  • C++深度解析:从核心特性到现代编程实践
  • 电商网站建设优缺点网站 微信 app
  • dw网站开发环境百度大搜
  • 有什么发布做投标报价的网站wordpress 首页添加图片不显示
  • 杭州协会网站建设做电子书网站
  • 163网站源码做优化很好的网站
  • JdbcTemplate(会用)
  • LangGraph 源码学习总结 2-图计算模型
  • 网站的建设技术有哪些内容在湖南建设人力资源网站
  • 网站被k的怎么办枫林seo工具
  • 网站布局分类商城网站的功能
  • 足球个人网站模板公司商标注册怎么弄
  • vps做网站 推广wordpress是不是很慢
  • 建设部网站哪里可以报名考监理员怎么做网站平台教程
  • 网站做相片页游网站建设
  • 网站制作泉州公司做系统之前的网站
  • 数据驱动+AI:重塑安全应急与网络安全的技术实践与方法论
  • 西部网站域名出售海口网站制作设计
  • 目前网站开发的主流语言是什么wordpress公司展示网站模板
  • 聊城做网站公司聊城博达网站设计公司哪家好
  • 国外建筑设计网站推荐贾汪城乡建设局网站