tree_iterator.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. // boost heap: node tree iterator helper classes
  2. //
  3. // Copyright (C) 2010 Tim Blechmann
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP
  9. #define BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP
  10. #include <functional>
  11. #include <vector>
  12. #include <boost/iterator/iterator_adaptor.hpp>
  13. #include <queue>
  14. namespace boost {
  15. namespace heap {
  16. namespace detail {
  17. template<typename type>
  18. struct identity
  19. {
  20. type& operator()(type& x) const BOOST_NOEXCEPT
  21. { return x; }
  22. const type& operator()(const type& x) const BOOST_NOEXCEPT
  23. { return x; }
  24. };
  25. template<typename Node>
  26. struct dereferencer
  27. {
  28. template <typename Iterator>
  29. Node * operator()(Iterator const & it)
  30. {
  31. return static_cast<Node *>(*it);
  32. }
  33. };
  34. template<typename Node>
  35. struct pointer_to_reference
  36. {
  37. template <typename Iterator>
  38. const Node * operator()(Iterator const & it)
  39. {
  40. return static_cast<const Node *>(&*it);
  41. }
  42. };
  43. template <typename HandleType,
  44. typename Alloc,
  45. typename ValueCompare
  46. >
  47. struct unordered_tree_iterator_storage
  48. {
  49. unordered_tree_iterator_storage(ValueCompare const & cmp)
  50. {}
  51. void push(HandleType h)
  52. {
  53. data_.push_back(h);
  54. }
  55. HandleType const & top(void)
  56. {
  57. return data_.back();
  58. }
  59. void pop(void)
  60. {
  61. data_.pop_back();
  62. }
  63. bool empty(void) const
  64. {
  65. return data_.empty();
  66. }
  67. std::vector<HandleType, typename Alloc::template rebind<HandleType>::other > data_;
  68. };
  69. template <typename ValueType,
  70. typename HandleType,
  71. typename Alloc,
  72. typename ValueCompare,
  73. typename ValueExtractor
  74. >
  75. struct ordered_tree_iterator_storage:
  76. ValueExtractor
  77. {
  78. struct compare_values_by_handle:
  79. ValueExtractor,
  80. ValueCompare
  81. {
  82. compare_values_by_handle(ValueCompare const & cmp):
  83. ValueCompare(cmp)
  84. {}
  85. bool operator()(HandleType const & lhs, HandleType const & rhs) const
  86. {
  87. ValueType const & lhs_value = ValueExtractor::operator()(lhs->value);
  88. ValueType const & rhs_value = ValueExtractor::operator()(rhs->value);
  89. return ValueCompare::operator()(lhs_value, rhs_value);
  90. }
  91. };
  92. ordered_tree_iterator_storage(ValueCompare const & cmp):
  93. data_(compare_values_by_handle(cmp))
  94. {}
  95. void push(HandleType h)
  96. {
  97. data_.push(h);
  98. }
  99. void pop(void)
  100. {
  101. data_.pop();
  102. }
  103. HandleType const & top(void)
  104. {
  105. return data_.top();
  106. }
  107. bool empty(void) const BOOST_NOEXCEPT
  108. {
  109. return data_.empty();
  110. }
  111. std::priority_queue<HandleType,
  112. std::vector<HandleType, typename Alloc::template rebind<HandleType>::other>,
  113. compare_values_by_handle> data_;
  114. };
  115. /* tree iterator helper class
  116. *
  117. * Requirements:
  118. * Node provides child_iterator
  119. * ValueExtractor can convert Node->value to ValueType
  120. *
  121. * */
  122. template <typename Node,
  123. typename ValueType,
  124. typename Alloc = std::allocator<Node>,
  125. typename ValueExtractor = identity<typename Node::value_type>,
  126. typename PointerExtractor = dereferencer<Node>,
  127. bool check_null_pointer = false,
  128. bool ordered_iterator = false,
  129. typename ValueCompare = std::less<ValueType>
  130. >
  131. class tree_iterator:
  132. public boost::iterator_adaptor<tree_iterator<Node,
  133. ValueType,
  134. Alloc,
  135. ValueExtractor,
  136. PointerExtractor,
  137. check_null_pointer,
  138. ordered_iterator,
  139. ValueCompare
  140. >,
  141. const Node *,
  142. ValueType,
  143. boost::forward_traversal_tag
  144. >,
  145. ValueExtractor,
  146. PointerExtractor
  147. {
  148. typedef boost::iterator_adaptor<tree_iterator<Node,
  149. ValueType,
  150. Alloc,
  151. ValueExtractor,
  152. PointerExtractor,
  153. check_null_pointer,
  154. ordered_iterator,
  155. ValueCompare
  156. >,
  157. const Node *,
  158. ValueType,
  159. boost::forward_traversal_tag
  160. > adaptor_type;
  161. friend class boost::iterator_core_access;
  162. typedef typename boost::mpl::if_c< ordered_iterator,
  163. ordered_tree_iterator_storage<ValueType, const Node*, Alloc, ValueCompare, ValueExtractor>,
  164. unordered_tree_iterator_storage<const Node*, Alloc, ValueCompare>
  165. >::type
  166. unvisited_node_container;
  167. public:
  168. tree_iterator(void):
  169. adaptor_type(0), unvisited_nodes(ValueCompare())
  170. {}
  171. tree_iterator(ValueCompare const & cmp):
  172. adaptor_type(0), unvisited_nodes(cmp)
  173. {}
  174. tree_iterator(const Node * it, ValueCompare const & cmp):
  175. adaptor_type(it), unvisited_nodes(cmp)
  176. {
  177. if (it)
  178. discover_nodes(it);
  179. }
  180. /* fills the iterator from a list of possible top nodes */
  181. template <typename NodePointerIterator>
  182. tree_iterator(NodePointerIterator begin, NodePointerIterator end, const Node * top_node, ValueCompare const & cmp):
  183. adaptor_type(0), unvisited_nodes(cmp)
  184. {
  185. BOOST_STATIC_ASSERT(ordered_iterator);
  186. if (begin == end)
  187. return;
  188. adaptor_type::base_reference() = top_node;
  189. discover_nodes(top_node);
  190. for (NodePointerIterator it = begin; it != end; ++it) {
  191. const Node * current_node = static_cast<const Node*>(&*it);
  192. if (current_node != top_node)
  193. unvisited_nodes.push(current_node);
  194. }
  195. }
  196. bool operator!=(tree_iterator const & rhs) const
  197. {
  198. return adaptor_type::base() != rhs.base();
  199. }
  200. bool operator==(tree_iterator const & rhs) const
  201. {
  202. return !operator!=(rhs);
  203. }
  204. const Node * get_node() const
  205. {
  206. return adaptor_type::base_reference();
  207. }
  208. private:
  209. void increment(void)
  210. {
  211. if (unvisited_nodes.empty())
  212. adaptor_type::base_reference() = 0;
  213. else {
  214. const Node * next = unvisited_nodes.top();
  215. unvisited_nodes.pop();
  216. discover_nodes(next);
  217. adaptor_type::base_reference() = next;
  218. }
  219. }
  220. ValueType const & dereference() const
  221. {
  222. return ValueExtractor::operator()(adaptor_type::base_reference()->value);
  223. }
  224. void discover_nodes(const Node * n)
  225. {
  226. for (typename Node::const_child_iterator it = n->children.begin(); it != n->children.end(); ++it) {
  227. const Node * n = PointerExtractor::operator()(it);
  228. if (check_null_pointer && n == NULL)
  229. continue;
  230. unvisited_nodes.push(n);
  231. }
  232. }
  233. unvisited_node_container unvisited_nodes;
  234. };
  235. template <typename Node, typename NodeList>
  236. struct list_iterator_converter
  237. {
  238. typename NodeList::const_iterator operator()(const Node * node)
  239. {
  240. return NodeList::s_iterator_to(*node);
  241. }
  242. Node * operator()(typename NodeList::const_iterator it)
  243. {
  244. return const_cast<Node*>(static_cast<const Node*>(&*it));
  245. }
  246. };
  247. template <typename Node,
  248. typename NodeIterator,
  249. typename ValueType,
  250. typename ValueExtractor = identity<typename Node::value_type>,
  251. typename IteratorCoverter = identity<NodeIterator>
  252. >
  253. class recursive_tree_iterator:
  254. public boost::iterator_adaptor<recursive_tree_iterator<Node,
  255. NodeIterator,
  256. ValueType,
  257. ValueExtractor,
  258. IteratorCoverter
  259. >,
  260. NodeIterator,
  261. ValueType const,
  262. boost::bidirectional_traversal_tag>,
  263. ValueExtractor, IteratorCoverter
  264. {
  265. typedef boost::iterator_adaptor<recursive_tree_iterator<Node,
  266. NodeIterator,
  267. ValueType,
  268. ValueExtractor,
  269. IteratorCoverter
  270. >,
  271. NodeIterator,
  272. ValueType const,
  273. boost::bidirectional_traversal_tag> adaptor_type;
  274. friend class boost::iterator_core_access;
  275. public:
  276. recursive_tree_iterator(void):
  277. adaptor_type(0)
  278. {}
  279. explicit recursive_tree_iterator(NodeIterator const & it):
  280. adaptor_type(it)
  281. {}
  282. void increment(void)
  283. {
  284. NodeIterator next = adaptor_type::base_reference();
  285. const Node * n = get_node(next);
  286. if (n->children.empty()) {
  287. const Node * parent = get_node(next)->get_parent();
  288. ++next;
  289. while (true) {
  290. if (parent == NULL || next != parent->children.end())
  291. break;
  292. next = IteratorCoverter::operator()(parent);
  293. parent = get_node(next)->get_parent();
  294. ++next;
  295. }
  296. } else
  297. next = n->children.begin();
  298. adaptor_type::base_reference() = next;
  299. return;
  300. }
  301. ValueType const & dereference() const
  302. {
  303. return ValueExtractor::operator()(get_node(adaptor_type::base_reference())->value);
  304. }
  305. static const Node * get_node(NodeIterator const & it)
  306. {
  307. return static_cast<const Node *>(&*it);
  308. }
  309. const Node * get_node() const
  310. {
  311. return get_node(adaptor_type::base_reference());
  312. }
  313. };
  314. } /* namespace detail */
  315. } /* namespace heap */
  316. } /* namespace boost */
  317. #endif /* BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP */