Reputation: 1100
From what I can gather of how to use BGL in order to invoke a DFS of a graph from a known root node I need to do something along the lines of
class MyVisitor : public boost::default_dfs_visitor
{
public:
void discover_vertex(MyVertex v, const MyGraph& g) const
{
cerr << v << endl;
return;
}
};
void bfsMethod(Graph g, int rootNodeId)
{
boost::undirected_dfs(g, vertex(rootNodeId,g), boost::visitor(vis));
}
Now I am not sure how I alter this so that std::vector
of vertexId's (or pointers) is built as the DFS visits all vertices in the graph in a similar way to how the minimum spanning tree algorithm can be used e.g.
std::vector < JPEdge > spanning_tree;
kruskal_minimum_spanning_tree(g, std::back_inserter(spanning_tree));
Upvotes: 2
Views: 1203
Reputation: 537
Because both depth_first_search
and undirected_dfs
pass DFSVisitor vis
by value, we cannot use std::vector<>
to store traversed vertices, otherwise its size will always be 0 after exiting depth_first_search
or undirected_dfs
. Instead, we can use a std::shared_ptr<std::vector<>>
or static std::vector<>
to store the vertices. In my opinion, using a static
data member is simpler and more expressive.
Here we can get pre-order traversal with discover_vertex()
and post-order traversal with finish_vertex
. See DFS Visitor for more details.
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>
#include <iostream>
using MyGraph = boost::adjacency_list<
boost::listS, boost::vecS, boost::undirectedS,
boost::property<boost::vertex_color_t, boost::default_color_type>>;
using MyVertex = boost::graph_traits<MyGraph>::vertex_descriptor;
struct MyDFSVisitor : public boost::default_dfs_visitor {
inline static std::vector<MyVertex> m_preorder_vertices;
inline static std::vector<MyVertex> m_postorder_vertices;
void discover_vertex(MyVertex v, const MyGraph &g) {
m_preorder_vertices.push_back(v);
}
void finish_vertex(MyVertex v, const MyGraph &g) {
m_postorder_vertices.push_back(v);
}
};
int main() {
MyGraph g{};
boost::add_edge(0, 1, g);
boost::add_edge(0, 2, g);
boost::add_edge(1, 2, g);
boost::add_edge(1, 3, g);
auto root = boost::vertex(0, g);
auto color_map = boost::get(boost::vertex_color, g);
MyDFSVisitor vis;
boost::depth_first_search(g, vis, color_map, root);
std::cout << "pre-order traversal : \n"; // 0 1 2 3
for (auto v : vis.m_preorder_vertices) {
std::cout << v << std::endl;
}
std::cout << "post-order traversal : \n"; // 2 3 1 0
for (auto v : vis.m_postorder_vertices) {
std::cout << v << std::endl;
}
}
Note that inline static
is a C++17 feature.
Upvotes: 0
Reputation: 132994
The vector must be a member of your visitor. In the discover_vertex
function, just push the discovered element into the vector.
class MyVisitor : public boost::default_dfs_visitor
{
public:
void discover_vertex(MyVertex v, const MyGraph& g) const
{
cerr << v << endl;
vv.push_back(v);
return;
}
vector<MyVertex> GetVector() const {return vv; }
private:
vector<MyVertex> vv;
};
void bfsMethod(Graph g, int rootNodeId)
{
MyVisitor vis;
boost::undirected_dfs(g, vertex(rootNodeId,g), vis);
vector<MyVertex> vctr = vis.GetVector();
}
Upvotes: 1