descendant_node_iterator.inl 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*******************************************************************************
  2. Tree Container Library: Generic container library to store data in tree-like structures.
  3. Copyright (c) 2006 Mitchel Haas
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the author be held liable for any damages arising from
  6. the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it freely,
  9. subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented;
  11. you must not claim that you wrote the original software.
  12. If you use this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such,
  15. and must not be misrepresented as being the original software.
  16. 3. The above copyright notice and this permission notice may not be removed
  17. or altered from any source distribution.
  18. For complete documentation on this library, see http://www.datasoftsolutions.net
  19. Email questions, comments or suggestions to mhaas@datasoftsolutions.net
  20. *******************************************************************************/
  21. // pre_order_iterator ++()
  22. template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
  23. tcl::const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator ++()
  24. {
  25. if (at_top) { // at top node?
  26. at_top = false; // iterator will be used going forward from here
  27. it = pTop_node->node_begin();
  28. } else if ( !it->empty() ) { // any children?
  29. node_stack.push(it); // yes. push current pos
  30. it = it->node_begin(); // and goto first child
  31. } else {
  32. ++it; // no children. incr to next sibling if present
  33. // while stack not empty and no next sibling
  34. while ( !node_stack.empty() && it == (node_stack.top())->node_end() ) {
  35. it = node_stack.top(); // pop parent
  36. node_stack.pop();
  37. ++it; // and see if it's got a next sibling
  38. }
  39. }
  40. return *this;
  41. }
  42. // pre_order_iterator --()
  43. template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
  44. tcl::const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator --()
  45. {
  46. typedef typename tree_category_type::const_node_iterator iterator_type;
  47. if ( it == pTop_node->node_end() ) { // at end?
  48. // yes. is top node empty?
  49. if (pTop_node->empty()) {
  50. at_top = true;
  51. return *this;
  52. }
  53. // yes. need to set up stack to state just before end
  54. rit = pTop_node->children.rbegin(); // going backwards
  55. if ( rit != pTop_node->children.rend() ) { // insure there's children
  56. if ( !(*rit)->empty() ) { // last node have children?
  57. do { // find the last child of this node
  58. ++rit; // incr reverse iter..
  59. it = iterator_type(rit.base(), (it != pTop_node->node_end() ? &(*it) : pTop_node)); // ..to convert to fwd iter correctly
  60. node_stack.push(it); // push parents on the way down
  61. rit = it->children.rbegin(); // get last child again
  62. } while ( !(*rit)->empty() ); // while last child has children
  63. }
  64. ++rit; // incr reverse iter
  65. it = iterator_type(rit.base(), (it != pTop_node->node_end() ? &(*it) : pTop_node)); // to convert to forward iter correctly
  66. }
  67. } else { // not at end.
  68. if ( it != it->parent()->node_begin() ) { // is this first sibling?
  69. --it; // no. ok to decr to next sibling
  70. if (!it->empty()) { // children present?
  71. do { // yes. get deepest last child
  72. node_stack.push(it); // first push current
  73. it = iterator_type(it->children.end(), &(*it));
  74. --it; // then go to last child
  75. } while ( !it->empty() ); // while children present
  76. }
  77. } else if (!node_stack.empty()) { // first sibling. Check for parent
  78. it = node_stack.top(); // just need to goto parent
  79. node_stack.pop();
  80. } else {
  81. if (!at_top) { // not at top node?
  82. at_top = true; // set at top (first) node
  83. } else {
  84. --it; // decrementing beyond top. this will make the iterator invalid
  85. at_top = false;
  86. }
  87. }
  88. }
  89. return *this;
  90. }
  91. // post_order_iterator constructor
  92. template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
  93. tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::const_post_order_descendant_node_iterator(const tree_type* pCalled_node, bool beg) : pTop_node(pCalled_node), at_top(false)
  94. {
  95. if (!beg) {
  96. it = pTop_node->node_end();
  97. } else {
  98. it = pTop_node->node_begin(); // goto first child
  99. if ( it != pTop_node->node_end()) {
  100. if ( !it->empty() ) { // have children of it's own?
  101. do { // goto deepest first child, while pushing parents
  102. node_stack.push(it);
  103. it = it->node_begin();
  104. } while ( !it->empty() );
  105. }
  106. } else {
  107. // no children. set top node as current
  108. at_top = true;
  109. }
  110. }
  111. }
  112. // post_order_iterator ++()
  113. template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
  114. tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator ++()
  115. {
  116. if (at_top) { // at last (called) node?
  117. // yes.
  118. at_top = false;
  119. it = pTop_node->node_end();
  120. return *this;
  121. } else if (pTop_node->empty()) {
  122. ++it; // iterator has just traversed past end
  123. return *this;
  124. }
  125. const typename tree_category_type::const_node_iterator it_end = it->parent()->node_end(); // end sibling
  126. ++it; // advance to next sibling, if present
  127. if ( it != it_end && !it->empty() ) { // next sibling present, and has children?
  128. do { // goto deepest first child while pushing parents
  129. node_stack.push(it);
  130. it = it->node_begin();
  131. } while ( !it->empty() );
  132. } else { // it is past last sibling, or it has no children
  133. // if valid it and it has no childrent, were done
  134. if ( !node_stack.empty() && it == node_stack.top()->node_end() ) {
  135. // it is past last sibling, and pushed parents exist. move back up to parent
  136. it = node_stack.top();
  137. node_stack.pop();
  138. } else if (node_stack.empty() && it == pTop_node->node_end()) {
  139. // at top node.
  140. at_top = true;
  141. }
  142. }
  143. return *this;
  144. }
  145. // post_order_iterator --()
  146. template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
  147. tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator --()
  148. {
  149. typedef typename tree_category_type::const_node_iterator iterator_type;
  150. if (at_top) { // at top node
  151. at_top = false;
  152. typename container_type::const_reverse_iterator rit = pTop_node->children.rbegin();
  153. ++rit;
  154. it = iterator_type(rit.base(), pTop_node); // goto last sibling of top node
  155. } else if ( it == pTop_node->node_end() ) { // at end?
  156. at_top = true;
  157. } else { // not at end
  158. if ( !it->empty() ) { // children present?
  159. typename container_type::const_reverse_iterator rit = it->children.rbegin();
  160. node_stack.push(it);
  161. ++rit; // push parent and go to last child
  162. it = iterator_type(rit.base(), &(*it));
  163. } else { // no children present
  164. if ( it != it->parent()->node_begin() ) { // at first sibling?
  165. --it; // no. just goto prev sibling
  166. } else { // at first sibling. work our way up until not first sibling
  167. while ( !node_stack.empty() && it == node_stack.top()->node_begin())
  168. {
  169. it = node_stack.top();
  170. node_stack.pop();
  171. }
  172. --it; // then goto prev sibling
  173. }
  174. }
  175. }
  176. return *this;
  177. }
  178. // level_order_iterator ++()
  179. template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
  180. tcl::const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator ++()
  181. {
  182. if (at_top) { // at top?
  183. // yes.
  184. at_top = false;
  185. it = pTop_node->node_begin();
  186. return *this;
  187. }
  188. const typename tree_category_type::const_node_iterator it_end = it->parent()->node_end();
  189. node_queue.push(it); // push current pos node in queue
  190. ++it; // and goto next sibling if present
  191. if ( it == it_end ) { // past last sibling? If not, we're done.
  192. while ( !node_queue.empty() ) { // yes. Insure queue not empty
  193. it = node_queue.front(); // pull pos off queue
  194. node_queue.pop(); // this should be the start pos of level just traversed
  195. if ( !it->empty() ) { // have children?
  196. it = it->node_begin(); // yes. descend to start of next level
  197. break;
  198. } else if ( node_queue.empty() ) { // no children. is queue empty?
  199. it = pTop_node->node_end(); // yes. at end
  200. return *this;
  201. }
  202. }
  203. }
  204. return *this;
  205. }