BFS 讲解

BFS简介

宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。简单来说,bfs好像是一个耳听六路眼观八方的人,搜索时是一层一层的搜索的。BFS利用的数据结构是queue,空间复杂度为o(2^n),另外BFS可以用来解决最短路问题。BFS是一个从近到远的扩散过程。

基本思想

从初始状态S开始,利用规则,生成所有可能的状态。构成树的下一层节点,检查是否出现目标状态G,若未出现,就对该层所有状态节点,分别顺序利用规则。生成再下一层的所有状态节点,对这一层的所有状态节点检查是否出现G,若未出现,继续按上面思想生成再下一层的所有状态节点,这样一层一层往下展开。直到出现目标状态为止。

BFS的使用步骤

可以分为四个步骤:初始化(初始化队列和所求的值) -> 判空取队头(判断是否为空并取出队头) -> 拓展(利用队头去扩展) -> 判断入队(如果符合,将该点入队)。

void bfs(){
    queue<int>q;
    q.push(初始位置);
    //初始化

    while(q.size()){
        int t = q.front();
        q.pop();//取出队头的点,用该点向周围扩散。
        if(check(j)){       //如果该点可行就将它加入队列中
        q.psuh(j);      
        //实施相应的操作 
        }
    } 
} 

经典例题

好人何老板

题目描述

八十高龄的邓大爷在大街上摔倒了,因为众所周知的原因围观的路人都不敢去救助。恰好何老板下班路过,一向助人为乐的他赶紧抱起邓大爷往医院跑。但好心的何老板面临着一个问题,城市里面有很多医院,到底哪家医院最近呢? 城市地图用一个由数字0,1,2,3构成的n*m矩阵表示(n,m<=1000)。数字0表示可以行走的道路或空地。数字1表示邓大爷摔倒的位置。数字2表示不可通过的建筑物或障碍物。数字3表示医院。 何老板只能延上下左右四个方向移动,每走一步的距离是1。问到最近的医院需要走多少步?(地图中至少有一个可到达的医院)

输入格式

第一行,两个空格间隔的整数n和m
接下来是一个n*m的矩阵,用空格做间隔

输出格式

一个整数,表示最小的步数。

样例输入

5 8
3 0 0 0 0 2 0 3
2 0 0 2 3 0 2 0
0 2 0 2 0 3 0 2
0 1 0 2 0 0 0 0
0 0 0 0 0 0 0 3

样例输出

6

思路:每次向四个方向搜索,第一个找到的就是最短的方案
没找到就把当前位置设置为2,并继续寻找

代码如下:

#include<iostream>
#include<queue>
using namespace std;
int n,m,c[1010][1010];
int k,l;
struct node{
    int x,y,s;
    node(int x_,int y_,int s_){
        x=x_;
        y=y_;
        s=s_;
    }
};
int bfs(int x,int y){
    queue<node> f;
    f.push(node(x,y,0));
    int dx[4]={-1,1,0,0};
    int dy[4]={0,0,-1,1};
    while(f.size()){
        node a=f.front();
        f.pop();
        for(int i=0;i<4;i++){
            node b(a.x+dx[i],a.y+dy[i],a.s+1);
            if(b.x>0&&b.x<=n&&b.y>0&&b.y<=m){
                if(c[b.x][b.y]==3){
                    return b.s;
                }
                if(c[b.x][b.y]==0){
                    c[b.x][b.y]=2;
                    f.push(b);
                }
            }
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&c[i][j]);
            if(c[i][j]==1){
                k=i,l=j;
            }
        }
    }
    cout<<bfs(k,l);
} 

特性:

空间复杂度

因为所有节点都必须被储存,因此BFS的空间复杂度为 O(|V| + |E|),其中 |V| 是节点的数目,而 |E| 是图中边的数目。注:另一种说法称BFS的空间复杂度为 O(BM),其中 B 是最大分支系数,而 M 是树的最长路径长度。由于对空间的大量需求,因此BFS并不适合解非常大的问题。

时间复杂度

最差情形下,BFS必须寻找所有到可能节点的所有路径,因此其时间复杂度为 O(|V| + |E|),其中 |V| 是节点的数目,而 |E| 是图中边的数目。

最佳解 若所有边的长度相等,广度优先搜索算法是最佳解——亦即它找到的第一个解,距离根节点的边数目一定最少;但对一般的图来说,BFS并不一定回传最佳解。这是因为当图形为加权图 (亦即各边长度不同)时,BFS仍然回传从根节点开始,经过边数目最少的解;而这个解距离根节点的距离不一定最短。这个问题可以使用考虑各边权值,BFS的改良算法成本一致搜寻法(en:uniform-cost search)来解决。然而,若非加权图形,则所有边的长度相等,BFS就能找到最近的最佳解。

广度优先搜索算法能用来解决图论中的许多问题,例如:

  1. 寻找图中所有连接元件(Connected Component)。一个连接元件是图中的最大相连子图。
  2. 寻找连接元件中的所有节点。
  3. 寻找非加权图中任两点的最短路径。
  4. 测试一图是否为二分图。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值