注意本文内容的理解需要:
1. 了解递归的原理
2. 了解二叉树或图的结构
深度优先搜索算法(Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法,即沿着树的深度遍历树的节点,尽可能深的搜索树的分支。
当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点,整个进程反复进行直到所有节点都被访问为止。
从某种意义来讲DFS属于盲目搜索,有时候最糟糕的情况,算法时间复杂度可以高达为O(n!),DFS搜索的过程访问可以称之为DFS序。
如图所示:
对于一颗这样的树,我们的DFS序可以为:abdefc(对于同一颗的树,其DFS序不一定唯一),即访问a之后访问a的子结点b,再在b的基础上依次访问它的子结点def,最后回退到a处访问c(此处采用的是先序遍历)。
对于一颗深度为 n 的二叉树,在没有任何优化的情况下适用DFS去搜索访问数据,其算法的时间复杂度也高达O(2^n),在数据较大的情况下DFS是无法满足程序的时间要求的
所以这就会涉及到一个思路——剪枝。
剪枝,顾名思义,就是将树上不要的小分叉剪掉,也就是说通过当前现有的数据判断接下来的数据是否能够满足要求。如果接下来的数据无法满足要求,则直接将当前结点以后的所有数据舍弃,不再继续遍历访问,按照程序的设计要求,通过精心设计的剪枝可以使得DFS搜索的效果得到很大提升。
下面是使用DFS解决一些算法题目的常用编程模板:
对于一个标准的DFS模板而言,其包括了以下的内容:
bool check(参数) //用来判断当前状态是否合法
{
if(满足条件)
return true ;
return false;
}
void dfs(int step)
{
判断边界
{
相应操作
}
尝试每一种可能
{
满足check条件
标记
继续下一步dfs(step+1)
恢复初始状态(回溯的时候要用到)
}
}
考虑更多情况的dfs模板:
void dfs()//参数用来表示状态
{
if(到达终点状态)
{
...//根据需求添加
return;
}
if(越界或者是不合法状态)
return;
if(特殊状态)//剪枝,去除一些不需要访问的场景,不一定要访问到底
return ;
for(扩展方式)
{
if(扩展方式所达到状态合法)
{
修改操作;//根据题意来添加
标记;
dfs();
(还原标记);
//是否还原标记根据题意
//如果加上(还原标记)就是 回溯法
}
}
}