关于深度优先搜索(bfs),广度优先搜索(bfs)的思考二三事

注:作者写这篇博客的目的其实不是因为自己掌握的很好想分享,而是作为一名小白想通过写博客的方式更好的掌握这两种方法。

关于深度优先搜索

深度优先搜索是用于图论中以深度优先方式遍历某个结点,当该结点的元素全部遍历完后,再遍历其他的同级结点。

再解释一下:比如说现在有一棵大树,如图,树上有一共7个结点,而我们需要的是结点6

 

你要搜索到当中的某个具体结点,一种办法是进行深度优先,即从A1到A2到A5返回到A1,再到A3,A6,找到了该结点

 对于找到该目标A6而言,一共进行了3步,如图,每一步都是向着最深的地方,之后返回到分叉的位置,再次向着最深处访问。

关于广度优先搜索

关于广度优先搜索则不同,对于结点的每一层,要遍历完上一层全体以后,再遍历第二层的第一个,如下图所示。

 对于这两种方法的应用,一般有两种方法,即使用栈/队列和迭代回溯法,根据博主的经验,一般bfs使用栈/队列的较多,而dfs使用回溯法的较多。

具体诠释

下面对具体例题,两种方法进行讲解,先给出具体的实现思路伪代码,就是说,bfs/dfs是有通法的,和之前提到的二分相同。不像贪心,方法是每题都不同,也不像动态规划,方法的类型种类很多。

1.dfs的递归伪代码

//伪代码

void dfs(初值){

        初始化条件

        剪枝写法(一般会有,也可能没有)

        if(终止条件){

                实现一定的操作

                 return;              

        }

        for(循环遍历这个点的深度){

                if(满足条件){

                                        进行操作

                               }

                迭代到下一个,即bfs(条件+1)

                还原操作

        }

}

2.bfs的栈/队列伪代码

void bfs(条件){

        queue<node> q;//定义一个queue,node为其数据类型

        赋初值,剪枝等常规操作

         node now;//储存当前状态的变量

        给node now赋值

        while(!q.empty()){

                now=q.front();

                q.pop();

                for(单个结点的情况遍历){

                        if(满足条件){

                                进行一系列操作

                                讨论下一个结点

                                q.push(入队某元素);

                                还原该结点的相关信息

                                }             

                }

        }

}

 用两个例题加以佐证:

3.迷宫问题

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

下图给出了一个迷宫的平面图,其中标记为 11 的为障碍,标记为 00 的为可以通行的地方。

010000
000100
001001
110000

迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。

对于上面的迷宫,从入口开始,可以按 DRRURRDDDR 的顺序通过迷宫, 一共 1010 步。其中 D、U、L、RD、U、L、R 分别表示向下、向上、向左、向右走。 对于下面这个更复杂的迷宫(3030 行 5050 列),请找出一种通过迷宫的方式,其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。

请注意在字典序中 D<L<R<UD<L<R<U。

01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000
 以bfs方式给出:
#include<bits/stdc++.h>
using namespace std;
const int row=30;
const int col=50;
int dirx[4]={0,0,1,-1};
int diry[4]={1,-1,0,0};
string ans;
const char dir[5]={'R','L','D','U'}; //以向下为x轴,向右为y轴 
int maze[row+1][col+1]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,1,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,1,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,0,
0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,1,0,0,1,0,1,
0,0,1,1,1,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,
0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1,1,
0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,
0,1,1,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,0,1,0,1,0,1,1,0,0,0,1,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,1,1,0,1,1,1,
0,0,0,0,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,1,0,0,0,0,0,0,0,
0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,1,0,
0,0,0,1,1,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,0,0,1,
0,1,1,0,0,0,1,1,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,
0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,0,1,0,1,0,1,1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,1,0,1,
0,1,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,0,0,
0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,1,
0,1,0,1,0,1,0,1,0,0,1,1,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,0,1,1,0,0,1,1,1,1,0,1,1,0,1,0,0,0,0,1,0,0,0,
0,1,0,1,0,1,0,1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,0,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,1,1,1,0,1,1,1,0,1,0,0,1,
0,1,0,0,0,0,0,0,0,1,0,1,1,0,0,0,1,0,0,0,0,1,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,1,0,0,
0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,1,1,0,1,0,1,0,0,1,
0,0,0,1,0,1,0,0,1,0,1,0,1,0,1,1,0,1,0,0,1,0,1,0,1,0,0,0,1,1,0,1,0,1,0,1,1,0,1,1,1,0,0,0,0,1,1,0,1,0,1,
0,1,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,1,0,
0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,
0,1,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,0,1,0,1,1,0,1,0,1,1,0,1,0,1,0,1,0,0,0,0,1,
0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,1,0,1,
0,1,0,1,0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,0,1,0,
0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,
0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,1,1,0,1,1,1,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,1,0,0,0,
0,0,0,0,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,1,1,
0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,
0,1,0,0,0,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,0,0,
0,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,1,
0,1,0,0,0,0,0,0,1,1,0,0,1,1,1,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,1,1,0,1,1,1,1,0,0,0
};
int best;
char a[row*col+10];
const int maxc=6;
int mins[row+1][col+1];
bool judge(int x,int y)//判断一个点是否越界 
{
	if(x>0&&x<=row&&y>0&&y<=col&&maze[x][y]==0)
	{
		return true;
	}
	else return false;
}
void dfs(int x,int y,int pos){
	if(pos>best)//剪枝写法 ,去掉没用的情况 
		return ;
	if(x==row&&y==col){
		string temp;
		for(int i=1;i<pos;i++)
		{
			temp+=a[i]; 
		}
		if(pos<best){
			ans=temp;
			best=pos;
	    }
	    else if(pos==best&&temp<ans)
	         ans=temp;
	    return ;
	}
	for(int i=0;i<4;i++){
		int tox=dirx[i]+x;int toy=diry[i]+y;
		if(judge(tox,toy)&&mins[tox][toy]>=pos+1){//剪枝写法  
			maze[tox][toy]=1;
			mins[tox][toy]=pos+1;
			a[pos]=dir[i];
			dfs(tox,toy,pos+1);
			maze[tox][toy]=0;
		}	
	}
}
int main(){
	memset(mins,1,sizeof(mins));
	best=1<<28;
	maze[1][1]=1;
	dfs(1,1,1);
	cout<<ans<<endl;
	return 0;
}
 
