【c++】广度优先搜索

广度优先搜索——概念

广搜又叫宽度优先搜索,它是一种与深搜完全不同的搜索策略, 它是从源点出发,逐层搜索出所有的点。

 例如:遍历左图中的所有节点

深度优先搜索的遍历输出为: 1-2-5-6-8-3-4-7

广度优先搜索的遍历输出为: 1-2-3-4-5-6-7-8

宽搜一般用在求最少多少步的情况,由于它的逐层特性, 它能保证搜到最小或最少的解。

广度优先搜索——算法框架(重点)

在广搜中我们需要用到队列的知识,因此我们先了解一下队列

队列基本原理入下图

 再来了解一下队列的基本操作

·empty() 判断queue容器是否为空

·size() 返回当前queue容器的大小(既有多少元数据)

·front() 访问queue容器的第一个(首部)元素

·back() 访问queue容器的(尾部)最后一个元数据

·push() 向queue容器中插入新的元数据

·emplace() 构造并插入元数据 ·pop() 删除队首数据 ·

swap() 交互两个queue容器的内容

了解了队列,我们就可以学习广搜代码了

void bfs(){ 
	初始化,初始状态入队列q表;
	while(!q.empty())
	{ 
		for(i=1;i<=max;i++) max为产生子结点的规则数
		{ 根据规则数产生子结点;
 			if(子结点符合条件&&未访问)
 			{
		 	q.push(子结点);
			}新结点放在队尾
 		if(新结点是目标结点)输出并退出;
 		}
 		新结点=q.front();q.pop();始终从头开始搜索
	}
}

广搜经典例题

1.细胞

【问题描述】一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下 左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。

如输入阵列

4 10

0234500067

1034560500

2045600671

0000000089

输出

【输入】 第一行为矩阵的行n和列m; 下面为一个n×m的矩阵。

【输出】 细胞个数。

【算法分析】

① 读入M*N 矩阵阵列,并将其转化成bool值存入bz[]数组中;

② 沿bz数组矩阵从上到下,从左到右,找到遇到的第一个细胞;

③ 细胞位置入队列h,并沿其上下左右四个方向的细胞位置入队,入队后的bz数组设为false;

④ 将h队的队头出队,并沿其上下左右四个方向的细胞位置入队,入队后的bz数组设为false;

⑤ 重复4,直到h队为空;

⑥ 重复2,直到矩阵无细胞;

⑦ 输出找到的细胞数;

【代码实现】

void bfs(int x,int y){
	tmp.x=x;tmp.y=y;// tmp为结构体代表(x,y)
	q.push(tmp);
	while(!q.empty()){
		tmp=q.front(); q.pop();//顶结点出队
		int xx=tmp.x, yy=tmp.y;
		if(xx<1 || xx>m || yy<1 || yy>n) continue;
		if(a[xx][yy]==0 || b[xx][yy]==1) continue;
		b[xx][yy]=1;// 访问过的结点标记
		for(int i=0;i<4;i++){
 			tmp.x=xx+dx[i];tmp.y=yy+dy[i]; 
			q.push(tmp); 
		} 
	} 
}

2.走迷宫 

【问题描述】一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可 以走。给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在 水平方向或垂直方向走,不能斜着走。

【输入】 第一行是两个整数,R和C,代表迷宫的长和宽。( 1≤ R,C ≤ 40) 接下来是R行,每行C个字符,代表整个迷宫。 空地格子用‘.’表示,有障碍物的格子用‘#’表示。 迷宫左上角和右下角都是‘.’。

【输出】 输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括 起点和终点。

样例输入

5 5
..###
#....
#.#.#
#.#.#
#.#..

样例输出 

9

【问题分析】

本题求解最少步数,其过程实际为从起点,根据移动规则广搜每一点, 直到到达终点。则需要解决一下问题:

① 构建数据结构并初始化;

② 建立移动规则;

③ 将起点(1,1)放入队首,将其前趋设置为0;

④ 从队首结点出发出发根据移动规则构搜索到能到达的所有子节点;

⑤ 如果 该子节点 符合选取规则 则记录该点的前趋点,同时该点入队列;

⑥ 重复2步,直到到达终点或者超出边界;

【代码实现】

void bfs(int x,int y){
	q.push((zb){1,1,1});
	while(!q.empty()){
		zb t=q.front();
		q.pop();
		for(int i=0;i<4;i++){
			int xx=t.x+dx[i];
			int yy=t.y+dy[i];
			if(xx==n&&yy==m){
				cout<<t.bs+1;
				return;
			}
			if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&a[xx][yy]=='.'&&book[xx][yy]==0){
				book[xx][yy]=1;
				q.push((zb){xx,yy,t.bs+1});
			}
		}	
	}
}

广搜就到这里

记得多做题

端午节安康!!!

完结撒花!!!

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
C++中的广度优先搜索(BFS)是一种用于图形遍历的算法。它从给定的起始节点开始,逐层遍历图形中的节点,直到找到目标节点或遍历完整个图形。下面是一个简单的C++代码示例来实现广度优先搜索: ```cpp #include <iostream> #include <queue> #include <vector> using namespace std; // 图形的节点结构 struct Node { int value; vector<Node*> neighbors; }; // 广度优先搜索函数 void BFS(Node* startNode, int targetValue) { queue<Node*> q; vector<Node*> visited; q.push(startNode); visited.push_back(startNode); while (!q.empty()) { Node* currentNode = q.front(); q.pop(); if (currentNode->value == targetValue) { cout << "目标节点已找到!" << endl; return; } for (Node* neighbor : currentNode->neighbors) { if (find(visited.begin(), visited.end(), neighbor) == visited.end()) { q.push(neighbor); visited.push_back(neighbor); } } } cout << "未找到目标节点!" << endl; } int main() { // 创建图形节点 Node* node1 = new Node{1}; Node* node2 = new Node{2}; Node* node3 = new Node{3}; Node* node4 = new Node{4}; Node* node5 = new Node{5}; // 构建图形关系 node1->neighbors.push_back(node2); node1->neighbors.push_back(node3); node2->neighbors.push_back(node4); node3->neighbors.push_back(node4); node4->neighbors.push_back(node5); // 在图形中进行广度优先搜索 BFS(node1, 5); return 0; } ``` 这段代码首先定义了一个节点结构 `Node`,其中包含一个值和一个邻居节点的向量。然后,定义了一个 `BFS` 函数来执行广度优先搜索。在 `BFS` 函数中,使用队列来存储待访问的节点,并使用一个 `visited` 向量来记录已访问过的节点。然后,从起始节点开始,逐层遍历图形中的节点,直到找到目标节点或遍历完整个图形。 在 `main` 函数中,创建了一些节点,并构建了它们之间的关系。然后,调用 `BFS` 函数来执行广度优先搜索,并传入起始节点和目标值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hear the Wind Sing.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值