![]() |
|
|||
File indexing completed on 2025-08-03 08:19:36
0001 /* This software is distributed under the GNU Lesser General Public License */ 0002 //========================================================================== 0003 // 0004 // dfs.h 0005 // 0006 //========================================================================== 0007 // $Id: dfs.h,v 1.25 2003/03/24 15:58:54 raitner Exp $ 0008 0009 #ifndef GTL_DFS_H 0010 #define GTL_DFS_H 0011 0012 #include <GTL/GTL.h> 0013 #include <GTL/algorithm.h> 0014 0015 __GTL_BEGIN_NAMESPACE 0016 0017 /** 0018 * $Date: 2003/03/24 15:58:54 $ 0019 * $Revision: 1.25 $ 0020 * 0021 * @brief Depth-First-Search (DFS) %algorithm 0022 * 0023 * Encapsulates the DFS %algoritm together with all the data 0024 * produced by a run of DFS. Since there exits so much different 0025 * things which one might want to calculate during a DFS this 0026 * class provides basically two different customization 0027 * features. First it is possible to take influence on the 0028 * behaviour of this %algortihm by changing some of the following 0029 * options: 0030 * - dfs::start_node 0031 * (default: an arbitrary %node will be chosen) 0032 * - dfs::scan_whole_graph states whether BFS will be 0033 * continued in the unused part of the %graph, if not all 0034 * nodes were touched at the end of DFS started at the start-%node. 0035 * (default: disabled) 0036 * - dfs::calc_comp_num toggle storing of completion-numbers 0037 * for each %node, i.e. a numbering which reflects the order in which 0038 * nodes were @em finished. (default: disabled) 0039 * - dfs::store_preds toggle storing the predecessor of each 0040 * %node, i.e. the father in DFS-tree. (default: disabled) 0041 * - dfs::store_non_tree_edges toggle storing of all non-tree-edges 0042 * (tree-edges are always stored) in a list and thus enable or disable 0043 * iteration through all non-tree-edges. 0044 * (default: disabled) 0045 * 0046 * But the trouble with most DFS-%algorithm is that one always 0047 * wants to add a little bit of code somewhere in the 0048 * %algorithm. And then there are only two ways to get this 0049 * done. The more efficient one (in terms of runtime) is to 0050 * implement the DFS anew and add the new code where 0051 * necessary. The other way (which is more efficient in terms of 0052 * code-writing) is to take the %algorithm as provided and run 0053 * through the list of nodes it returns (resulting in an extra 0054 * factor of 2). 0055 * 0056 * Our DFS-%algoritm class provides a new method to add small 0057 * pieces of code to the %algorithm: Handler. These are virtual 0058 * functions called at well-defined, important states of the 0059 * %algorithm (e.g. before a new recursive call). So the only 0060 * thing to do is to derive your extended DFS from this class and 0061 * to override the handlers where needed. In detail there are the 0062 * following handler supported (have a look at the source code 0063 * for details): 0064 * - dfs::init_handler 0065 * - dfs::end_handler 0066 * - dfs::entry_handler 0067 * - dfs::leave_handler 0068 * - dfs::before_recursive_call_handler 0069 * - dfs::after_recursive_call_handler 0070 * - dfs::old_adj_node_handler 0071 * - dfs::new_start_handler 0072 * 0073 * @em Please @em note: We do @em not claim that this set of handlers 0074 * is sufficient in any way. So if you believe that some new handler is 0075 * needed urgently please let us know. 0076 * 0077 * There is a lot of information stored during DFS (e.g. nodes in 0078 * dfs-order, list of non-tree-edges). Some of it can be obtained directly 0079 * by using the corresponding member-function (e.g. dfs::dfs_num), 0080 * but all information that can be thought of as a list (e.g. nodes in 0081 * dfs-order) can be accessed through iterators. In detail these are (of 0082 * course depending on what options are chosen!): 0083 * - dfs::dfs_iterator 0084 * - dfs::tree_edges_iterator 0085 * - dfs::non_tree_edges_iterator 0086 * - dfs::roots_iterator 0087 */ 0088 class GTL_EXTERN dfs : public algorithm 0089 { 0090 public: 0091 /** 0092 * @brief Constructor. 0093 */ 0094 dfs (); 0095 0096 0097 /** 0098 * @brief Destructor. 0099 */ 0100 virtual ~dfs (); 0101 0102 int run (graph& G); 0103 0104 /** 0105 * @brief Checks whether the preconditions for DFS are 0106 * satisfied. 0107 * 0108 * Currently there aren't any restricitions for the DFS 0109 * %algorithm. 0110 * 0111 * @param G graph. 0112 * @retval algorithm::GTL_OK if %algorithm can be applied 0113 * @retval algorithm::GTL_ERROR otherwise. 0114 */ 0115 virtual int check (graph& G); 0116 0117 virtual void reset (); 0118 0119 0120 //--------------------------------------------------------------------- 0121 // Parameters 0122 //--------------------------------------------------------------------- 0123 0124 /** 0125 * @brief Sets start-%node for DFS. 0126 * 0127 * @param n start-node. 0128 */ 0129 void start_node (const node& n) 0130 { start = n; } 0131 0132 /** 0133 * @brief Returns start-%node for DFS. 0134 * 0135 * @return start-%node. 0136 */ 0137 node start_node () const {return start;} 0138 0139 /** 0140 * @brief Enables or disables scanning of the whole %graph. 0141 * 0142 * If enabled and the DFS started at the given start-%node 0143 * stops without having touched all nodes, it will be 0144 * continued with the next unused %node, and so on until all 0145 * nodes were used. This makes sure that for every %node 0146 * #dfs_number is defined. 0147 * 0148 * On the other hand, if this feature is disabled, one 0149 * will be able to check what nodes can be reached, when 0150 * starting a DFS at the start-%node, because for those not 0151 * reached #dfs_number will be 0. 0152 * 0153 * @param set if true enable scanning the whole graph. 0154 * @sa dfs::roots_begin 0155 * @sa dfs::roots_end 0156 */ 0157 void scan_whole_graph (bool set) {whole_graph = set;} 0158 0159 /** 0160 * @brief Returns true iff the whole graph will be scanned. 0161 * 0162 * @retval true iff the whole graph will be scanned. 0163 * @sa dfs::roots_begin 0164 * @sa dfs::roots_end 0165 */ 0166 bool scan_whole_graph () const {return whole_graph;} 0167 0168 /** 0169 * @brief Enables or Disables the calculation of the completion number. 0170 * 0171 * @param set if true completion-numbers will be calculated. 0172 * @sa dfs::comp_num 0173 */ 0174 void calc_comp_num (bool set); 0175 0176 /** 0177 * @brief Returns true iff completion-numbers will be calculated. 0178 * 0179 * @retval true iff completion-numbers will be calculated. 0180 * @sa dfs::comp_num 0181 */ 0182 bool calc_comp_num () const {return comp_number != 0;} 0183 0184 0185 /** 0186 * @brief Enables or disables the storing of predecessors. 0187 * 0188 * If enabled for every %node the predecessor in DFS will be 0189 * stored. 0190 * 0191 * @param set if true predecessors will be stored. 0192 * @sa dfs::father 0193 */ 0194 void store_preds (bool set); 0195 0196 /** 0197 * @brief Returns true iff the storing of predecessors is enabled. 0198 * 0199 * @retval true iff the storing of predecessors is enabled. 0200 * @sa dfs::father 0201 */ 0202 bool store_preds () const {return preds != 0;} 0203 0204 /** 0205 * @brief Enables the storing of back-edges. 0206 * 0207 * If enabled the list of non-tree-edges can be traversed in 0208 * the order they occured using #non_tree_edges_iterator. 0209 * 0210 * @param set if true non_tree_edges will be stored. 0211 * @sa dfs::non_tree_edges_begin 0212 * @sa dfs::non_tree_edges_end 0213 */ 0214 void store_non_tree_edges (bool set); 0215 0216 /** 0217 * @brief Returns true iff the storing of non-tree-edges is enabled. 0218 * 0219 * @return true iff the storing of non-tree-edges is enabled. 0220 * @sa dfs::non_tree_edges_begin 0221 * @sa dfs::non_tree_edges_end 0222 */ 0223 bool store_non_tree_edges () const {return back_edges != 0;} 0224 0225 //--------------------------------------------------------------------- 0226 // Access 0227 //---------------------------------------------------------------------- 0228 0229 /** 0230 * @brief Checks whether %node @a n was reached in last DFS. 0231 * 0232 * @param n %node to be checked. 0233 * @return true iff @a n was reached. 0234 */ 0235 bool reached (const node& n) const 0236 {return dfs_number[n] != 0;} 0237 0238 /** 0239 * @brief DFS-Number of @a n. 0240 * 0241 * Please note that DFS-Number 0 means that this %node wasn't 0242 * reached. 0243 * 0244 * @param n %node. 0245 * @return DFS-Number of @a n. 0246 */ 0247 int dfs_num (const node& n) const 0248 {return dfs_number[n];} 0249 0250 /** 0251 * @brief DFS-Number of @a n. 0252 * 0253 * Please note that DFS-Number 0 means that this %node wasn't 0254 * reached. 0255 * 0256 * @param n %node. 0257 * @return DFS-Number of @a n. 0258 */ 0259 int operator[] (const node& n) const 0260 {return dfs_number[n];} 0261 0262 /** 0263 * @brief Completion-number of %node @a n, if enabled in last 0264 * run. 0265 * 0266 * @param n %node. 0267 * @return Completion-number of @a n. 0268 * @sa dfs::calc_comp_num 0269 */ 0270 int comp_num (const node& n) const 0271 {assert (comp_number); return (*comp_number)[n];} 0272 0273 /** 0274 * @brief Returns father of node @a n in DFS-forest. 0275 * 0276 * If @a n is a root in the forest or wasn't reached the 0277 * return value is @c node(). 0278 * 0279 * @param n %node. 0280 * @return Father of @a n. 0281 * @sa dfs::store_preds 0282 */ 0283 node father (const node& n) const 0284 {assert (preds); return (*preds)[n];} 0285 0286 /** 0287 * @brief Iterator for the tree edges of the DFS-tree. 0288 */ 0289 typedef list<edge>::const_iterator tree_edges_iterator; 0290 0291 /** 0292 * @brief Iterate through all edges picked in last DFS. 0293 * 0294 * Please note that this edges not always form a tree. In 0295 * case the %graph is not (strongly) connected they form a 0296 * forest. 0297 * 0298 * @return start for iteration through all edges followed in DFS. 0299 */ 0300 tree_edges_iterator tree_edges_begin () const 0301 {return tree.begin();} 0302 0303 /** 0304 * @brief End-iterator for iteration through all edges picked in last DFS. 0305 * 0306 * @return end for iteration through all edges followed in DFS. 0307 */ 0308 tree_edges_iterator tree_edges_end () const 0309 {return tree.end();} 0310 0311 /** 0312 * @brief Iterator for the (reached) nodes in DFS-order. 0313 */ 0314 typedef list<node>::const_iterator dfs_iterator; 0315 0316 /** 0317 * @brief Iterate through all (reached) nodes in DFS-order. 0318 * 0319 * @return start for iteration through all nodes in DFS-order. 0320 */ 0321 dfs_iterator begin () const 0322 {return dfs_order.begin();} 0323 0324 /** 0325 * @brief End-Iterator for iteration through all (reached) 0326 * nodes in DFS-order. 0327 * 0328 * @return end for iteration through all (reached) nodes 0329 */ 0330 dfs_iterator end () const 0331 {return dfs_order.end();} 0332 0333 /** 0334 * @brief Iterator for the non-tree-edges 0335 */ 0336 typedef list<edge>::const_iterator non_tree_edges_iterator; 0337 0338 /** 0339 * @brief Iterate through all non-tree-edges (if enabled). 0340 * 0341 * @return start for iteration through all non-tree-edges. 0342 * @sa dfs::store_non_tree_edges 0343 */ 0344 non_tree_edges_iterator non_tree_edges_begin () const 0345 {assert (back_edges); return back_edges->begin(); } 0346 0347 /** 0348 * @brief End-iterator for iteration through all 0349 * non-tree-edges (if enabled). 0350 * 0351 * @return end for iteration through all non-tree-edges. 0352 * @sa dfs::store_non_tree_edges 0353 */ 0354 non_tree_edges_iterator non_tree_edges_end () const 0355 {assert (back_edges); return back_edges->end(); } 0356 0357 /** 0358 * @brief Iterator for the roots of the DFS-forest. 0359 */ 0360 typedef list<dfs_iterator>::const_iterator roots_iterator; 0361 0362 /** 0363 * @brief Iterator pointing towards the first root in the DFS-forest. 0364 * 0365 * <em>Please note</em> that intstead of pointing directly 0366 * towards the node (i.e. @c *it is of type node) the 0367 * iterator points towards a #dfs_iterator, which represents 0368 * the root (i.e. @c *it is of type #dfs_iterator). 0369 * 0370 * Using this technique makes it possible not only to obtain 0371 * all the roots in the forest, but also the whole trees 0372 * associated with each one. This can be achieved because a 0373 * #root_iterator specifies the exact position of the root in 0374 * the DFS-ordering and by definition of DFS all the 0375 * descendents of the root, i.e. the whole tree, will come 0376 * later in DFS, such that by incrementing the #dfs_iterator, 0377 * a #roots_iterator points at, one can traverse the whole 0378 * tree with this given root. 0379 * 0380 * Of course if the root isn't the last node in the 0381 * DFS-forest on will also traverse all following trees, but 0382 * since the first node of such a tree one will discover is 0383 * its root, the successor of the #roots_iterator can be used 0384 * as end-iterator. 0385 * 0386 * @return start for iteration through all roots in DFS-forest. 0387 * @sa dfs::scan_whole_graph 0388 */ 0389 roots_iterator roots_begin () const 0390 {return roots.begin();} 0391 0392 /** 0393 * @brief Iterator pointing to the end of all roots. 0394 * 0395 * @return end for iteration through all roots in DFS-forest. 0396 * @sa dfs::scan_whole_graph 0397 */ 0398 roots_iterator roots_end () const 0399 {return roots.end();} 0400 0401 /** 0402 * @brief Number of nodes reached in last DFS. 0403 * 0404 * @return number of reached nodes. 0405 * @sa dfs::scan_whole_graph 0406 */ 0407 int number_of_reached_nodes () const 0408 {return reached_nodes;} 0409 0410 0411 //----------------------------------------------------------------------- 0412 // Handler - for customization purposes 0413 //----------------------------------------------------------------------- 0414 0415 /** 0416 * @brief Handler called before the start of DFS. 0417 * 0418 * @param G %graph for which DFS was invoked. 0419 */ 0420 virtual void init_handler (graph& G) {} 0421 0422 /** 0423 * @brief Handler called at the end of DFS. 0424 * 0425 * @param G %graph for which DFS was invoked. 0426 */ 0427 virtual void end_handler (graph& G) {} 0428 0429 /** 0430 * @brief Handler called when touching %node @a n. 0431 * 0432 * @param G %graph for which DFS was invoked. 0433 * @param n actual %node. 0434 * @param f predecessor. 0435 */ 0436 virtual void entry_handler (graph& G, node& n, node& f) {} 0437 0438 /** 0439 * @brief Handler called after all the adjacent edges of @a n 0440 * have been examined. 0441 * 0442 * @param G %graph for which DFS was invoked. 0443 * @param n actual %node. 0444 * @param f predecessor. 0445 */ 0446 virtual void leave_handler (graph& G, node& n, node& f) {} 0447 0448 /** 0449 * @brief Handler called when a unused %node @a n connected to the 0450 * actual %node by @a e is found. 0451 * 0452 * @param G %graph for which DFS was invoked. 0453 * @param e %edge connecting the actual %node to the unused one. 0454 * @param n unused %node. 0455 */ 0456 virtual void before_recursive_call_handler (graph& G, edge& e, node& n) {} 0457 0458 /** 0459 * @brief Handler called after the %algorithm returns from the 0460 * subtree starting at @a n connected to the actual %node by 0461 * @a e. 0462 * 0463 * @param G %graph for which DFS was invoked. 0464 * @param e %edge connecting the actual %node to the unused one. 0465 * @param n unused %node. 0466 */ 0467 virtual void after_recursive_call_handler (graph& G, edge& e, node& n) {} 0468 0469 /** 0470 * @brief Handler called when a already marked %node @a n connected 0471 * to the actual %node by @a e is found during the search of all 0472 * adjacent edges of the actual %node. 0473 * 0474 * @param G %graph for which DFS was invoked. 0475 * @param e %edge connecting the actual %node to the old one. 0476 * @param n used %node. 0477 */ 0478 virtual void old_adj_node_handler (graph& G, edge& e, node& n) {} 0479 0480 /** 0481 * @brief Called when DFS is started with start-%node @a 0482 * n. 0483 * 0484 * This is particularly useful when DFS was invoked with the 0485 * #scan_whole_graph option. 0486 * 0487 * @param G %graph for which DFS was invoked. 0488 * @param n start-%node. 0489 */ 0490 virtual void new_start_handler (graph& G, node& n) { }; 0491 0492 private: 0493 0494 /** 0495 * @internal 0496 */ 0497 void dfs_sub (graph&, node&, node&); 0498 0499 protected: 0500 0501 //---------------------------------------------------------------------- 0502 // Data 0503 //---------------------------------------------------------------------- 0504 0505 /** 0506 * @internal 0507 */ 0508 int act_dfs_num; 0509 /** 0510 * @internal 0511 */ 0512 int act_comp_num; 0513 /** 0514 * @internal 0515 */ 0516 list<edge> tree; 0517 /** 0518 * @internal 0519 */ 0520 list<node> dfs_order; 0521 /** 0522 * @internal 0523 */ 0524 node_map<int> dfs_number; 0525 /** 0526 * @internal 0527 */ 0528 int reached_nodes; 0529 /** 0530 * @internal 0531 */ 0532 edge_map<int>* used; 0533 /** 0534 * @internal 0535 */ 0536 list<dfs_iterator> roots; 0537 0538 0539 //----------------------------------------------------------------------- 0540 // Optional 0541 //----------------------------------------------------------------------- 0542 0543 /** 0544 * @internal 0545 */ 0546 node_map<int>* comp_number; 0547 /** 0548 * @internal 0549 */ 0550 node_map<node>* preds; 0551 /** 0552 * @internal 0553 */ 0554 list<edge>* back_edges; 0555 /** 0556 * @internal 0557 */ 0558 node start; 0559 /** 0560 * @internal 0561 */ 0562 bool whole_graph; 0563 }; 0564 0565 __GTL_END_NAMESPACE 0566 0567 #endif // GTL_DFS_H 0568 0569 //-------------------------------------------------------------------------- 0570 // end of file 0571 //--------------------------------------------------------------------------
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |