目录

2024-12-28-深度搜索DFS和广度搜索BFS

深度搜索(DFS)和广度搜索(BFS)

深度搜索(DFS)

一、搜索方法:

沿出发顶点的第一条路径尽量深入,遍历路径上所有顶点;然后退回到该顶点,搜索其它路径,直到以该顶点为始点的所有路径的顶点都被访问,深度搜索算法是递归算法,因为对于没一个节点来说,执行的是同样的操作。

简单来说,深度搜素算法就是一条道走到黑,走不动了再回溯回去,选择其他路径,举个例子,对于下面的图,假设从1开始遍历:

https://img-blog.csdnimg.cn/20190717212121576.png?x-oss-

(1)第一步,访问结点1并标记

https://i-blog.csdnimg.cn/blog_migrate/9ccff0f42d9df4fbf3c51a82f92f767e.png https://i-blog.csdnimg.cn/blog_migrate/42b8d076cbd9bd9d676619c5d32ffc82.png https://i-blog.csdnimg.cn/blog_migrate/a0cfada640589359f2c2fa9f86be9fbb.png

https://i-blog.csdnimg.cn/blog_migrate/94aefa6d5628bc1d937f202f36a25dbe.png https://i-blog.csdnimg.cn/blog_migrate/42b8d076cbd9bd9d676619c5d32ffc82.png https://i-blog.csdnimg.cn/blog_migrate/3417ff45e9079d8cc9538a650b01dc2f.png

https://img-blog.csdnimg.cn/20190718093312846.png?x-oss- https://i-blog.csdnimg.cn/blog_migrate/42b8d076cbd9bd9d676619c5d32ffc82.png

int dxy[4][2]={//模拟上下左右四个方向
	-1,0,//向上(x减一,y不变)
	1, 0,//向下
	0,-1,//向左
	0, 1//向右
	}
void dfs(int x0,int y0,int x1,int y1)
{
	//(x0,y0)是出发点,(x1,y1)是目标点
	if(x0==x1&&y0==y1)//找到目标点
	{
		//执行操作如输出路径等
		return
	}
	for(int i=0;i<4;i++)//遍历四个方向每一个分支,对每一个分支都进行深度搜索
	{
		int dx=dxy[i][0];//移动后的横坐标
		int dy=dxy[i][1];//移动后的纵坐标
		if(坐标越界||遇到障碍物||...)//不满足条件
			continue;
		//执行操作
		dfs(dx,dy,x1,y1)//深度遍历
		//遍历结束恢复操作
	}
}

广度搜索(BFS)

一、搜索方法

广度搜索,顾名思义,就是更大范围内搜索,与深度搜索不同的是,深度搜索是一次搜索一条路径,一直搜索到走不通为止;而广度搜索是同时搜索所有路径,相当于一层一层地搜索,就好比波浪的扩展一样。此搜索方法跟树的层次遍历类似,因此宽度搜索一般都用队列存储结构。搜索原则:

(1)访问遍历出发顶点,该顶点入队

(2)队列不空,则队头顶点出队;

(3)访问出队顶点所有的未访问邻接点并将其入队;

(4)重复(2)(3),直到队空或者找到目标点

举个例子,还是对下面这个图进行广度遍历:

https://img-blog.csdnimg.cn/20190717212121576.png?x-oss-

https://i-blog.csdnimg.cn/blog_migrate/9ccff0f42d9df4fbf3c51a82f92f767e.png

https://i-blog.csdnimg.cn/blog_migrate/c64c2300d240d26bd93038f0312114af.png

https://i-blog.csdnimg.cn/blog_migrate/5b3ced9beda31e0fd35552b78d7f82c4.png

https://i-blog.csdnimg.cn/blog_migrate/7a1cc5d8108f014251f782440d146614.png

二、用途

虽然看似广度搜索一次扩张了很多个点,但实际上任然是一个结点一个结点地搜索,只是它是以层层扩张的方式进行搜索。广度搜索也常用于解决图的遍历,在求一个点到另一个点的最短距离时,广度搜索比深度搜索更有优势,因为广度搜索是层层遍历的,所以一定存在某条路径最先到达目标点,只要找到目标点后就退出,就不用搜索所有点。

广度搜索也是分支限界法的主要算法(当然,分支限界也可能是广度搜索和宽度搜索的结合)。广度搜索最常解决的问题类型是:求从某一个状态到另一个状态的最小步数,每一个状态对应多个(扩展结点个数)不同的操作。

三、算法模板

#include<iostream>
#include<queue>
using namespace std;
struct state
{
	int a,b;//存储相应信息
	int step;//存储当前结点的步数
};
queue<state>Q;
int bfs(int a,int b,int A,int B)//返回最小步数
{
	//参数a,b是初始状态,
	//参数A,B是目标状态判断条件;
	while(!Q.empty())Q.pop();//清空队列
	state P;
	P.a=a;P.b=b;P.step=0;//初始结点
	Q.push(P);//初始结点入队
	while(!Q.empty())//队列非空
	{
		state head=Q.front();//保存队头
		Q.pop();//队头出队
		//以下扩展每个结点的邻接结点*************************
		state p=head;
		p.a=...//执行操作
		p.b=...//执行操作
		p.step++;//步数加一
		//判断p.a,p.b是否合法(剪枝处理)
		if(ok(p.a,p.b))
		{
			if(p.a==A&&p.b==B)//判断该状态是否满足目标状态
			return p.step;//返回步数
			Q.push(p);//否则入队
		}
		
		//扩展其他结点
		......
		//扩展结点结束*************************************
	}
	return -1;//不能到达目标状态,返回-1;
}

经典例题

68747470733a2f2f:626c6f672e6373646e2e6e65742f71715f3432373132333531:2f61727469636c652f64657461696c732f3936333633363931