深度优先搜索算法(DFS)讲解
深度优先搜索算法(DFS)讲解
深度优先搜索(DFS)是一种用于遍历或搜索树或图的算法。它以深入探索图的分支为目标,直到到达指定的“深度”,无法继续前进为止,然后通过回溯探索其他分支。DFS是数据结构与算法中一个非常重要且基础的概念,对于理解复杂数据结构的搜索和遍历过程至关重要。
1. DFS定义及应用
DFS允许你从一个顶点开始,沿着树或图的边走到尽可能深的分支,然后通过回溯,继续探索未遍历的分支。它的应用非常广泛,包括解决迷宫问题、路径查找、检查图中是否存在环、排序问题等。
2. DFS原理
DFS的核心思想是使用递归或栈来实现对图的深入探索。在递归实现中,DFS从一个顶点开始,访问其任一未被访问的邻接顶点,将其标记为已访问,然后从这个邻接顶点出发继续这一过程,形成递归。当到达一个顶点而它没有未访问的邻接顶点时,算法将回溯,继续探索前一个顶点的其他邻接顶点。
3. DFS代码框架
DFS的代码看起来简单,但是初学者在逻辑上会感到难以理解。请读者在大量编码的基础上,再回头体会这个框架的作用。
ans
void dfs(层数,其他参数){
if(出局判断){ // 到达最底层,或者满足条件推出
更新答案 // 答案一般用全局变量表示
return; // 返回到上一层
}
(搜索顺序剪枝(优化搜索顺序) || 最优性剪枝) // 在进一步dfs之前剪枝
for(枚举下一层可能的情况){
if(used[i]==0 && 可行性剪枝){ // 如果状态i没有用过,就可以进入下一层
used[i]=1; // 标记状态i已经使用过
dfs(层数+1,其他参数); // 下一层
used[i]=0; // 回溯
}
}
return; // 返回到上一层
}
4. DFS的优点和缺点
优点:
- 空间效率高:DFS在实现时可以通过递归调用的系统栈来保存信息,因此它的空间复杂度相对较低。
- 适用于路径和配置问题:对于需要寻找所有可能路径的问题,DFS提供了一种直接而有效的解决方案。
缺点:
- 时间复杂度可能高:在最坏的情况下,需要访问所有的顶点和边,时间复杂度为O(V+E),其中V是顶点数,E是边数。
- 可能不会找到最短路径:对于需要找到最短路径的问题,DFS可能不是最好的选择。
5.回溯及其使用与避免
回溯的概念及其在DFS中的角色
回溯可以被看作是DFS的一个特例或者说是一种策略,它的核心思想是“走不通就退回去”。简单来说,当DFS在探索过程中遇到一个死路(即没有其他出路或者没有达到目标条件的路)时,它就会沿着来时的路径退回一步,尝试其他的可能性。
使用回溯解决问题的情况
回溯法非常适合解决需要多次尝试、寻找所有可能解的问题。例如,解谜题(如八皇后问题)、组合问题(如数独)等,都是通过尝试每一种可能的组合来找到解决方案。在这些问题中,每做出一个选择,就进入下一层决策树;如果发现当前选择导致无法达到目标,就退回到上一层,改变选择。
判断是否使用回溯及其限制
在实施DFS时,如果问题需要遍历所有可能的路径来找到解决方案,或者需要不断尝试直到满足特定条件,那么使用回溯是非常合适的。
回溯避免示例
在解决洪水填充这一类连通性相关的问题当中,我们要避免使用回溯;我们可以从以下两个角度去理解:
- 在解决这一类连通性问题中,我们不需要多次尝试、寻找所有可能解,就像遍历一棵树/图一样,只需简单的进行dfs遍历即可,不需要回溯
- 调用使用了回溯的dfs函数后,所有状态都会回归初始状态,而解决连通性这一类问题中我们需要调用dfs后所有连通块中的状态都被更新,因此我们要避免使用回溯
DFS剪枝优化
深度优先搜索(DFS)是一种遍历或搜索树或图的算法,它从一个根节点开始,尽可能深地搜索每个分支,直到找到解为止。在搜索过程中,为了提高效率,减少不必要的搜索,通常会采用各种剪枝优化策略。下面详细介绍几种常用的DFS剪枝优化策略:
1. 优化搜索顺序
- 目的:通过调整搜索顺序,使得搜索尽快地接近目标或者尽早地剪枝。
- 策略:在开始搜索前,对所有可能的选择进行排序,优先搜索那些最有可能导致最优解或最快发现无解(以便剪枝)的选项。例如,在解决背包问题时,可以先考虑价值密度最高的物品。
2. 排除等效冗余
- 目的:避免搜索到重复或等效的解,减少搜索空间。
- 策略:在搜索过程中,如果发现当前的选择会导致之前已经搜索过的状态,则可以直接剪枝。例如,在全排列问题中,如果某个数已经被选取,那么在这一层的其他分支中就不再考虑这个数。
3. 可行性剪枝
- 目的:在搜索过程中,一旦发现当前路径不可能达到目标(即不可行),立即停止进一步搜索。
- 策略:根据问题的约束条件,实时计算当前选择的后果,如果违反约束则立即回溯。例如,在求解和为特定值的子集问题中,如果当前子集的和已经超过目标值,就可以停止向该分支的更深层搜索。
4. 最优化剪枝
- 目的:在搜索过程中,及早排除那些即使在最好情况下也比已找到的最优解差的路径。
- 策略:维护一个全局的最优解变量,在搜索过程中,如果某个分支的最佳可能结果仍然不如当前最优解,则放弃该分支。例如,在旅行商问题(TSP)中,如果当前路径加上未访问城市的最小成本估算仍然大于当前最短路径,则放弃该路径。
总结
一道题目中可能用到多种剪枝技术,不过用不着可以区分是哪种剪枝技术,总体思路就是减少搜索状态。