(深度优先遍历和宽度优先遍历)DFS和BFS(1)

目录

文章目录

前言

一、什么是DFS?

二、什么是BFS?

三、题目演示(一个简单的题目,帮助理解)


前言

DFS和BFS在解决能够解决我们见到的很多图论问题,两者有很大的区别,但有些时候,两者又有相同的地方。比如都能通过搜索,来达到某种目的。接下来我们通过两道试题来简单的对DFS和BFS进行理解。

一、什么是DFS?

    DFS就相当于是一个非常耿直,执着的人,当它走某条路的时候,只要不走到无路可走他就一直往前走,直至无路可走,然后就退回一步,去另一条路搜索。

(深度优先遍历和宽度优先遍历)DFS和BFS(1)_第1张图片

二、什么是BFS?

   BFS就相当于是一个平稳的人,它在搜索的时候是一层一层的搜索,直至搜索到我们想要的结果。

(深度优先遍历和宽度优先遍历)DFS和BFS(1)_第2张图片

三、题目演示(一个简单的题目,帮助理解)

题目:

(深度优先遍历和宽度优先遍历)DFS和BFS(1)_第3张图片

   这一题用BFS和DFS都可以,但是用DFS搜索的,搜索的步骤比较多,有些过程会重复搜索,会导致时间复杂度高,会导致Time Limit Exceeded。

  DFS题解:

差不多解这样的题都会使用同一个模板。只不过过程不太一样而已,过程如下。(解析都在题目上写着) 

#include 
#include 
using namespace std;
const int N=200;
int a[N][N],book[N][N],n,m,mi=9999999;
pair p[N];
void dfs(int x,int y,int k)
{
	int next[4][2]={{0,1},{1,0},{-1,0},{0,-1}};//这一步相当于是移动
	int kx,ky;
	if(x==n&&y==m)//当搜索到合适的位置的时候,输出并返回 
	{
		if(k"; //题目上不必写这一步,这一步是用来
	//最短路时的过程是怎样的,使用pair记起来,当找到一个比原来步数小的就输出一下过程 
	cout<<"("<n||ky<=0||ky>m)//有一部分分支“很耿直”,直接撞南墙到出界 
		continue;
		if(book[kx][ky]==-1&&a[kx][ky]==0)//这一步在“一条路往南走的过程”没走过,而且这个位置不围墙 
		{
			p[k].first=kx;
			p[k].second=ky;
			book[kx][ky]=0;
			dfs(kx,ky,k+1);
			book[kx][ky]=-1;//当走完这一条路还要寻找其他可行的路,所以要让这个还原 
		}
	}
	return ;
}
int main()
{
	memset(book,-1,sizeof(book));
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	cin>>a[i][j];
	book[1][1]=0;
	dfs(1,1,0);//意思是从(1,1)位置走,现在是0步 
	cout<<"最短路"<

 (深度优先遍历和宽度优先遍历)DFS和BFS(1)_第4张图片

 搜索次数太多导致了超时 

BFS题解:

用BFS会很省时间,因为每一个位置只列举了一次,但是BFS比较浪费空间。 

代码如下(示例):

//宽度优先遍历
#include 
#include 
using namespace std;
const int N=110;
struct PI
{
    int x;
    int y;
    int s;//用来记录走第几步 
    int f;//来储存这一步的上一步是那一步 
} a[N*N];//用数组来模拟队列。 
int main()
{
    int n,m,flag=1;
    cin>>n>>m;
    int book[n+1][m+1];
    int nu[n+1][m+1];
    memset(book,-1,sizeof(book));//将book数组内的值全部置为-1,
    //用来判断相对应的点是否走过。
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        cin>>nu[i][j];//输入对应的值(0表示可以走,1表示墙,走不通) 
    int head=0,tail=0;//对队列初始化,头指针和尾指针都指向0
    int next[4][2]={{0,1},{1,0},{-1,0},{0,-1}};//这一步相当于是移动
    a[tail].x=1;
    a[tail].y=1;
    a[tail].f=0;
    a[tail++].s=0;//从(1,1)点出发(可以更改) 
    while(tail>=head)
    {
        for(int i=0;i<4;i++){
        int kx=a[head].x+next[i][0],ky=a[head].y+next[i][1];
        if(kx<=0||kx>n||ky<=0||ky>m)//判断是否越界,越界之后不再进行以后的操作
        continue;
        if(book[kx][ky]==-1&&nu[kx][ky]==0)//证明这一步没有走过,并且这个位置不是墙
        {
            book[kx][ky]=0;//这一步走过了,以后都不需要再走了
            a[tail].x=kx;
            a[tail].y=ky;
            a[tail].s=a[head].s+1;//接着你上一次走的走。因为这是队列,先把走某一步的处理完
            //才能再继续处理下一步的。
            a[tail++].f=head;//他的上一步为head(头指针的位置);
             //宽搜和深搜不同,不需要将book数组进行还原,每一个格子最多走一步 
         } 
         if(kx==n&&ky==m)
         {
             flag=0;//在这里标记一下,如果找到结果,直接打断所有的循环 
              break;//搜索到了我们想要的点,直接输出即可
         }
        }
        if(flag==0)
        break; 
         //如果还没有找到,那就继续寻找,让头指针移动
         head++;  
    } 
     cout<

(深度优先遍历和宽度优先遍历)DFS和BFS(1)_第5张图片(深度优先遍历和宽度优先遍历)DFS和BFS(1)_第6张图片

 小小的总结一下:

   BFS和DFS各有好处,DFS(一般用栈来实现)比较耿直,其搜索的过程比较复杂,很多过程重复搜索,但其能找到我们想要的答案,空间复杂度低。而BFS(一般用队列来实现)就是一层一层的搜索,直至搜索到我们想要的结果就结束,其搜索没有重复的过程,其空间复杂度较高。两者没有谁好谁坏,只是二者适用于不同搜索类型的题。

你可能感兴趣的:(算法,c++,深度优先)