DFS(深度优先搜索 Depth First Search)

白话理解:

我觉得其实就是暴力把所有的路径都搜索出来,运用回溯,保存这次的位置,深入搜索,都搜索完了便回溯回来,搜下一个位置,直到把所有最深位置都搜一遍,要注意的一点是,搜索的时候有记录走过的位置,标记完后可能要改回来

我的最白的理解就是,一个人每条路都一直走到黑,到头了再返回来,全走一遍,找出你想要的路。

回溯法:

回溯法是一种搜索法,按条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法;

图解:

例如这张图,从1开始到2,之后到5,5不能再走了,退回2,到6,退回2退回1,到3,一直进行;
DFS和BFS的思想探究_回溯法
理解这种方法比较简单,难的是要怎么用

伪代码理解:

简单来说就是这样:

void dfs()
{
	访问过的点 = 1;
	cout << " " << a;
	for (int i = 0; i < N; i++)
	{
		if (其他点到这个点有边并且该点未被访问过)	// 该点未访问过并且其他点到这个点有边
		{
			// Dfs递归
			dfs();
		}
	}
}

详细来说:

void dfs(int deep)
{
	int x=deep/n,y=deep%n;
	// 回溯结束判断条件
	if(符合某种要求||已经不能在搜了)
	{
		做一些处理操作;
		return ;
	}
	
	// 判断当前回溯结点是否满足条件,或者处理数据
	// 这里可能会有多种条件,可能要循环什么的
	if(符合某种条件且有地方可以继续搜索的)
	{
		a[x][y]='x';	// 可能要改变条件,这个是瞎写的
	        dfs(deep+1,sum+1);	// 搜索下一层
		a[x][y]='.';	// 可能要改回条件,有些可能不用改比如搜地图上有多少块连续的东西
	}
	
	// 最后可能要判断一些特殊条件,处理一些特殊数据,一般没有
}
BFS(宽度/广度优先搜索 Breadth First Search)

白话理解:

我觉得就是从某点开始,走四面可以走的路,然后在从这些路,在找可以走的路,直到最先找到符合条件的,这个运用需要用到队列(queue)。

我的最白的理解就是,一群人(无数),碰到了一个岔路,就派出去一队人继续走,遇到岔路再分,让人们一次性的遍布整个图,最后找出你想要的路。

DFS和BFS的思想探究_宽度优先_02

图解:

还是这张图,从1开始搜,有2,3,4几个点,存起来,从2开始有5,6,存起来,搜3,有7,8,存起来,搜4,没有了;现在开始搜刚刚存的点,从5开始,没有,然后搜6…一直进行,直到找到;
DFS和BFS的思想探究_搜索_03

伪代码理解:

简单来说

void bfs()
{
	创建队列
	将点压入队列;
	访问过该点 = 1;
	while (队列不为空) 
	{
		设an为队首元素;
		弹出队首元素;
		将an输出;
		for (int i = 0; i < N; i++)
		{
			if (该点未访问过并且该点与其他点有边) 
			{
				标记该点为1,被访问过
				将该点压入队列
			}
		}
	}
}

详细来说(当然,也不是每个都这样写):

int visit[N][N]// 用来记录走过的位置
int dir[4][2]={
	0,-1,
	0,1,
	-1,0,
	1,0
};	// 上下左右四个方向


struct node
{
	int x,y,bits;	// 一般是点,还有步数,也可以存其他的
	......
};
queue<node>v;
void bfs(node p)
{
	node t,tt;
	v.push(p);
	while(!v.empty())
	{
		t=v.front();// 取出最前面的
		v.pop();	// 删除
		
		// 终止判断
		if(找到符合条件的)
		{
			做记录;
			while(!v.empty()) 	// 如果后面还需要用,随手清空队列
				v.pop();	
			return;
		}
		visit[t.x][t.y]=1;	// 走过的进行标记,以免重复
		{
			tt=t;
			tt.x+=dir[i][0];
			tt.y+=dir[i][1];	// 这里的是按照:向上下左右查找的
			
			if(如果这个位置符合条件)
			{
				tt.bits++;		// 步数加一
				v.push(tt); 	// 把它推入队列,在后面的时候就可以用了
			}
		}
	}
}
DFS和BFS的区别
广度优先搜索(BFS) 深度优先搜索(DFS)
遍历 BFS在Graph中逐级访问节点。 DFS访问图深度明智的节点。 它会访问节点,直到到达叶或没有未访问节点的节点为止。
搜索 在开始任何其他节点之前,必须先充分探究一个节点。 一旦发现另一个未探索节点,就会暂停对该节点的探索。
数据结构 使用队列数据结构存储未探索的节点。 使用堆栈数据结构存储未探索的节点。
内存 BFS较慢,需要更多的内存。 DFS更快并且需要更少的内存。
应用
在图中查找所有连接的组件。
查找两个节点之间的最短路径。
查找一个连接的组件内的所有节点。
测试图的二等性

拓扑排序。
查找连接的组件。
解决迷宫等难题。
查找牢固连接的组件。
查找图形的关节点(切顶点)。
总结

bfs是浪费空间节省时间,dfs是浪费时间节省空间。

  1. 数据结构:
    DFS用递归的形式,用到了栈结构,先进后出。
    BFS选取状态用队列的形式,先进先出。

  2. 复杂度
    DFS的复杂度与BFS的复杂度大体一致(O(∣V∣2)),不同之处在于遍历的方式与对于问题的解决出发点不同,DFS适合目标明确,而BFS适合大范围的寻找。

  3. 思想
    思想上来说这两种方法都是穷竭列举所有的情况。