src/work/marci/oldies/marci_bfs.hh
author athos
Thu, 03 Mar 2005 17:18:27 +0000
changeset 1182 a1abe9452199
permissions -rw-r--r--
Added two demo programs: of course they are not considered to be complete or finished in any sense.
marci@280
     1
#ifndef MARCI_BFS_HH
marci@280
     2
#define MARCI_BFS_HH
marci@280
     3
marci@280
     4
#include <queue>
marci@280
     5
marci@280
     6
#include <marci_property_vector.hh>
marci@280
     7
marci@280
     8
namespace hugo {
marci@280
     9
marci@280
    10
  template <typename graph_type>
marci@280
    11
  struct bfs {
marci@280
    12
    typedef typename graph_type::node_iterator node_iterator;
marci@280
    13
    typedef typename graph_type::edge_iterator edge_iterator;
marci@280
    14
    typedef typename graph_type::each_node_iterator each_node_iterator;
marci@280
    15
    typedef typename graph_type::out_edge_iterator out_edge_iterator;
marci@280
    16
    graph_type& G;
marci@280
    17
    node_iterator s;
marci@280
    18
    node_property_vector<graph_type, bool> reached;
marci@280
    19
    node_property_vector<graph_type, edge_iterator> pred;
marci@280
    20
    node_property_vector<graph_type, int> dist;
marci@280
    21
    std::queue<node_iterator> bfs_queue;
marci@280
    22
    bfs(graph_type& _G, node_iterator _s) : G(_G), s(_s), reached(_G), pred(_G), dist(_G) { 
marci@280
    23
      bfs_queue.push(s); 
marci@280
    24
      for(each_node_iterator i=G.first_node(); i.valid(); ++i) 
marci@280
    25
	reached.put(i, false);
marci@280
    26
      reached.put(s, true);
marci@280
    27
      dist.put(s, 0); 
marci@280
    28
    }
marci@280
    29
    
marci@280
    30
    void run() {
marci@280
    31
      while (!bfs_queue.empty()) {
marci@280
    32
	node_iterator v=bfs_queue.front();
marci@280
    33
	out_edge_iterator e=G.first_out_edge(v);
marci@280
    34
	bfs_queue.pop();
marci@280
    35
	for( ; e.valid(); ++e) {
marci@280
    36
	  node_iterator w=G.head(e);
marci@280
    37
	  std::cout << "scan node " << G.id(w) << " from node " << G.id(v) << std::endl;
marci@280
    38
	  if (!reached.get(w)) {
marci@280
    39
	    std::cout << G.id(w) << " is newly reached :-)" << std::endl;
marci@280
    40
	    bfs_queue.push(w);
marci@280
    41
	    dist.put(w, dist.get(v)+1);
marci@280
    42
	    pred.put(w, e);
marci@280
    43
	    reached.put(w, true);
marci@280
    44
	  } else {
marci@280
    45
	    std::cout << G.id(w) << " is already reached" << std::endl;
marci@280
    46
	  }
marci@280
    47
	}
marci@280
    48
      }
marci@280
    49
    }
marci@280
    50
  };
marci@280
    51
marci@280
    52
  template <typename graph_type> 
marci@280
    53
  struct bfs_visitor {
marci@280
    54
    typedef typename graph_type::node_iterator node_iterator;
marci@280
    55
    typedef typename graph_type::edge_iterator edge_iterator;
marci@280
    56
    typedef typename graph_type::out_edge_iterator out_edge_iterator;
marci@280
    57
    graph_type& G;
marci@280
    58
    bfs_visitor(graph_type& _G) : G(_G) { }
marci@280
    59
    void at_previously_reached(out_edge_iterator& e) { 
marci@280
    60
      //node_iterator v=G.tail(e);
marci@280
    61
      node_iterator w=G.head(e);
marci@280
    62
      std::cout << G.id(w) << " is already reached" << std::endl;
marci@280
    63
   }
marci@280
    64
    void at_newly_reached(out_edge_iterator& e) { 
marci@280
    65
      //node_iterator v=G.tail(e);
marci@280
    66
      node_iterator w=G.head(e);
marci@280
    67
      std::cout << G.id(w) << " is newly reached :-)" << std::endl;
marci@280
    68
    }
marci@280
    69
  };
marci@280
    70
marci@280
    71
  template <typename graph_type, typename reached_type, typename visitor_type>
marci@280
    72
  struct bfs_iterator {
marci@280
    73
    typedef typename graph_type::node_iterator node_iterator;
marci@280
    74
    typedef typename graph_type::edge_iterator edge_iterator;
marci@280
    75
    typedef typename graph_type::out_edge_iterator out_edge_iterator;
marci@280
    76
    graph_type& G;
marci@280
    77
    std::queue<out_edge_iterator>& bfs_queue;
marci@280
    78
    reached_type& reached;
marci@280
    79
    visitor_type& visitor;
marci@280
    80
    void process() {
marci@280
    81
      while ( !bfs_queue.empty() && !bfs_queue.front().valid() ) { bfs_queue.pop(); } 
marci@280
    82
      if (bfs_queue.empty()) return;
marci@280
    83
      out_edge_iterator e=bfs_queue.front();
marci@280
    84
      //node_iterator v=G.tail(e);
marci@280
    85
      node_iterator w=G.head(e);
marci@280
    86
      if (!reached.get(w)) {
marci@280
    87
	visitor.at_newly_reached(e);
marci@280
    88
	bfs_queue.push(G.first_out_edge(w));
marci@280
    89
	reached.put(w, true);
marci@280
    90
      } else {
marci@280
    91
	visitor.at_previously_reached(e);
marci@280
    92
      }
marci@280
    93
    }
marci@280
    94
    bfs_iterator(graph_type& _G, std::queue<out_edge_iterator>& _bfs_queue, reached_type& _reached, visitor_type& _visitor) : G(_G), bfs_queue(_bfs_queue), reached(_reached), visitor(_visitor) { 
marci@280
    95
      //while ( !bfs_queue.empty() && !bfs_queue.front().valid() ) { bfs_queue.pop(); } 
marci@280
    96
      valid();
marci@280
    97
    }
marci@280
    98
    bfs_iterator<graph_type, reached_type, visitor_type>& operator++() { 
marci@280
    99
      //while ( !bfs_queue.empty() && !bfs_queue.front().valid() ) { bfs_queue.pop(); } 
marci@280
   100
      //if (bfs_queue.empty()) return *this;
marci@280
   101
      if (!valid()) return *this;
marci@280
   102
      ++(bfs_queue.front());
marci@280
   103
      //while ( !bfs_queue.empty() && !bfs_queue.front().valid() ) { bfs_queue.pop(); } 
marci@280
   104
      valid();
marci@280
   105
      return *this;
marci@280
   106
    }
marci@280
   107
    //void next() { 
marci@280
   108
    //  while ( !bfs_queue.empty() && !bfs_queue.front().valid() ) { bfs_queue.pop(); } 
marci@280
   109
    //  if (bfs_queue.empty()) return;
marci@280
   110
    //  ++(bfs_queue.front());
marci@280
   111
    //  while ( !bfs_queue.empty() && !bfs_queue.front().valid() ) { bfs_queue.pop(); } 
marci@280
   112
    //}
marci@280
   113
    bool valid() { 
marci@280
   114
      while ( !bfs_queue.empty() && !bfs_queue.front().valid() ) { bfs_queue.pop(); } 
marci@280
   115
      if (bfs_queue.empty()) return false; else return true;
marci@280
   116
    }
marci@280
   117
    //bool finished() { 
marci@280
   118
    //  while ( !bfs_queue.empty() && !bfs_queue.front().valid() ) { bfs_queue.pop(); } 
marci@280
   119
    //  if (bfs_queue.empty()) return true; else return false;
marci@280
   120
    //}
marci@280
   121
    operator edge_iterator () { return bfs_queue.front(); }
marci@280
   122
marci@280
   123
  };
marci@280
   124
marci@280
   125
  template <typename graph_type, typename reached_type>
marci@280
   126
  struct bfs_iterator1 {
marci@280
   127
    typedef typename graph_type::node_iterator node_iterator;
marci@280
   128
    typedef typename graph_type::edge_iterator edge_iterator;
marci@280
   129
    typedef typename graph_type::out_edge_iterator out_edge_iterator;
marci@280
   130
    graph_type& G;
marci@280
   131
    std::queue<out_edge_iterator>& bfs_queue;
marci@280
   132
    reached_type& reached;
marci@280
   133
    bool _newly_reached;
marci@280
   134
    bfs_iterator1(graph_type& _G, std::queue<out_edge_iterator>& _bfs_queue, reached_type& _reached) : G(_G), bfs_queue(_bfs_queue), reached(_reached) { 
marci@280
   135
      valid();
marci@280
   136
      if (!bfs_queue.empty() && bfs_queue.front().valid()) { 
marci@280
   137
	out_edge_iterator e=bfs_queue.front();
marci@280
   138
	node_iterator w=G.head(e);
marci@280
   139
	if (!reached.get(w)) {
marci@280
   140
	  bfs_queue.push(G.first_out_edge(w));
marci@280
   141
	  reached.put(w, true);
marci@280
   142
	  _newly_reached=true;
marci@280
   143
	} else {
marci@280
   144
	  _newly_reached=false;
marci@280
   145
	}
marci@280
   146
      }
marci@280
   147
    }
marci@280
   148
    bfs_iterator1<graph_type, reached_type>& operator++() { 
marci@280
   149
      if (!valid()) return *this;
marci@280
   150
      ++(bfs_queue.front());
marci@280
   151
      valid();
marci@280
   152
      if (!bfs_queue.empty() && bfs_queue.front().valid()) { 
marci@280
   153
	out_edge_iterator e=bfs_queue.front();
marci@280
   154
	node_iterator w=G.head(e);
marci@280
   155
	if (!reached.get(w)) {
marci@280
   156
	  bfs_queue.push(G.first_out_edge(w));
marci@280
   157
	  reached.put(w, true);
marci@280
   158
	  _newly_reached=true;
marci@280
   159
	} else {
marci@280
   160
	  _newly_reached=false;
marci@280
   161
	}
marci@280
   162
      }
marci@280
   163
      return *this;
marci@280
   164
    }
marci@280
   165
    bool valid() { 
marci@280
   166
      while ( !bfs_queue.empty() && !bfs_queue.front().valid() ) { bfs_queue.pop(); } 
marci@280
   167
      if (bfs_queue.empty()) return false; else return true;
marci@280
   168
    }
marci@280
   169
    operator edge_iterator () { return bfs_queue.front(); }
marci@280
   170
    bool newly_reached() { return _newly_reached; }
marci@280
   171
marci@280
   172
  };
marci@280
   173
marci@280
   174
} // namespace hugo
marci@280
   175
marci@280
   176
#endif //MARCI_BFS_HH