[算法日志]图论: 深度优先搜索(DFS)
深度优先概论
深度优先搜索算法是一种遍历图这种数据结构的算法策略,其中心思想是朝图节点的一个方向不断跳转,当该节点无下一个节点或所有方向都遍历完时,便回溯朝上一个节点的另一个方向继续遍历。这种搜索策略与回溯法有异曲同工之妙。
DFS的代码框架
c++
void dfs(参数)
{
if(终止条件)
{
储存结果;
return;
}
for(遍历节点的各个分支)
{
处理节点;
dfs(参数);//调用本函数
撤销处理,回溯;
}
}
正因为和回溯法有相似之处,所以其在代码结构上与回溯大致相同。
深搜三部曲
-
确认递归函数及其参数
在深搜过程中,我们通常会定义两个数组容器,一个二维数组储存结果,一个一维数组储存节点路径。
而递归函数参数我们往往无法在一开始便确认,通常都是在书写递归逻辑时按需添加。
-
确认终止条件
终止条件的不同有时会导致函数的需要遍历的值不同。同时,递归条件如果确定错误会导致死循环,栈溢出等错误。所以确定好递归条件是比较关键的一步。
-
遍历节点的各个路径
首先将本节点下一个要遍历的节点放进路径,适当处理后进入递归函数,回来时将该节点从路径中取出,做回溯操作。
深搜的简单应用
leetcode 797
示例代码
c++
void DFS1(const vector<vector<int>>& mygraph, vector<vector<int>>& result, vector<int>& path, int next)
{
if (mygraph[next].empty() || path.back() == mygraph.size() - 1)
{
if (path.back() == mygraph.size() - 1)
result.push_back(path);
return;
}
const int size = mygraph[next].size();
for (int i = 0; i < size; ++i)
{
path.push_back(mygraph[next][i]);
DFS1(mygraph, result, path, mygraph[next][i]);
path.pop_back();
}
}
vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& mygraph)
{
vector<vector<int>> result;
vector<int> path;
if (mygraph.empty())
return result;
path.push_back(0);
DFS1(mygraph, result, path, 0);
return result;
}