bfs和dfs小记

看到一道题,题解总结了bfs和dfs的模板,来记录下。 

一:bfs

bfs是按一层一层来访问的,适合有目标求最短路的步数,你想想层层搜索每次层就代表了一步。bfs优先访问的是兄弟节点(相邻的节点),只有这一层全部访问完才能访问下一层,也就是说bfs第几层就代表当前可以走到的位置(结点).

二:dfs


dfs是按递归来实现的,它优先搜索深度,再回溯。优先访问的是没有访问过的子节点。DFS多用于连通性问题因为其运行思想与人脑的思维很相似,故解决连通性问题更自然。

    Difference between BFS and DFS

以下是bfs和dfs的简单框架 

一:bfs

模板

第一种://bfs模板
struct ed
{
	.....
}
deque<ed>q;//当然用queue也可以
void bfs()
{
	标记起点 
	起点入队列 
	while(!q.empty())//队列不为空 
	{
		ed nw=q.front();//返回队首
		for(拓展出接下来可能的状态)
		{
			ed nxt;
			记录这一状态
			判断状态是否合法 
			标记状态 
			q.push_back(nxt);//状态入队列 
		}
		q.pop_front();//弹出队首 
	}
}


第二种:
/** 
 * 广度优先搜索 
 * @param Vs 起点 
 * @param Vd 终点 
 */  
bool BFS(Node& Vs, Node& Vd){  
    queue<Node> Q;  
    Node Vn, Vw;  
    int i;  

    //初始状态将起点放进队列Q  
    Q.push(Vs);  
    hash(Vw) = true;//设置节点已经访问过了!  

    while (!Q.empty()){//队列不为空,继续搜索!  
        //取出队列的头Vn  
        Vn = Q.front();  

        //从队列中移除  
        Q.pop();  

        while(Vw = Vn通过某规则能够到达的节点){  
            if (Vw == Vd){//找到终点了!  
                //把路径记录,这里没给出解法  
                return true;//返回  
            }  

            if (isValid(Vw) && !visit[Vw]){  
                //Vw是一个合法的节点并且为白色节点  
                Q.push(Vw);//加入队列Q  
                hash(Vw) = true;//设置节点颜色  
            }  
        }  
    }  
    return false;//无解  
}  

二:dfs

模板:

第一种://也是一次走到底,然后回溯
void dfs()
{
	for(拓展状态)
	{
		判断合法
		记录
		dfs(继续搜);
		回溯;
	}
}
*/

第二种:
void dfs(){
    搜索上下左右四个位置是否符合条件。
    if(符合条件) {
        标记
        dfs()
    }
}

根据模板,记录一道题,方便理解

题目:

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

输入格式

第一行两个整数代表矩阵大小 n 和 m。

接下来 n 行,每行一个长度为 m 的只含字符 0 到 9 的字符串,代表这个 n \times m n×m 的矩阵。

输出格式

一行一个整数代表细胞个数。

输入输出样例

输入 #1 

4 10
0234500067
1034560500
2045600671
0000000089

输出 #1

其实思路很简单就是连通块,为了便于理解,我特地将数字0标红,结果发现就是只有四个被数字0包裹住的连通块。

首先是bfs的解法:

#include<iostream>
#include<deque>//双向队列头文件
using namespace std;
struct pp
{
	int x, y;
};//初始化函数
deque<pp> q;//队列
int n, m, ans = 0;//n行m列,ans为答案 
int a[105][105];//存矩阵 
bool used[105][105];//记录是否走过 
int dx[4] = { -1,1,0,0 };//向上下左右走一步行号和列好的改变 
int dy[4] = { 0,0,-1,1 };
void bfs(int sx, int sy)//bfs 
{
	pp st;
	st.x = sx; st.y = sy;
	used[sx][sy] = 1;
	q.push_back(st);
	while (!q.empty())
	{
		pp nw = q.front();
		for (int i = 0; i < 4; i++)
		{
			pp nxt = nw;
			nxt.x += dx[i];
			nxt.y += dy[i];
			if (a[nxt.x][nxt.y] == 0 || used[nxt.x][nxt.y] == 1) continue;//为零的就不用在管他了
			used[nxt.x][nxt.y] = 1;//把这一连通块的点染色 
			q.push_back(nxt);
		}
		q.pop_front();//因为是双向队列。这可以让遍历过的数出去
	}
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			scanf("%1d", &a[i][j]);//遍历地图
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			if (used[i][j] == 0 && a[i][j] != 0)
			{
				bfs(i, j);
				ans++;//若这一连通块没搜过ans++ 
			}
		}
	}
	cout << ans;
	return 0;
}

其次时dfs的方法,因为都是连通块,相差不太大

#include<iostream>
using namespace std;
int n, m, ans = 0;
int a[105][105];
bool used[105][105];
int dx[4] = { -1,1,0,0 };
int dy[4] = { 0,0,-1,1 };
void dfs(int x, int y)
{
	used[x][y] = 1;
	for (int i = 0; i < 4; i++)
	{
		int nx = x + dx[i];
		int ny = y + dy[i];
		if (a[nx][ny] == 0 || used[nx][ny] == 1) continue;
		dfs(nx, ny);//回溯
	}
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			scanf("%1d", &a[i][j]);//遍历地图
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			if (used[i][j] == 0 && a[i][j] != 0)
			{
				dfs(i, j);
				ans++;//寻找连通块
			}
		}
	}
	cout << ans;
	return 0;
}

总之

一个着重队列,一个着重是回溯,嗯,就这样。

BFSDFS都是常用的图搜索算法。它们的区别在于搜索的策略和复杂度。引用中提到,对于给定的问题,BFS是较佳的算法。 BFS(广度优先搜索)是一种逐层扩展搜索的算法。它从起始节点开始,逐层遍历邻接节点,直到找到目标节点或遍历完整个图。BFS使用队列来存储待访问的节点,确保按照层级的顺序进行搜索。BFS算法的时间复杂度为O(V + E),其中V是节点的数量,E是边的数量。 DFS(深度优先搜索)是一种递归实现的搜索算法。它从起始节点开始,不断沿着路径深入直到无法继续或找到目标节点,然后回溯到上一个节点,继续探索其他路径。DFS使用栈来存储待访问的节点,它的搜索路径是深度优先的。DFS算法的时间复杂度为O(V + E),其中V是节点的数量,E是边的数量。 在实际应用中,BFSDFS都有各自的优缺点。BFS通常用于解决最短路径和最小生成树等问题,而DFS更适合用于寻找所有可能的解,如图的连通性和拓扑排序等问题。选择使用哪种算法取决于具体的问题和需求。引用中提到,我们在学习数据结构时通常会接触到BFSDFS算法,尤其是在图的遍历和二叉树的遍历中经常用到。 总结起来,BFSDFS是常用的图搜索算法,它们在搜索策略和复杂度上有不同。BFS逐层扩展搜索,适用于最短路径和最小生成树等问题。DFS深度优先搜索,适用于寻找所有可能解的问题。具体选择哪种算法取决于问题的特点和需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [熬夜怒肝,图解算法!BFSDFS的直观解释](https://blog.csdn.net/c406495762/article/details/117307841)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值