/// @file depth_first_search.cpp
/// @brief 深度优先搜索
/// @copyright 玉涵 updated,2013/11/1
#include <iostream>
#include <vector>
#include <queue>
#include "graphics.h"
using namespace std;
namespace algo
{
vector<int> DFS_Visit(GraphicsAdjList &g, size_t start_index, vector<int> &d,
vector<int> &f, vector<bool> &traversed, int &time);
/// @brief 深度优先遍历主函数
/// @param g 邻接表表示的图结构
void DepthFirstSearch(GraphicsAdjList &g)
{
vector<int> d(g.GetVertex().size()); //时间戳d
vector<int> f(g.GetVertex().size()); //时间戳f
vector<bool> traversed(g.GetVertex().size(), false); //着色布尔量
int time = 0;
cout << "深度优先遍历:";
for(size_t i=0; i<g.GetVertex().size(); i++)
{
if(!traversed[i])
{
vector<int> ids = DFS_Visit(g,i,d,f,traversed,time);
for(size_t k=0; k<ids.size(); k++)
{
cout << g.GetVertex()[ids[k]] << "[" << d[ids[k]]
<< "," << f[ids[k]] << "] ";
}
}
}
cout << endl << "深度优先遍历:";
vector< pair< int, pair<int, int> > > r;
for(size_t i=0; i<g.GetVertex().size(); i++)
{
r.push_back(make_pair(i, make_pair(d[i], f[i])));
}
sort(r.begin(), r.end(), [](pair<int, pair<int, int> > const &p1, pair<int, pair<int, int> > const &p2)
{
return p1.second.first < p2.second.first;
});
for(size_t i=0; i<r.size(); i++)
{
cout << g.GetVertex()[r[i].first] << "[" << r[i].second.first << "," << r[i].second.second << "] ";
}
}
/// @brief 深度优先遍历核心递归函数
/// @param g 邻接表表示的图
/// @param start_index 源顶点编号
/// @param d 时间戳d
/// @param f 时间戳f
/// @param traversed 着色布尔量
/// @param time 全局时间量
/// @return 返回本次深度优先搜索遍历子树的依次编号
vector<int> DFS_Visit(GraphicsAdjList &g, size_t start_index, vector<int> &d,
vector<int> &f, vector<bool> &traversed, int &time)
{
vector<int> this_time_traversed;
this_time_traversed.push_back(start_index);
traversed[start_index] = true;
time++;
d[start_index] = time;
for(size_t i=0; i<g.GetVertex().size(); i++)
{
if(!traversed[i] && g.IsLinked(start_index, i).first)
{
vector<int> v = DFS_Visit(g, i, d, f, traversed, time);
this_time_traversed.insert(this_time_traversed.end(), v.begin(), v.end());
}
}
time++;
f[start_index] = time;
return this_time_traversed;
}
}
程序实际上采用了两种方式实现了输出,第一种是在做搜索的时候,把依次遍历到的结点编号导入一个vector<int>中,之后在输出的时候只需要索引该容器即可。另一种方式则是采用了算法导论上提出的时间戳方法,将时间戳d排序然后顺序输出,即是深度遍历顺序,而将f排序输出,则是拓扑排序,拓扑排序以后补充。
最后感谢川奇兄的coding,川奇兄的指引让我更加熟练操作STL,尽管相对一些诸如Python的语言,C++代码显得既装逼且又臭又长,但是魅力永不减分。
graphics.h请参考之前的博文:图的两种结构封装