src/work/marci/bfs_iterator.h
author jacint
Thu, 22 Apr 2004 15:56:05 +0000
changeset 374 0fc9cd9b854a
parent 303 1b377a730d02
child 389 770cc1f4861f
permissions -rw-r--r--
(none)
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@301
    31
    void pushAndSetReached(Node s) { 
marci@301
    32
      reached.set(s, true);
marci@301
    33
      if (bfs_queue.empty()) {
marci@301
    34
	bfs_queue.push(s);
marci@303
    35
	graph->first(actual_edge, s);
marci@303
    36
	if (graph->valid(actual_edge)) { 
marci@303
    37
	  Node w=graph->bNode(actual_edge);
marci@303
    38
	  if (!reached[w]) {
marci@301
    39
	    bfs_queue.push(w);
marci@301
    40
	    reached.set(w, true);
marci@301
    41
	    b_node_newly_reached=true;
marci@301
    42
	  } else {
marci@301
    43
	    b_node_newly_reached=false;
marci@301
    44
	  }
marci@301
    45
	} 
marci@301
    46
      } else {
marci@301
    47
	bfs_queue.push(s);
marci@301
    48
      }
marci@301
    49
    }
marci@360
    50
    BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& 
marci@301
    51
    operator++() { 
marci@303
    52
      if (graph->valid(actual_edge)) { 
marci@303
    53
	graph->next(actual_edge);
marci@303
    54
	if (graph->valid(actual_edge)) {
marci@303
    55
	  Node w=graph->bNode(actual_edge);
marci@303
    56
	  if (!reached[w]) {
marci@301
    57
	    bfs_queue.push(w);
marci@301
    58
	    reached.set(w, true);
marci@301
    59
	    b_node_newly_reached=true;
marci@301
    60
	  } else {
marci@301
    61
	    b_node_newly_reached=false;
marci@301
    62
	  }
marci@301
    63
	}
marci@301
    64
      } else {
marci@301
    65
	bfs_queue.pop(); 
marci@301
    66
	if (!bfs_queue.empty()) {
marci@303
    67
	  graph->first(actual_edge, bfs_queue.front());
marci@303
    68
	  if (graph->valid(actual_edge)) {
marci@303
    69
	    Node w=graph->bNode(actual_edge);
marci@303
    70
	    if (!reached[w]) {
marci@301
    71
	      bfs_queue.push(w);
marci@301
    72
	      reached.set(w, true);
marci@301
    73
	      b_node_newly_reached=true;
marci@301
    74
	    } else {
marci@301
    75
	      b_node_newly_reached=false;
marci@301
    76
	    }
marci@301
    77
	  }
marci@301
    78
	}
marci@301
    79
      }
marci@301
    80
      return *this;
marci@301
    81
    }
marci@301
    82
    bool finished() const { return bfs_queue.empty(); }
marci@301
    83
    operator OutEdgeIt () const { return actual_edge; }
marci@301
    84
    bool isBNodeNewlyReached() const { return b_node_newly_reached; }
marci@303
    85
    bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
marci@301
    86
    Node aNode() const { return bfs_queue.front(); }
marci@303
    87
    Node bNode() const { return graph->bNode(actual_edge); }
marci@301
    88
    const ReachedMap& getReachedMap() const { return reached; }
marci@301
    89
    const std::queue<Node>& getBfsQueue() const { return bfs_queue; }
marci@301
    90
  };  
marci@301
    91
marci@303
    92
  template <typename Graph, /*typename OutEdgeIt,*/ 
marci@303
    93
	    typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
marci@360
    94
  class DfsIterator {
marci@303
    95
  protected:
marci@303
    96
    typedef typename Graph::Node Node;
marci@303
    97
    typedef typename Graph::OutEdgeIt OutEdgeIt;
marci@303
    98
    const Graph* graph;
marci@301
    99
    std::stack<OutEdgeIt> dfs_stack;
marci@301
   100
    bool b_node_newly_reached;
marci@301
   101
    OutEdgeIt actual_edge;
marci@301
   102
    Node actual_node;
marci@301
   103
    ReachedMap& reached;
marci@301
   104
    bool own_reached_map;
marci@301
   105
  public:
marci@360
   106
    DfsIterator(const Graph& _graph, ReachedMap& _reached) : 
marci@303
   107
      graph(&_graph), reached(_reached), 
marci@301
   108
      own_reached_map(false) { }
marci@360
   109
    DfsIterator(const Graph& _graph) : 
marci@303
   110
      graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))), 
marci@301
   111
      own_reached_map(true) { }
marci@360
   112
    ~DfsIterator() { if (own_reached_map) delete &reached; }
marci@301
   113
    void pushAndSetReached(Node s) { 
marci@301
   114
      actual_node=s;
marci@301
   115
      reached.set(s, true);
marci@301
   116
      OutEdgeIt e;
marci@303
   117
      graph->first(e, s);
marci@301
   118
      dfs_stack.push(e); 
marci@301
   119
    }
marci@360
   120
    DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>& 
marci@301
   121
    operator++() { 
marci@301
   122
      actual_edge=dfs_stack.top();
marci@301
   123
      //actual_node=G.aNode(actual_edge);
marci@303
   124
      if (graph->valid(actual_edge)/*.valid()*/) { 
marci@303
   125
	Node w=graph->bNode(actual_edge);
marci@301
   126
	actual_node=w;
marci@303
   127
	if (!reached[w]) {
marci@301
   128
	  OutEdgeIt e;
marci@303
   129
	  graph->first(e, w);
marci@301
   130
	  dfs_stack.push(e);
marci@301
   131
	  reached.set(w, true);
marci@301
   132
	  b_node_newly_reached=true;
marci@301
   133
	} else {
marci@303
   134
	  actual_node=graph->aNode(actual_edge);
marci@303
   135
	  graph->next(dfs_stack.top());
marci@301
   136
	  b_node_newly_reached=false;
marci@301
   137
	}
marci@301
   138
      } else {
marci@301
   139
	//actual_node=G.aNode(dfs_stack.top());
marci@301
   140
	dfs_stack.pop();
marci@301
   141
      }
marci@301
   142
      return *this;
marci@301
   143
    }
marci@301
   144
    bool finished() const { return dfs_stack.empty(); }
marci@301
   145
    operator OutEdgeIt () const { return actual_edge; }
marci@301
   146
    bool isBNodeNewlyReached() const { return b_node_newly_reached; }
marci@303
   147
    bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
marci@301
   148
    Node aNode() const { return actual_node; /*FIXME*/}
marci@301
   149
    Node bNode() const { return G.bNode(actual_edge); }
marci@301
   150
    const ReachedMap& getReachedMap() const { return reached; }
marci@301
   151
    const std::stack<OutEdgeIt>& getDfsStack() const { return dfs_stack; }
marci@301
   152
  };
marci@301
   153
marci@301
   154
} // namespace hugo
marci@301
   155
marci@301
   156
#endif //HUGO_BFS_ITERATOR_H