1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
#include <map>
#include <vector>
#include <set>
#include <iostream>
#include <stack>
#include <queue>
#include <cassert>
#include <string>
#include <sstream>
template< typename T > using adjacency_list_type = std::map< T, std::vector<T> > ;
typedef int node_type ; // for exposition
typedef adjacency_list_type<node_type> adjacency_list ;
// input of pairs of adjacent vertices of a directed graph
// 1 7 => edge from 1 -------> 7
// 2 7 => edge from 2 -------> 7
// 1 5 => edge from 1 -------> 5
// etc.
adjacency_list create( std::istream& stm )
{
adjacency_list graph ;
node_type a, b ;
while( stm >> a >> b ) { graph[a].push_back(b) ; graph[b] ; }
return graph ;
}
bool topological_sort( const adjacency_list& graph )
{
std::map< node_type, int > num_pred_map ;
for( const auto& pair : graph )
{
num_pred_map[pair.first] ;
for( auto n : pair.second ) ++num_pred_map[n] ;
}
while( !num_pred_map.empty() )
{
bool cyclic = true ;
for( auto iter = num_pred_map.begin() ; iter != num_pred_map.end() ; )
{
if( iter->second == 0 )
{
std::cout << iter->first << ' ' ;
for( auto& v : graph.find(iter->first)->second )
--num_pred_map[v] ;
iter = num_pred_map.erase(iter) ;
cyclic = false ;
}
else ++iter ;
}
if(cyclic)
{
std::cerr << "graph is cyclic - nodes " ;
for( auto& pair : num_pred_map ) std::cout << pair.first << ' ' ;
std::cout << '\n' ;
return false ;
}
}
std::cout << '\n' ;
return true ;
}
template< typename STACK_OR_QUEUE, typename NEXT_FN >
bool graph_search( const adjacency_list& graph, node_type start, node_type target,
NEXT_FN next )
{
STACK_OR_QUEUE stk_or_queue ;
std::set<node_type> visited ;
stk_or_queue.push(start) ;
while( !stk_or_queue.empty() )
{
node_type id = next(stk_or_queue) ;
std::cout << id << ' ' ;
visited.insert(id) ;
if( id == target ) { std::cout << " found target\n" ; return true ; }
else
{
stk_or_queue.pop() ;
auto iter = graph.find(id) ;
if( iter != graph.end() )
for( auto& n : iter->second )
if( visited.find(n)==visited.end() ) stk_or_queue.push(n) ;
}
}
std::cout << " could not find target\n" ;
return false ;
}
bool depth_first_search( const adjacency_list& graph, node_type start, node_type target )
{
return graph_search< std::stack<node_type> >( graph, start, target,
[]( const std::stack<node_type>& stk ) { return stk.top() ; } ) ;
}
bool breadth_first_search( const adjacency_list& graph, node_type start, node_type target )
{
return graph_search< std::queue<node_type> >( graph, start, target,
[]( const std::queue<node_type>& q ) { return q.front() ; } ) ;
}
int main() // trivial test driver
{
const std::string str = "1 2 1 7 1 8 2 3 2 6 2 10 3 4 3 5 3 11 "
"6 10 6 12 8 9 8 12 9 10 9 11 11 7 12 5" ;
std::istringstream stm(str) ;
adjacency_list graph = create(stm) ;
std::cout << "top sort => " ; topological_sort(graph) ;
std::cout << "DFS 1 to 5 => " ; depth_first_search( graph, 1, 5 ) ;
std::cout << "BFS 1 to 5 => " ; breadth_first_search( graph, 1, 5 ) ;
std::cout << "DFS 1 to 6 => " ; depth_first_search( graph, 1, 6 ) ;
std::cout << "BFS 1 to 6 => " ; breadth_first_search( graph, 1, 6 ) ;
}
|