bfs和dfs辨析—基础复习(从stack和queue的角度来理解区别,加深理解,不再模糊)
Posted kid-yln
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bfs和dfs辨析—基础复习(从stack和queue的角度来理解区别,加深理解,不再模糊)相关的知识,希望对你有一定的参考价值。
参考:
https://blog.csdn.net/dangzhangjing97/article/details/81477192
一般来说,dfs总是先学,然后再学bfs,因为dfs就是一个简单的递归思想,理解起来比较简单,思维过程如下,
1 dfs(要搜的点){ 2 将该点标记为已搜过 3 if(终止条件){ 4 如果找存在路径,就退出 5 如果找最短路径,就比较这个与最小值,回去接着找 6 } 7 else{ 8 case1{ 9 目标值变化 10 dfs(case1); 11 目标值恢复到原来 12 } 13 case2 ... 14 case3 ... 15 } 16 }
用stack来理解就是,每次”返回“的方式都是弹出之前那一个,即由ann->弹出,下一个是ann-1,再看看ann-1指向的地方有没有没到的
总共三个过程:
- 某节点到底了,还没找到满足条件的
- 弹出 stack ,销毁这个分支, 返回到上一个
- 检查当前往下的另一个方向。有,则再往下另一个分支,压入stack。没有,就继续 "弹出"当前stack
但是学完dfs之后,再学习bfs的时候总是把这两个搞混, 尤其是它加入了queue这个结构来实现"返回",
而且之前一直搞不懂, bfs虽然是"按层"搜索,但是也有 "返回" 的过程, 可是, dfs也有返回过程啊,这个"返回"和dfs的到底有甚区别??!!
后来又重新看了一些stack和queue的辨析(文章开头的链接),才慢慢理解到:
虽然 bfs 也有“返回”,但是,它的返回,其实是在 an这一层已经完全遍历完了之后,才考虑“返回”还是继续 “往下”,
它是已经把当前这一层的情况都记录下来了,才考虑后续的操作,所以常常说bfs耗空间,因为它要记录!!!它的“返回”只有两个过程!
- 某节点到底了,还没找到满足条件的
- 直接横向看,检查,当前这一层是否还有没有遍历完的“邻支”,有,则再往旁边另一个分支。没有,就 "返回"
总结就是,dfs返回 ,先要找到“上家” ,再看有没有分支,而 bfs,可以直接找“邻居”,比较粗暴,直接横着来,
那它凭什么这么做呢?因为它用的是 queue + 数组 ,这样来理解就是,bfs 总是需要一个代表“第n层”的队列,每次都会将当前层 “ 全部元素” 丢进“数组”去,
然后横向剪 “邻枝” 或者说,排除邻支,以及包括从邻支到底层的所有可能,所以效率特别高,
又因为它是queue实现,先进先出,一定按照从前到后的次序,来“剪枝”/记录“路径”/“遍历”
因此,如果是bfs 特征一定是,它判断“成功”的条件,不需要到最底层,在当前层就已经可以排除掉,可以“预判”,可以在上层剪枝
所以适合——迷宫/找最小全“1”/“0”或者某一条件的矩阵,又或者同样可以用dfs解决但是对“更高效率”有要求的题目
如下为一般结构:
1 bfs(){ 2 初始点入列 3 while(终止条件不满足 或 队列不为空){//层数不为0 4 队列头出列 // 5 从出列元素开始扩散,满足的就入列 6 找个数组记下来目标值 7 } 8 找目标值 9 }
以上是关于bfs和dfs辨析—基础复习(从stack和queue的角度来理解区别,加深理解,不再模糊)的主要内容,如果未能解决你的问题,请参考以下文章