DFS和BFS

一、前导

先分别了解一下深度搜索和广度搜索

深度搜索: 深度搜索的遍历过程简单来说就是一路走到底再往回走。例如当前最新节点为 v,那么我们先判断该点是否还有其他未搜索过的边,如果有直接进入第一个发现的新节点。 但如果没有发现新的边了,就回到上一节点再探寻上一节点是否有其他边,如果没有就一直回退直到所有节点探索完毕或者达到目的。

广度搜索: 广度搜索就是一个地毯式的扩展搜索, 以初始节点为中心向外扩散搜索。例如初始节点为 v,那么先遍历 v 可以达到的所有边,然后再以此遍历达到的新节点可以到达的边。

了解完深度和广度的基本思路后,我们分别做一个具体的介绍

二、 深度搜索DFS

1.DFS的运用

我们首先得知道DFS的代码实现是基于递归实现的,并且了解DFS最重要的方法—回溯法。回溯法很好理解,就是使用完一个点后,这个点没有了作用或者不符条件了,那么就 “清扫现场” 即清除当前节点的访问状态。下图就是一个回溯搜索过程:
在这里插入图片描述

列题:
迷宫 (题号待补)
就是在一个二维矩阵中寻找出路
马走日 (题号待补)
就是象棋中马的移动,比迷宫稍复杂一点,以为马的访问方向是一个日型。

2. DFS的基础模板

  • 邻接矩阵构图的模板 (连通图)
const int maxn = 1100;
int g[maxn][maxn];	//矩阵定义
bool vis[maxn];		//访问记录

void DFS(int now, int n)	//now 表示当前节点号, n为矩阵大小
{
	if(vis[now]) return;	//如果节点访问过,那么终止下搜
	vis[now] = true;		//如果没有访问过就标记访问
	//printf("%d",now);	输出访问路径 可以此观察搜索顺序
	for(int i = 0; i < n; i++)
		if(g[now][i])		//如果 now 到 i 有边
				DFS(i,n);	//把 i 当作新的出发节点继续搜索
	//回溯
	vis[now] = false;
}
  • 非联通图

非联通图的实现就得多一个条件,记录初始节点start。 当start的所有联通点都遍历过后,再判断是否有节点没有遍历,如果有那么就是有非联通的图,那么我们就把该点作为新的 start继续遍历。

const int maxn = 1100;
int g[maxn][maxn];	//矩阵定义
bool vis[maxn];		//访问记录

void DFS(int now, int n,int start)	
{
	if(vis[now]) return;	
	vis[now] = true;		
	//printf("%d",now);	输出访问路径 可以此观察搜索顺序
	for(int i = 0; i < n; i++)
		if(g[now][i])		
				DFS(i,n,start);	
	//在一个初始节点的所有连接点都探索完
	//判断是否还有点没有探索
	for(int i = 0; i < n && now == start; i++)
		if(vis[i] == 0)
			DFS(i,n,i);
	
	//回溯
	vis[now] = false;
}
  • 简易模板
//状态可以有更多
void dfs(int now, int n, int start, int depth)	//当前点、大小、起始点、深度
{
	//访问条件
	if(vis[now]) return;
	//标记访问
	vis[now] = true;
	//特判条件
	if(now == end)	//举个列子到达了终点
	{
		//需要的操作
		cout << "到达目的了" << endl;		
	}
	//循环遍历
	for(int i = 0; i < n; i++)
		if(g[now][i])
		{
			//需要的操作,如记录或者输出
			DFS(i,n,start,depth++);
		}
	//回溯
	vis[now] = 0;
} 

3.剪枝

在题目中除了状态和目的条件的限制外,还有重要的时间限制。如果没有限制的对所有节点访问,在数据量大的时候可能就会出现超时了。例如走迷宫,当迷宫是一个20×20的矩阵时,访问量仅有400个节点,但如果时3000×3000时访问量就到达了9000000的大数目必然会超时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值