src/work/marci/bfs_iterator.h
author marci
Mon, 26 Apr 2004 14:19:19 +0000
changeset 413 9cb93f692e92
parent 389 770cc1f4861f
child 414 3fd2eec272e0
permissions -rw-r--r--
misc
marci@301
     1
// -*- c++ -*-
marci@301
     2
#ifndef HUGO_BFS_ITERATOR_H
marci@301
     3
#define HUGO_BFS_ITERATOR_H
marci@301
     4
marci@301
     5
#include <queue>
marci@301
     6
#include <stack>
marci@301
     7
#include <utility>
marci@301
     8
marci@301
     9
namespace hugo {
marci@301
    10
marci@303
    11
  template <typename Graph, /*typename OutEdgeIt,*/ 
marci@303
    12
	    typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
marci@360
    13
  class BfsIterator {
marci@303
    14
  protected:
marci@303
    15
    typedef typename Graph::Node Node;
marci@303
    16
    typedef typename Graph::OutEdgeIt OutEdgeIt;
marci@303
    17
    const Graph* graph;
marci@301
    18
    std::queue<Node> bfs_queue;
marci@301
    19
    ReachedMap& reached;
marci@301
    20
    bool b_node_newly_reached;
marci@301
    21
    OutEdgeIt actual_edge;
marci@301
    22
    bool own_reached_map;
marci@301
    23
  public:
marci@360
    24
    BfsIterator(const Graph& _graph, ReachedMap& _reached) : 
marci@303
    25
      graph(&_graph), reached(_reached), 
marci@301
    26
      own_reached_map(false) { }
marci@360
    27
    BfsIterator(const Graph& _graph) : 
marci@303
    28
      graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))), 
marci@301
    29
      own_reached_map(true) { }
marci@360
    30
    ~BfsIterator() { if (own_reached_map) delete &reached; }
marci@409
    31
    //s is marcked reached.
marci@409
    32
    //if the queue is empty, then the its is pushed ant the first OutEdgeIt is processe.
marci@409
    33
    //is the queue is not empty, then is it pushed.
marci@301
    34
    void pushAndSetReached(Node s) { 
marci@301
    35
      reached.set(s, true);
marci@301
    36
      if (bfs_queue.empty()) {
marci@301
    37
	bfs_queue.push(s);
marci@303
    38
	graph->first(actual_edge, s);
marci@303
    39
	if (graph->valid(actual_edge)) { 
marci@303
    40
	  Node w=graph->bNode(actual_edge);
marci@303
    41
	  if (!reached[w]) {
marci@301
    42
	    bfs_queue.push(w);
marci@301
    43
	    reached.set(w, true);
marci@301
    44
	    b_node_newly_reached=true;
marci@301
    45
	  } else {
marci@301
    46
	    b_node_newly_reached=false;
marci@301
    47
	  }
marci@301
    48
	} 
marci@301
    49
      } else {
marci@301
    50
	bfs_queue.push(s);
marci@301
    51
      }
marci@301
    52
    }
marci@360
    53
    BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& 
marci@301
    54
    operator++() { 
marci@303
    55
      if (graph->valid(actual_edge)) { 
marci@303
    56
	graph->next(actual_edge);
marci@303
    57
	if (graph->valid(actual_edge)) {
marci@303
    58
	  Node w=graph->bNode(actual_edge);
marci@303
    59
	  if (!reached[w]) {
marci@301
    60
	    bfs_queue.push(w);
marci@301
    61
	    reached.set(w, true);
marci@301
    62
	    b_node_newly_reached=true;
marci@301
    63
	  } else {
marci@301
    64
	    b_node_newly_reached=false;
marci@301
    65
	  }
marci@301
    66
	}
marci@301
    67
      } else {
marci@301
    68
	bfs_queue.pop(); 
marci@301
    69
	if (!bfs_queue.empty()) {
marci@303
    70
	  graph->first(actual_edge, bfs_queue.front());
marci@303
    71
	  if (graph->valid(actual_edge)) {
marci@303
    72
	    Node w=graph->bNode(actual_edge);
marci@303
    73
	    if (!reached[w]) {
marci@301
    74
	      bfs_queue.push(w);
marci@301
    75
	      reached.set(w, true);
marci@301
    76
	      b_node_newly_reached=true;
marci@301
    77
	    } else {
marci@301
    78
	      b_node_newly_reached=false;
marci@301
    79
	    }
marci@301
    80
	  }
marci@301
    81
	}
marci@301
    82
      }
marci@301
    83
      return *this;
marci@301
    84
    }
marci@301
    85
    bool finished() const { return bfs_queue.empty(); }
marci@409
    86
    operator OutEdgeIt() const { return actual_edge; }
marci@301
    87
    bool isBNodeNewlyReached() const { return b_node_newly_reached; }
marci@303
    88
    bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
marci@301
    89
    Node aNode() const { return bfs_queue.front(); }
marci@303
    90
    Node bNode() const { return graph->bNode(actual_edge); }
marci@301
    91
    const ReachedMap& getReachedMap() const { return reached; }
marci@301
    92
    const std::queue<Node>& getBfsQueue() const { return bfs_queue; }
marci@301
    93
  };  
marci@301
    94
marci@409
    95
  /// Bfs searches from s for the nodes wich are not marked in 
marci@409
    96
  /// reachedmap
marci@409
    97
  template <typename Graph, 
marci@409
    98
	    typename ReachedMap=typename Graph::template NodeMap<bool>, 
marci@409
    99
	    typename PredMap
marci@409
   100
	    =typename Graph::template NodeMap<typename Graph::Edge>, 
marci@409
   101
	    typename DistMap=typename Graph::template NodeMap<int> > 
