深度优先搜索,即DFS(depth first search)是一种图的搜索方法,一般使用递归实现。
深度优先搜索的原理很简单,即从一个点开始,将这点标记为已搜索,然后找到与该点链接的顶点,再在该顶点继续上述操作。直到我们走到的顶点没有与其链接的未标记顶点时,往前回溯,再继续搜索,直到搜索完该点所在的连通分支的全部节点。
in algorithm.h
class DFS
{
public:
DFS(graph g,int s);
int num()
{
return count;
}
private:
bool *marked;
int count;
void dfs(graph g, int v);
bool mark(int v);
};
in algorithm.cpp
/*深度优先搜索*/
DFS::DFS(graph g, int s)
{
marked = new bool[g.numv()];
std::fill(marked, marked + g.numv(), 0);
dfs(g, s);
}
bool DFS::mark(int v)
{
return marked[v];
}
void DFS::dfs(graph g, int v)
{
marked[v] = true;
count++;
std::vector<int> gv = g.iterator(v);
for (auto w : gv)
{
//printf("%d %d\n", w,marked[w]);
if (!mark(w))
{
dfs(g, w);
}
}
}
细心的读者应该注意到了,我这次并没有使用vector,而是使用了数组,不是我良心发现,只是单纯的觉得marked数组不需要什么操作,用数组快一点
以上代码就是DFS的核心部分,不过我们在应用时常常对部分代码进行更改使其能达到我们预期的功能,不如我们使用DFS来搜索路径,代码如下:
in algorithm.h
class DFS
{
public:
DFS(graph g,int s);
int num()
{
return count;
}
std::string path_to(int v);
private:
bool *marked;
int count;
std::vector<std::string> path;
void dfs(graph g, int v);
bool mark(int v);
};
in alorithm.cpp
/*深度优先搜索*/
DFS::DFS(graph g, int s)
{
marked = new bool[g.numv()];
std::fill(marked, marked + g.numv(), 0);
path.resize(g.numv());
path[s] += std::to_string(s);
dfs(g, s);
}
bool DFS::mark(int v)
{
return marked[v];
}
void DFS::dfs(graph g, int v)
{
marked[v] = true;
count++;
std::vector<int> gv = g.iterator(v);
for (auto w : gv)
{
//printf("%d %d\n", w,marked[w]);
if (!mark(w))
{
path[w] = path[v] + " " + std::to_string(w); //将顶点转换为字符串压入数组
dfs(g, w);
}
}
}
std::string DFS::path_to(int v)
{
return path[v];
}
运行结果:
此处我写的获取路径代码与原书中不太一样,因为我觉得原书中的代码过于含糊与麻烦所以对其进行了修改。
我们也可以用DFS来求图的连通性,不过比起union-find算法虽然DFS在理论上更快,但是实际操作起来,DFS需要构造好的图,并且每当图发生变化,都需要图重新构造。而union-find是动态算法。所以如果仅仅是求连通性,union-find算法实际上会比DFS更快
DFS是非常重要的算法,很多与图有关的操作都需要DFS,所以需要牢牢掌握