Graphs: | directed and undirected |
---|---|
Properties: | color |
Complexity: | time: O(V + E) |
(1) template <class VertexListGraph, class BFSVisitor> void breadth_first_search(VertexListGraph& G, typename graph_traits<VertexListGraph>::vertex_descriptor s, BFSVisitor vis); (2) template <class VertexListGraph, class BFSVisitor, class ColorMap> void breadth_first_search(const VertexListGraph& g, typename graph_traits<VertexListGraph>::vertex_descriptor s, BFSVisitor vis, ColorMap color); (3) template <class IncidenceGraph, class Buffer, BFSVisitor, class ColorMap> void breadth_first_search(const VertexListGraph& g, typename graph_traits<VertexListGraph>::vertex_descriptor s, Buffer& Q, BFSVisitor vis, ColorMap color)
The breadth-first search (BFS) algorithm is not really an algorithm in the sense that it has a particular purpose. Instead BFS is more like an algorithm pattern. One can do many different things with BFS. For example, the BFS pattern is used in the BGL to build several other algorithms: Dijkstra's shortest paths, Prim's Minimum Spanning Tree and best-first search. The definition of a breadth-first search is given in Section Breadth-First Search.
The BGL BFS functions are highly parameterized so that they can be used in a wide variety of places. The way to customize the BFS algorithm to perform different operations is to supply a visitor, which is a function object with multiple functions. Each member function of the visitor gets invoked at special times during the algorithm as specified by BFSVisitor. Also, visitors can be layered on top of each other so that one can do lots of things during a single run of BFS. See the bfs_visitor class and the EventVisitor concept for more details.
Another way to customize the BFS algorithm is change the type of queue used. For instance, dijkstra_shortest_paths() uses a priority queue.
The ColorMap is used by BFS to keep track of which vertices have been visited. At the beginning of the algorithm all vertices are white. As the algorithm proceeds, vertices are colored gray as they are inserted into the queue, and then colored black when they are finished and removed from queue.
Version 1 of the algorithm takes only three arguments: the graph object, the source vertex, and a visitor to specify the actions to be taken during the graph search. The algorithm will need to use a color property which must be provided by the graph object (through a vertex color property).
Version 2 of the algorithm adds a color property argument to accommodate the use of an external property map.
Version 3 of the algorithm is the most generalized. It adds a parameter for the queue. This version does not initialize the color of all the vertices to white at the start of the algorithm or invoke the initialize_vertex() visitor method, so that must be taken care of before calling this versin of breadth_first_search().
boost/graph/breadth_first_search.hpp
The time complexity is O(E + V).
This example demonstrates using the BGL Breadth-first search algorithm on the graph from Figure 5. The source code for this example is in examples/bfs_basics.cpp.
// Select the graph type we wish to use typedef adjacency_list<vecS, undirectedS> Graph; // Set up the vertex ID's and names enum { r, s, t, u, v, w, x, y, N }; char name[] = { 'r', 's', 't', 'u', 'v', 'w', 'x', 'y' }; // Specify the edges in the graph typedef pair<int,int> E; E edge_array[] = { E(r,s), E(r,v), E(s,w), E(w,r), E(w,t), E(w,x), E(x,t), E(t,u), E(x,y), E(u,y) }; // Create the graph object Graph G(N, edge_array, edge_array + sizeof(edge_array)/sizeof(E)); // Some typedef's to save a little typing typedef Graph::vertex_descriptor Vertex; typedef std::vector<Vertex>::iterator Piter; typedef std::vector<Graph::size_type>::iterator Iiter; // vectors to hold color, discover time, and finish time properties std::vector<default_color_type> color(num_vertices(G)); std::vector<Graph::size_type> dtime(num_vertices(G)); std::vector<Graph::size_type> ftime(num_vertices(G)); breadth_first_search(G, vertex(s,G), visit_timestamp(dtime.begin(), ftime.begin()), color.begin()); // Use std::sort to order the vertices by their discover time vector<Graph::size_type> discover_order(N); iota(discover_order.begin(), discover_order.end(), 0); std::sort(discover_order.begin(), discover_order.end(), indirect_cmp<Iiter, std::less<Graph::size_type> >(dtime.begin())); cout << "order of discovery: "; for (int i = 0; i < N; ++i) cout << name[ discover_order[i] ] << " "; vector<Graph::size_type> finish_order(N); iota(finish_order.begin(), finish_order.end(), 0); std::sort(finish_order.begin(), finish_order.end(), indirect_cmp<Iiter, std::less<Graph::size_type> >(ftime.begin())); cout << endl << "order of finish: "; for (int i = 0; i < N; ++i) cout << name[ finish_order[i] ] << " "; cout << endl;The output is:
order of discovery: s r w v t x u y order of finish: s r w v t x u y
Copyright © 2000 | Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) |