marci@409
   102
  class Bfs : public BfsIterator<Graph, ReachedMap> {
marci@409
   103
    typedef BfsIterator<Graph, ReachedMap> Parent;
marci@409
   104
  protected:
marci@409
   105
    typedef typename Parent::Node Node;
marci@409
   106
    PredMap& pred;
marci@409
   107
    DistMap& dist;
marci@409
   108
  public:
marci@409
   109
    Bfs<Graph, ReachedMap, PredMap, DistMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred, DistMap& _dist) : BfsIterator<Graph, ReachedMap>(_graph, _reached), pred(&_pred), dist(&_dist) { }
marci@409
   110
    //s is marked to be reached and pushed in the bfs queue.
marci@409
   111
    //if the queue is empty, then the first out-edge is processed
marci@409
   112
    //If s was not marked previously, then 
marci@409
   113
    //in addition its pred is set to be INVALID, and dist to 0. 
marci@409
   114
    //if s was marked previuosly, then it is simply pushed.
marci@409
   115
    void push(Node s) { 
marci@409
   116
      if (this->reached[s]) {
marci@409
   117
	Parent::pushAndSetReached(s);
marci@409
   118
      } else {
marci@409
   119
	Parent::pushAndSetReached(s);
marci@409
   120
	pred.set(s, INVALID);
marci@409
   121
	dist.set(s, 0);
marci@409
   122
      }
marci@409
   123
    }
marci@409
   124
    void run(Node s) {
marci@409
   125
      push(s);
marci@409
   126
      while (!this->finished()) this->operator++();
marci@409
   127
    }
marci@409
   128
    Bfs<Graph, ReachedMap, PredMap, DistMap> operator++() {
marci@409
   129
      Parent::operator++();
marci@409
   130
      if (this->graph->valid(actual_edge) && this->b_node_newly_reached) {
marci@409
   131
	pred.set(s, actual_edge);
marci@409
   132
	dist.set(s, dist[this->aNode()]);
marci@409
   133
      }
marci@409
   134
      return *this;
marci@409
   135
    }
marci@409
   136
    const PredMap& getPredMap() const { return pred; }
marci@409
   137
    const DistMap& getDistMap() const { return dist; }
marci@409
   138
  };
marci@409
   139
marci@303
   140
  template <typename Graph, /*typename OutEdgeIt,*/ 
marci@303
   141
	    typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
marci@360
   142
  class DfsIterator {
marci@303
   143
  protected:
marci@303
   144
    typedef typename Graph::Node Node;
marci@303
   145
    typedef typename Graph::OutEdgeIt OutEdgeIt;
marci@303
   146
    const Graph* graph;
marci@301
   147
    std::stack<OutEdgeIt> dfs_stack;
marci@301
   148
    bool b_node_newly_reached;
marci@301
   149
    OutEdgeIt actual_edge;
marci@301
   150
    Node actual_node;
marci@301
   151
    ReachedMap& reached;
marci@301
   152
    bool own_reached_map;
marci@301
   153
  public:
marci@360
   154
    DfsIterator(const Graph& _graph, ReachedMap& _reached) : 
marci@303
   155
      graph(&_graph), reached(_reached), 
marci@301
   156
      own_reached_map(false) { }
marci@360
   157
    DfsIterator(const Graph& _graph) : 
marci@303
   158
      graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))), 
marci@301
   159
      own_reached_map(true) { }
marci@360
   160
    ~DfsIterator() { if (own_reached_map) delete &reached; }
marci@301
   161
    void pushAndSetReached(Node s) { 
marci@301
   162
      actual_node=s;
marci@301
   163
      reached.set(s, true);
marci@301
   164
      OutEdgeIt e;
marci@303
   165
      graph->first(e, s);
marci@301
   166
      dfs_stack.push(e); 
marci@301
   167
    }
marci@360
   168
    DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& 
marci@301
   169
    operator++() { 
marci@301
   170
      actual_edge=dfs_stack.top();
marci@301
   171
      //actual_node=G.aNode(actual_edge);
marci@303
   172
      if (graph->valid(actual_edge)/*.valid()*/) { 
marci@303
   173
	Node w=graph->bNode(actual_edge);
marci@301
   174
	actual_node=w;
marci@303
   175
	if (!reached[w]) {
marci@301
   176
	  OutEdgeIt e;
marci@303
   177
	  graph->first(e, w);
marci@301
   178
	  dfs_stack.push(e);
marci@301
   179
	  reached.set(w, true);
marci@301
   180
	  b_node_newly_reached=true;
marci@301
   181
	} else {
marci@303
   182
	  actual_node=graph->aNode(actual_edge);
marci@303
   183
	  graph->next(dfs_stack.top());
marci@301
   184
	  b_node_newly_reached=false;
marci@301
   185
	}
marci@301
   186
      } else {
marci@301
   187
	//actual_node=G.aNode(dfs_stack.top());
marci@301
   188
	dfs_stack.pop();
marci@301
   189
      }
marci@301
   190
      return *this;
marci@301
   191
    }
marci@301
   192
    bool finished() const { return dfs_stack.empty(); }
marci@409
   193
    operator OutEdgeIt() const { return actual_edge; }
marci@301
   194
    bool isBNodeNewlyReached() const { return b_node_newly_reached; }
marci@303
   195
    bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
marci@301
   196
    Node aNode() const { return actual_node; /*FIXME*/}
marci@389
   197
    Node bNode() const { return graph->bNode(actual_edge); }
marci@301
   198
    const ReachedMap& getReachedMap() const { return reached; }
marci@301
   199
    const std::stack<OutEdgeIt>& getDfsStack() const { return dfs_stack; }
marci@301
   200
  };
marci@301
   201
marci@301
   202
} // namespace hugo
marci@301
   203
marci@301
   204
#endif //HUGO_BFS_ITERATOR_H