[算法]BFS(广度优先搜索)C++

1.BFS简介
宽度优先搜索算法(Breadth First Search,又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
BFS一般由队列实现,且总是按层次的顺序进行遍历。
2.算法讲解
求解下图迷宫中从起点到终点的最少步数:
在这里插入图片描述
①访问A(第一层),发现从A出发能到达B和C(第二层), 因此接下来需要B和C
②访问B (第二层),发现从B出发能到达D和E (第三层),因此待第二层的结点全部访问完毕后需要访问D和E。
③访问C (第二层),发现从C出发能到达F和G (第三层),因此待第二层的结点全部访问完毕后需要访问F和G,且它们排在D和E之后。
④由于第二层访问完毕,因此需要访问第三层。访问D (第三层),发现从D出发能到达H、I、J(第四层),因此待第三层的结点全部访问完毕后需要访问H、I、J。
⑤访问E (第三层),发现从E出发能到达K、L、 M (第四层),因此待第三层的结点全部访问完毕后需要访问K、L、 M。
⑥访问F(第三层),发现F是死胡同,没有能直接到达的新结点,因此不予理睬。
⑦访问G(第三层),发现G是出口,算法结束,至于那些第四层还没有访问的结点,就可以不用去访问了。
上面的算法很像一个入队出队的过程:
①先在队列中放置初始点A,然后取出队首元素A,将A直接相连的B与C入队,此时队列内元素为{B, C}。
②队首元素B出队,将B直接相连的D与E入队,此时队列内元素{C,D,E}。
③队首元素C出队(注意:队列的特性是先进先出,因此这里不是D出队),将C直接相连的F与G入队,此时队列内元素为{D,E,F,G}。
④队首元素D出队,将D直接相连的H、I、J入队,此时队列内元素为{E,F,G,H,I,J}。
⑤队首元素E出队,将E直接相连的K、L、M入队,此时队列内元素为{F,G,H,I,J,K,L,M}。
⑥队首元素F出队,没有与F直接相连的新结点,此时队列内元素为{G,H,I,J,K,L,M}。
⑦队首元素G出队,找到出口,算法结束。
3.模板
因此广度优先搜索(BFS) 一般由队列实现, 且总是按层次的顺序进行遍历,其基本写法如下(可作模板用):

void BFS(int s) {
	queue<int> q;
	q.push(s) ;
	while (!q. empty()) {
		取出队首元素top;
		访问队首元素top,访问可以是任何事情;
		将队首元素出队;
		将top的下一层结点中未曾入队的结点全部入队并设置为已入队;
}

4.实例
给出一个m*n的矩阵,矩阵中的元素为0或1.称位置(x,y)与其上下左右四个位置是相邻的。如果矩阵中有若干个1是相邻的(不必两两相邻),那么称这些1构成了一个块。
求给定的矩阵中块的个数
0 1 1 1 0 0 1
0 0 1 0 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 1 0
1 1 1 0 1 0 0
1 1 1 1 0 0 0

#include<iostream>
#include<queue>
using namespace std;
const int maxn=10;
struct node{
	int x,y;//元素的位置
}Node;

int n,m;	//矩阵大小为n*m 
bool inqueue[maxn][maxn]={false};	//是否入队 
int matrix[maxn][maxn];	//矩阵 
int a[4]={0,0,1,-1};
int b[4]={1,-1,0,0};

bool judge(int x,int y){	//判断(x,y)是否需要被访问
	//如果超出边界则退出
	if(x>=n||y>=m||x<0||y<0) return false;
	//如果当前位置的元素是0或者已经入过队则退出
	if(matrix[x][y]==0||inqueue[x][y]==true) return false;
	return true;
} 
void BFS(int x,int y){
	queue<node> q;
	Node.x=x,Node.y=y;
	q.push(Node);
	inqueue[x][y]=true;
	while(!q.empty()){
		node top=q.front();
		q.pop();
		for(int i=0;i<4;i++){
			int newX=top.x+a[i];
			int newY=top.y+b[i];
			if(judge(newX,newY)){
				Node.x=newX,Node.y=newY;
				q.push(Node);
				inqueue[newX][newY]=true;
			}
		}
	} 
}
int main(){
	int num=0; 
	cin>>n;
	cin>>m;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			cin>>matrix[i][j];
		}
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			//访问元素为1并且没有入队过的数 
			if(matrix[i][j]==1&&inqueue[i][j]==false){
				num++;
				BFS(i,j);	
			}
		}
	}
	cout<<num;
	return 0;
} 

5.参考书籍
《算法笔记》
6.其他题目
链接:
http://codeup.cn/contest.php?cid=100000609.
https://leetcode-cn.com/tag/breadth-first-search/.

ps:
第一次博客,有点偷懒不愿意做图,也借鉴了很多其他的博客以及有关算法的书籍说是搬运也不为过,我只是想记录一下自己的学习过程。之后会搭建自己的博客,然后再将内容转过去。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值