C++ Boost

depth_first_search

Graphs: directed and undirected
Properties: color
Complexity: time: O(V + E)
Where Defined: boost/graph/depth_first_search.hpp

(1)
template <class VertexListGraph, class DFSVisitor>
void depth_first_search(VertexListGraph& G, DFSVisitor v);

(2)
template <class VertexListGraph, class DFSVisitor, class ColorMap>
void depth_first_search(VertexListGraph& G, DFSVisitor v, ColorMap c);

The depth_first_search() algorithm performs a depth-first search (DFS) on a graph, invoking the methods of the graph search visitor at the appropriate event-points. A depth-first search visits all the vertices in a graph, starting with some arbitrary vertex and then always choosing the next adjacent unvisited vertex. Once the DFS reaches a vertex with no unvisited neighbors it backtracks to one of the previous vertices and continues from there. Once all of the vertices in the same connected component have been visited, another arbitrary unvisited vertex is choosen and the depth-first search resumes. A more detailed explanation of DFS is given in Section Depth-First Search. The depth-first exploration of each connected component is implemented by the function depth_first_visit().

The DFSVisitor supplied by the user determines what actions are taken at each event-point within the algorithm.

The ColorMap is used by the algorithm to keep track of which vertices have been visited.

DFS is used as the kernel for several other graph algorithms, including topological_sort and two of the connected component algorithms.

Requirements on Types

Complexity

The time complexity is O(E + V).

Example

This example shows DFS applied to the graph in Figure 1. The source code for this example is in examples/dfs_basics.cpp.

Figure 1: Depth-first search spreading through a graph.

  // Select the graph type we wish to use
  typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS> Graph;
  // Set up the vertex names
  enum { u, v, w, x, y, z, N };
  char name[] = { 'u', 'v', 'w', 'x', 'y', 'z' };
  // Specify the edges in the graph
  typedef std::pair<int,int> E;
  E edge_array[] = { E(u,v), E(u,x), E(x,v), E(y,x),
                     E(v,y), E(w,y), E(w,z), E(z,z) };
  Graph G(N, edge_array, edge_array + sizeof(edge_array)/sizeof(E));

  // Some typedef's to save a little typing
  typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
  typedef boost::graph_traits<Graph>::vertices_size_type size_type;
  typedef std::vector<Vertex>::iterator Piter;
  typedef std::vector<size_type>::iterator Iiter;

  // color, discover time, and finish time properties
  std::vector<default_color_type> color(num_vertices(G));
  std::vector<size_type> dtime(num_vertices(G));
  std::vector<size_type> ftime(num_vertices(G));

  boost::depth_first_search(G, boost::visit_timestamp(dtime.begin(), ftime.begin()), 
                            color.begin());

  // use std::sort to order the vertices by their discover time
  std::vector<size_type> discover_order(N);
  boost::iota(discover_order.begin(), discover_order.end(), 0);
  std::sort(discover_order.begin(), discover_order.end(),
    boost::indirect_cmp<Iiter, std::less<size_type> >(dtime.begin()));

  std::cout << "order of discovery: ";
  for (int i = 0; i < N; ++i)
    std::cout << name[ discover_order[i] ] << " ";

  std::vector<size_type> finish_order(N);
  boost::iota(finish_order.begin(), finish_order.end(), 0);
  std::sort(finish_order.begin(), finish_order.end(),
    boost::indirect_cmp<Iiter, std::less<size_type> >(ftime.begin()));

  std::cout << endl << "order of finish: ";
  for (size_type i = 0; i < N; ++i)
    std::cout << name[ finish_order[i] ] << " ";
  std::cout << std::endl;
The output is:
order of discovery: u v y x w z 
order of finish: x y v u z w

See Also

depth_first_visit

Copyright © 2000 Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu)
Lie-Quan Lee, Univ.of Notre Dame (llee1@lsc.nd.edu)
Andrew Lumsdaine, Univ.of Notre Dame (lums@lsc.nd.edu)