文章目录
白话理解:
我觉得其实就是暴力把所有的路径都搜索出来,运用回溯,保存这次的位置,深入搜索,都搜索完了便回溯回来,搜下一个位置,直到把所有最深位置都搜一遍,要注意的一点是,搜索的时候有记录走过的位置,标记完后可能要改回来;
我的最白的理解就是,一个人每条路都一直走到黑,到头了再返回来,全走一遍,找出你想要的路。
回溯法:
回溯法是一种搜索法,按条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法;
图解:
例如这张图,从1开始到2,之后到5,5不能再走了,退回2,到6,退回2退回1,到3,一直进行;
理解这种方法比较简单,难的是要怎么用
伪代码理解:
简单来说就是这样:
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)。
我的最白的理解就是,一群人(无数),碰到了一个岔路,就派出去一队人继续走,遇到岔路再分,让人们一次性的遍布整个图,最后找出你想要的路。
图解:
还是这张图,从1开始搜,有2,3,4几个点,存起来,从2开始有5,6,存起来,搜3,有7,8,存起来,搜4,没有了;现在开始搜刚刚存的点,从5开始,没有,然后搜6…一直进行,直到找到;
伪代码理解:
简单来说
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是浪费时间节省空间。
-
数据结构:
DFS用递归的形式,用到了栈结构,先进后出。
BFS选取状态用队列的形式,先进先出。 -
复杂度
DFS的复杂度与BFS的复杂度大体一致(O(∣V∣2)),不同之处在于遍历的方式与对于问题的解决出发点不同,DFS适合目标明确,而BFS适合大范围的寻找。 -
思想
思想上来说这两种方法都是穷竭列举所有的情况。