1 // boost heap: node tree iterator helper classes
3 // Copyright (C) 2010 Tim Blechmann
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)
9 #ifndef BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP
10 #define BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP
15 #include <boost/core/allocator_access.hpp>
16 #include <boost/iterator/iterator_adaptor.hpp>
17 #include <boost/type_traits/conditional.hpp>
25 template<typename type>
28 type& operator()(type& x) const BOOST_NOEXCEPT
31 const type& operator()(const type& x) const BOOST_NOEXCEPT
35 template<typename Node>
38 template <typename Iterator>
39 Node * operator()(Iterator const & it)
41 return static_cast<Node *>(*it);
45 template<typename Node>
46 struct pointer_to_reference
48 template <typename Iterator>
49 const Node * operator()(Iterator const & it)
51 return static_cast<const Node *>(&*it);
56 template <typename HandleType,
60 struct unordered_tree_iterator_storage
62 unordered_tree_iterator_storage(ValueCompare const & cmp)
65 void push(HandleType h)
70 HandleType const & top(void)
80 bool empty(void) const
85 std::vector<HandleType, typename boost::allocator_rebind<Alloc, HandleType>::type> data_;
88 template <typename ValueType,
91 typename ValueCompare,
92 typename ValueExtractor
94 struct ordered_tree_iterator_storage:
97 struct compare_values_by_handle:
101 compare_values_by_handle(ValueCompare const & cmp):
105 bool operator()(HandleType const & lhs, HandleType const & rhs) const
107 ValueType const & lhs_value = ValueExtractor::operator()(lhs->value);
108 ValueType const & rhs_value = ValueExtractor::operator()(rhs->value);
109 return ValueCompare::operator()(lhs_value, rhs_value);
113 ordered_tree_iterator_storage(ValueCompare const & cmp):
114 data_(compare_values_by_handle(cmp))
117 void push(HandleType h)
127 HandleType const & top(void)
132 bool empty(void) const BOOST_NOEXCEPT
134 return data_.empty();
137 std::priority_queue<HandleType,
138 std::vector<HandleType, typename boost::allocator_rebind<Alloc, HandleType>::type>,
139 compare_values_by_handle> data_;
143 /* tree iterator helper class
146 * Node provides child_iterator
147 * ValueExtractor can convert Node->value to ValueType
150 template <typename Node,
152 typename Alloc = std::allocator<Node>,
153 typename ValueExtractor = identity<typename Node::value_type>,
154 typename PointerExtractor = dereferencer<Node>,
155 bool check_null_pointer = false,
156 bool ordered_iterator = false,
157 typename ValueCompare = std::less<ValueType>
160 public boost::iterator_adaptor<tree_iterator<Node,
171 boost::forward_traversal_tag
176 typedef boost::iterator_adaptor<tree_iterator<Node,
187 boost::forward_traversal_tag
190 friend class boost::iterator_core_access;
192 typedef typename boost::conditional< ordered_iterator,
193 ordered_tree_iterator_storage<ValueType, const Node*, Alloc, ValueCompare, ValueExtractor>,
194 unordered_tree_iterator_storage<const Node*, Alloc, ValueCompare>
196 unvisited_node_container;
200 adaptor_type(0), unvisited_nodes(ValueCompare())
203 tree_iterator(ValueCompare const & cmp):
204 adaptor_type(0), unvisited_nodes(cmp)
207 tree_iterator(const Node * it, ValueCompare const & cmp):
208 adaptor_type(it), unvisited_nodes(cmp)
214 /* fills the iterator from a list of possible top nodes */
215 template <typename NodePointerIterator>
216 tree_iterator(NodePointerIterator begin, NodePointerIterator end, const Node * top_node, ValueCompare const & cmp):
217 adaptor_type(0), unvisited_nodes(cmp)
219 BOOST_STATIC_ASSERT(ordered_iterator);
223 adaptor_type::base_reference() = top_node;
224 discover_nodes(top_node);
226 for (NodePointerIterator it = begin; it != end; ++it) {
227 const Node * current_node = static_cast<const Node*>(&*it);
228 if (current_node != top_node)
229 unvisited_nodes.push(current_node);
233 bool operator!=(tree_iterator const & rhs) const
235 return adaptor_type::base() != rhs.base();
238 bool operator==(tree_iterator const & rhs) const
240 return !operator!=(rhs);
243 const Node * get_node() const
245 return adaptor_type::base_reference();
251 if (unvisited_nodes.empty())
252 adaptor_type::base_reference() = 0;
254 const Node * next = unvisited_nodes.top();
255 unvisited_nodes.pop();
256 discover_nodes(next);
257 adaptor_type::base_reference() = next;
261 ValueType const & dereference() const
263 return ValueExtractor::operator()(adaptor_type::base_reference()->value);
266 void discover_nodes(const Node * n)
268 for (typename Node::const_child_iterator it = n->children.begin(); it != n->children.end(); ++it) {
269 const Node * n = PointerExtractor::operator()(it);
270 if (check_null_pointer && n == NULL)
272 unvisited_nodes.push(n);
276 unvisited_node_container unvisited_nodes;
279 template <typename Node, typename NodeList>
280 struct list_iterator_converter
282 typename NodeList::const_iterator operator()(const Node * node)
284 return NodeList::s_iterator_to(*node);
287 Node * operator()(typename NodeList::const_iterator it)
289 return const_cast<Node*>(static_cast<const Node*>(&*it));
293 template <typename Node,
294 typename NodeIterator,
296 typename ValueExtractor = identity<typename Node::value_type>,
297 typename IteratorCoverter = identity<NodeIterator>
299 class recursive_tree_iterator:
300 public boost::iterator_adaptor<recursive_tree_iterator<Node,
308 boost::bidirectional_traversal_tag>,
309 ValueExtractor, IteratorCoverter
311 typedef boost::iterator_adaptor<recursive_tree_iterator<Node,
319 boost::bidirectional_traversal_tag> adaptor_type;
321 friend class boost::iterator_core_access;
325 recursive_tree_iterator(void):
329 explicit recursive_tree_iterator(NodeIterator const & it):
335 NodeIterator next = adaptor_type::base_reference();
337 const Node * n = get_node(next);
338 if (n->children.empty()) {
339 const Node * parent = get_node(next)->get_parent();
344 if (parent == NULL || next != parent->children.end())
347 next = IteratorCoverter::operator()(parent);
348 parent = get_node(next)->get_parent();
352 next = n->children.begin();
354 adaptor_type::base_reference() = next;
358 ValueType const & dereference() const
360 return ValueExtractor::operator()(get_node(adaptor_type::base_reference())->value);
363 static const Node * get_node(NodeIterator const & it)
365 return static_cast<const Node *>(&*it);
368 const Node * get_node() const
370 return get_node(adaptor_type::base_reference());
375 } /* namespace detail */
376 } /* namespace heap */
377 } /* namespace boost */
379 #endif /* BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP */