转载自:https://blog.csdn.net/qq_21158525/article/details/79459378
递归:就是出现这种情况的代码: (或者说是用到了栈)
解答树角度:在dfs遍历一棵解答树
优点:结构简洁
缺点:效率低,可能栈溢出
递归的一般结构:
void f()
{
if(符合边界条件)
{
///////
return;
}
//某种形式的调用
f();
}
回溯:递归的一种,或者说是通过递归这种代码结构来实现回溯这个目的。回溯法可以被认为是一个有过剪枝的DFS过程。
解答树角度:带回溯的dfs遍历一棵解答树
回溯的一般结构:
void dfs(int 当前状态)
{
if(当前状态为边界状态)
{
记录或输出
return;
}
for(i=0;i<n;i++) //横向遍历解答树所有子节点
{
//扩展出一个子状态。
修改了全局变量
if(子状态满足约束条件)
{
dfs(子状态)
}
恢复全局变量//回溯部分
}
}
经典例题,比如解数独问题。
BFS与 DFS
BFS的占用的是队列的空间,DFS 占用的是栈的空间(因为递归)。BFS和DFS的空间复杂度恰好相反。对链状图,BFS最好(队列中最多只有1个元素),DFS最差(所有节点都在根节点的递归内)。对起点与其他所有点相邻的图,DFS最好(递归深度为1),BFS最差(队列中放满了所有与起点相邻的图)。
BFS一般结构:
queue<type> q;
q.push(初始状态);
while (!q.empty())
{
type t = q.front() ;
q.pop();
遍历 t 的各个Next状态 next
{
if (next is legal)
q.push(next); 计数或维护等;
}
}
但是BFS的状态数一多,需要的空间就会较大。
DFS 一般结构与回溯相似
DFS(顶点)
{
处理当前顶点,记录为已访问
遍历与当前顶点相邻的所有未访问顶点
{
标记更改;
DFS( 下一子状态);
恢复更改;
}
}