7 /// \brief Bfs and dfs iterators.
9 /// This file contains bfs and dfs iterator classes.
11 // /// \author Marton Makai
17 #include <hugo/invalid.h>
21 /// Bfs searches for the nodes wich are not marked in
23 /// Reached have to work as read-write bool Node-map.
25 template <typename Graph, /*typename OutEdgeIt,*/
26 typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
29 typedef typename Graph::Node Node;
30 typedef typename Graph::OutEdgeIt OutEdgeIt;
32 std::queue<Node> bfs_queue;
34 bool b_node_newly_reached;
35 OutEdgeIt actual_edge;
38 /// In that constructor \c _reached have to be a reference
39 /// for a bool Node-map. The algorithm will search in a bfs order for
40 /// the nodes which are \c false initially
41 BfsIterator(const Graph& _graph, ReachedMap& _reached) :
42 graph(&_graph), reached(_reached),
43 own_reached_map(false) { }
44 /// The same as above, but the map storing the reached nodes
45 /// is constructed dynamically to everywhere false.
46 BfsIterator(const Graph& _graph) :
47 graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))),
48 own_reached_map(true) { }
49 /// The map storing the reached nodes have to be destroyed if
50 /// it was constructed dynamically
51 ~BfsIterator() { if (own_reached_map) delete &reached; }
52 /// This method markes \c s reached.
53 /// If the queue is empty, then \c s is pushed in the bfs queue
54 /// and the first out-edge is processed.
55 /// If the queue is not empty, then \c s is simply pushed.
56 void pushAndSetReached(Node s) {
58 if (bfs_queue.empty()) {
60 graph->first(actual_edge, s);
61 if (graph->valid(actual_edge)) {
62 Node w=graph->bNode(actual_edge);
66 b_node_newly_reached=true;
68 b_node_newly_reached=false;
75 /// As \c BfsIterator<Graph, ReachedMap> works as an edge-iterator,
76 /// its \c operator++() iterates on the edges in a bfs order.
77 BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&
79 if (graph->valid(actual_edge)) {
80 graph->next(actual_edge);
81 if (graph->valid(actual_edge)) {
82 Node w=graph->bNode(actual_edge);
86 b_node_newly_reached=true;
88 b_node_newly_reached=false;
93 if (!bfs_queue.empty()) {
94 graph->first(actual_edge, bfs_queue.front());
95 if (graph->valid(actual_edge)) {
96 Node w=graph->bNode(actual_edge);
100 b_node_newly_reached=true;
102 b_node_newly_reached=false;
110 bool finished() const { return bfs_queue.empty(); }
111 /// The conversion operator makes for converting the bfs-iterator
112 /// to an \c out-edge-iterator.
113 ///\bug Edge have to be in HUGO 0.2
114 operator OutEdgeIt() const { return actual_edge; }
116 bool isBNodeNewlyReached() const { return b_node_newly_reached; }
118 bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
120 Node aNode() const { return bfs_queue.front(); }
122 Node bNode() const { return graph->bNode(actual_edge); }
124 const ReachedMap& getReachedMap() const { return reached; }
126 const std::queue<Node>& getBfsQueue() const { return bfs_queue; }
129 /// Bfs searches for the nodes wich are not marked in
131 /// Reached have to work as a read-write bool Node-map,
132 /// Pred is a write Edge Node-map and
133 /// Dist is a read-write Node-map of integral value, have to be.
135 template <typename Graph,
136 typename ReachedMap=typename Graph::template NodeMap<bool>,
138 =typename Graph::template NodeMap<typename Graph::Edge>,
139 typename DistMap=typename Graph::template NodeMap<int> >
140 class Bfs : public BfsIterator<Graph, ReachedMap> {
141 typedef BfsIterator<Graph, ReachedMap> Parent;
143 typedef typename Parent::Node Node;
147 /// The algorithm will search in a bfs order for
148 /// the nodes which are \c false initially.
149 /// The constructor makes no initial changes on the maps.
150 Bfs<Graph, ReachedMap, PredMap, DistMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred, DistMap& _dist) : BfsIterator<Graph, ReachedMap>(_graph, _reached), pred(&_pred), dist(&_dist) { }
151 /// \c s is marked to be reached and pushed in the bfs queue.
152 /// If the queue is empty, then the first out-edge is processed.
153 /// If \c s was not marked previously, then
154 /// in addition its pred is set to be \c INVALID, and dist to \c 0.
155 /// if \c s was marked previuosly, then it is simply pushed.
157 if (this->reached[s]) {
158 Parent::pushAndSetReached(s);
160 Parent::pushAndSetReached(s);
161 pred.set(s, INVALID);
165 /// A bfs is processed from \c s.
168 while (!this->finished()) this->operator++();
170 /// Beside the bfs iteration, \c pred and \dist are saved in a
171 /// newly reached node.
172 Bfs<Graph, ReachedMap, PredMap, DistMap>& operator++() {
173 Parent::operator++();
174 if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached)
176 pred.set(this->bNode(), this->actual_edge);
177 dist.set(this->bNode(), dist[this->aNode()]);
182 const PredMap& getPredMap() const { return pred; }
184 const DistMap& getDistMap() const { return dist; }
187 /// Dfs searches for the nodes wich are not marked in
189 /// Reached have to be a read-write bool Node-map.
191 template <typename Graph, /*typename OutEdgeIt,*/
192 typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
195 typedef typename Graph::Node Node;
196 typedef typename Graph::OutEdgeIt OutEdgeIt;
198 std::stack<OutEdgeIt> dfs_stack;
199 bool b_node_newly_reached;
200 OutEdgeIt actual_edge;
203 bool own_reached_map;
205 /// In that constructor \c _reached have to be a reference
206 /// for a bool Node-map. The algorithm will search in a dfs order for
207 /// the nodes which are \c false initially
208 DfsIterator(const Graph& _graph, ReachedMap& _reached) :
209 graph(&_graph), reached(_reached),
210 own_reached_map(false) { }
211 /// The same as above, but the map of reached nodes is
212 /// constructed dynamically
213 /// to everywhere false.
214 DfsIterator(const Graph& _graph) :
215 graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))),
216 own_reached_map(true) { }
217 ~DfsIterator() { if (own_reached_map) delete &reached; }
218 /// This method markes s reached and first out-edge is processed.
219 void pushAndSetReached(Node s) {
221 reached.set(s, true);
226 /// As \c DfsIterator<Graph, ReachedMap> works as an edge-iterator,
227 /// its \c operator++() iterates on the edges in a dfs order.
228 DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&
230 actual_edge=dfs_stack.top();
231 //actual_node=G.aNode(actual_edge);
232 if (graph->valid(actual_edge)/*.valid()*/) {
233 Node w=graph->bNode(actual_edge);
239 reached.set(w, true);
240 b_node_newly_reached=true;
242 actual_node=graph->aNode(actual_edge);
243 graph->next(dfs_stack.top());
244 b_node_newly_reached=false;
247 //actual_node=G.aNode(dfs_stack.top());
253 bool finished() const { return dfs_stack.empty(); }
255 operator OutEdgeIt() const { return actual_edge; }
257 bool isBNodeNewlyReached() const { return b_node_newly_reached; }
259 bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
261 Node aNode() const { return actual_node; /*FIXME*/}
263 Node bNode() const { return graph->bNode(actual_edge); }
265 const ReachedMap& getReachedMap() const { return reached; }
267 const std::stack<OutEdgeIt>& getDfsStack() const { return dfs_stack; }
270 /// Dfs searches for the nodes wich are not marked in
272 /// Reached is a read-write bool Node-map,
273 /// Pred is a write Node-map, have to be.
275 template <typename Graph,
276 typename ReachedMap=typename Graph::template NodeMap<bool>,
278 =typename Graph::template NodeMap<typename Graph::Edge> >
279 class Dfs : public DfsIterator<Graph, ReachedMap> {
280 typedef DfsIterator<Graph, ReachedMap> Parent;
282 typedef typename Parent::Node Node;
285 /// The algorithm will search in a dfs order for
286 /// the nodes which are \c false initially.
287 /// The constructor makes no initial changes on the maps.
288 Dfs<Graph, ReachedMap, PredMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred) : DfsIterator<Graph, ReachedMap>(_graph, _reached), pred(&_pred) { }
289 /// \c s is marked to be reached and pushed in the bfs queue.
290 /// If the queue is empty, then the first out-edge is processed.
291 /// If \c s was not marked previously, then
292 /// in addition its pred is set to be \c INVALID.
293 /// if \c s was marked previuosly, then it is simply pushed.
295 if (this->reached[s]) {
296 Parent::pushAndSetReached(s);
298 Parent::pushAndSetReached(s);
299 pred.set(s, INVALID);
302 /// A bfs is processed from \c s.
305 while (!this->finished()) this->operator++();
307 /// Beside the dfs iteration, \c pred is saved in a
308 /// newly reached node.
309 Dfs<Graph, ReachedMap, PredMap>& operator++() {
310 Parent::operator++();
311 if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached)
313 pred.set(this->bNode(), this->actual_edge);
318 const PredMap& getPredMap() const { return pred; }
324 #endif //HUGO_BFS_DFS_H