今天没有例题!
广度优先搜索(BFS)介绍
广度优先搜索(Breadth-First Search,简称BFS)是一种用于遍历或搜索树或图的算法。它从根节点(或任意节点)开始,逐层探索邻近节点,先访问离起点最近的节点。
基本思想
BFS的核心思想是"先广后深",即:
- 访问起始节点
- 依次访问起始节点的所有相邻节点
- 对这些相邻节点,再依次访问它们的未被访问过的相邻节点
- 重复上述过程,直到所有可达节点都被访问
算法实现
BFS通常使用队列(FIFO)数据结构来实现:
BFS(起始节点):
1. 创建一个队列Q,并将起始节点放入Q
2. 标记起始节点为已访问
3. while Q不为空:
a. 从Q中取出第一个节点v
b. 访问v
c. 将v的所有未被访问的相邻节点加入Q
d. 标记这些相邻节点为已访问
特点
- 完备性:如果解存在,BFS一定能找到(在无限图中如果解存在有限深度)
- 最优性:对于无权图,BFS能找到最短路径
- 空间复杂度:O(b^d),其中b是分支因子,d是解的深度
- 时间复杂度:O(b^d)
应用场景
- 无权图的最短路径问题
- 社交网络中查找人与人之间的最短关系链
- 网络爬虫的网页抓取
- 迷宫求解
- 连通性检测
- 广播网络中的信息传播
与深度优先搜索(DFS)的比较
- BFS使用队列,DFS使用栈(递归实现隐式使用调用栈)
- BFS适合寻找最短路径,DFS适合寻找是否存在路径
- BFS空间复杂度通常高于DFS
- BFS在深度大的情况下可能不实用,而DFS可能在分支多的情况下不实用
BFS是许多更复杂算法的基础,如Dijkstra算法和Prim最小生成树算法都可以看作是BFS的变种。
广度优先搜索的示列代码
解题的通式1:
#include <bits/stdc++.h>
using namespace std;
signed main()
{
queue<int> q;
// ! 将队列初始状态入队
q.push("初始状态");
while(!q.empty)
{
// ! 取出队首元素
State cur = q.front();
// ! 队首出队
q.pop();
// ! 找到u所有可能性v
for("枚举所有可能状态")
{
// ! 状态v是否合法,如未访问过,未在队列中
if("状态合法")
{
// ! 状态v入队,同时可能要维护某些信息,记录路径
q.push("新状态");
}
}
}
}
解题通式2:
#include <bits/stdc++.h>
using namespace std;
int n;
int dis[1000005];
void bdf(int s)
{
for(枚举所有可能状态)
{
dis[当前状态] = -1;
}
queue<int>q;
dis[初始状态] = 0;
q.push(初始状态);
while(!Q.empty)
{
state u=q.front();
q.pop();
if(当前状态是答案状态)记录答案
for(枚举所有可能状态)
{
if(状态合法)
{
state v=当前状态u进行决策得到的新状态;
if(v满足题目限制条件 && dis[状态v]==-1)
{
q.push(v);
dis[状态v] = dis[u] + 1;
}
}
}
}
}
老师上课原装正版代码:
bfs:(模板)
//State 为结构体类型的名字
#include<bits/stdc++.h>
using namespace std;
int n;
int dis[100006];
void dfs(){
//dis 数组表示起始状态到每一个状态的最小步数
for(枚举所有状态)dis[当前状态]=-1;//数组初始化
queue<State>Q;
dis[初始状态]=0;
Q.push(初始状态);
if(当前状态u是答案状态)记录/处理答案;
while(!Q.enpty()){//当队列不为空,说明还没有处理完所有状态
State u=Q.front();
Q.pop();
for(枚举所有当前状态可以进行的决策/选择/行为){
State v=当前状态u惊醒当前决策得到的新状态;
if(当前状态v满足题目限制条件 && dis[v]==-1){
Q.push(v);
dis[v]=dis[u]+1;
}
}
}
}