关于BFS广度优先搜索的一些个人理解

对于BFS,其实相比之下比DFS更加简单一些。

如果说DFS是为了走出一条最深的路径,那么BFS就是更像是为了层层扩张来达到访问所有节点的目的,例如树中的层序遍历,也可以认为是一种BFS;

BFS更像是逐层扩散的过程,所以BFS不需要回溯,所以也就不需要递归,更多的实现方式是利用队列,来进行层序输出;之前刷题中,也利用过队列进行过BFS的逐层访问,来记录树的层数,其实现在想想,利用DFS更直观一点;

其实BFS自己接触比较多的在图论和树论里,这里补充两个问题来辅助一下BFS的了解;

这道题是书上给出的经典实例,目的是找出矩阵中的各个不连通的块;

对于这个问题,就可以很好的采用BFS来解决;

代码如下所示:

#include<cstdio>
#include<stdlib.h>
using namespace std;
const int maxn=100;
struct node{
    int x,y;
}Node;
int n,m;
int matrix[maxn][maxn];
bool inq[maxn][maxn]={false};
int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};
//注意这里是为了进行BFS访问时候,可以生成上下左右四个方向的坐标
bool judge(int x,int y){
    //判定条件
    if(x>=n||x<0||y>=m||y<0)
        return false;
    if(matrix[x][y]=0||inq[x]==true)
        return false;
    return true;
}
void BFS(int x,int y){
    queue<node>Q;
    Node.x=x,Node.y=y;
    Q.push(Node);
    while(!Q.empty()){
        node top=Q.front();
        Q.pop();
        for(int i=0;i<4;i++){
            int newX=top.x+X[i];
            int newY=top.y+Y[i];
            if(judge(newX,newY)){
                //当可以进行访问
                Node.x=newX;
                Node.y=newY;
                Q.push(Node);
                inq[newX][newY]=true;
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int x=0;x<n;x++){
        for(int y=0;y<m;y++){
            scanf("%d",&matrix[x][y]);
        }
    }
    int ans=0;
    for(int x=0;x<n;x++){
        //挨个进行访问从而遍历出不同的块
        for(int y=0;y<m;y++){
            if(matrix[x][y]==1&&inq[x][y]=false){
                ans++;
                BFS(x,y);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

这里要注意一个点,之前自己写BFS的时候完全没想过:

上述的代码最后一行并不是标志访问没有,而是有没有入队,这是一个很重要的差别;

之前如果只是判断是否访问,是先执行入队在进行判别,这样会造成很多的出队入队操作,造成不必要的时间浪费;所以如果判断入队没有,会减少不必要的入队出队操作,降低时间复杂度;

还有,要注意STL中queue的一个特性,入队的都只是副本,对队列中的元素进行改变并不影响初始值,所以一般queue最好存储下标索引,避免更改造成的不便;

猜你喜欢

转载自blog.csdn.net/InNoVaion_yu/article/details/86751691