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