以dfs形式给出:
#include<bits/stdc++.h>
using namespace std;
#define maxn 50
const int row=30;
const int col=50;
int step=0;
string maze[30]={
"01010101001011001001010110010110100100001000101010",
"00001000100000101010010000100000001001100110100101",
"01111011010010001000001101001011100011000000010000",
"01000000001010100011010000101000001010101011001011",
"00011111000000101000010010100010100000101100000000",
"11001000110101000010101100011010011010101011110111",
"00011011010101001001001010000001000101001110000000",
"10100000101000100110101010111110011000010000111010",
"00111000001010100001100010000001000101001100001001",
"11000110100001110010001001010101010101010001101000",
"00010000100100000101001010101110100010101010000101",
"11100100101001001000010000010101010100100100010100",
"00000010000000101011001111010001100000101010100011",
"10101010011100001000011000010110011110110100001000",
"10101010100001101010100101000010100000111011101001",
"10000000101100010000101100101101001011100000000100",
"10101001000000010100100001000100000100011110101001",
"00101001010101101001010100011010101101110000110101",
"11001010000100001100000010100101000001000111000010",
"00001000110000110101101000000100101001001000011101",
"10100101000101000000001110110010110101101010100001",
"00101000010000110101010000100010001001000100010101",
"10100001000110010001000010101001010101011111010010",
"00000100101000000110010100101001000001000000000010",
"11010000001001110111001001000011101001011011101000",
"00000110100010001000100000001000011101000000110011",
"10101000101000100010001111100010101001010000001000",
"10000010100101001010110000000100101010001011101000",
"00111100001000010000000110111000000001000000001011",
"10000001100111010111010001000110111010101101111000"

};
bool vis[maxn][maxn];
const int dirx[4]={1,0,0,-1};
const int diry[4]={0,-1,1,0};
const char dir[5]={'D','L','R','U'};
bool judge(int x,int y)
{
	if(x>=0&&x<row&&y>=0&&y<col&&maze[x][y]!='1'){
		return true;
	}
	else return false;
}
struct node
{
	int x,y,step;
	char direction;
};
node father[maxn][maxn];
node now,nextpos;
void dfs(int x,int y){
	if(x==0&&y==0){
		return ;
	}
	else{
		dfs(father[x][y].x,father[x][y].y);
	}
	cout<<father[x][y].direction;
}   
    
void bfs(int x,int y){
	queue<node> q;
	now.x=x;
	now.y=y;
	now.step=0;
	q.push(now);
	father[x][y].x=10000;
	father[x][y].y=10000;
	father[x][y].direction=0;	
	vis[x][y]=true;
	while(!q.empty())//队列空为结束条件 
	{
		now=q.front();//表示队首元素 
		q.pop();
		for(int i=0;i<4;i++){
			int tox=now.x+dirx[i];
			int toy=now.y+diry[i];
			if(judge(tox,toy)&&!vis[tox][toy])
			{
				vis[tox][toy]=true;
				nextpos.x=tox;
				nextpos.y=toy;
				nextpos.step=now.step+1;
				q.push(nextpos);
				father[tox][toy].x=now.x;
				father[tox][toy].y=now.y;
				father[tox][toy].direction=dir[i];
			}
		} 
	 } 
}
int main()
{
	bfs(0,0);
	dfs(29,49);
	return 0;
}

小结:

bfs和dfs在搜索中具有很重要的应用,无论是在图论算法中,或者是需要查找的问题中均表现出众,但需要注意以下几点:

  • 要注意返回原状态,你在遍历了后一个状态以后,要返回前一个状态是需要返回到该情况下的值,比如迷宫的步数等
  • 要注意会正确使用栈和队列
  • 有时候对赋值和剪枝的应用
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值