// boost heap: node tree iterator helper classes // // Copyright (C) 2010 Tim Blechmann // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP #define BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP #include #include #include #include #include namespace boost { namespace heap { namespace detail { template struct identity { type& operator()(type& x) const BOOST_NOEXCEPT { return x; } const type& operator()(const type& x) const BOOST_NOEXCEPT { return x; } }; template struct dereferencer { template Node * operator()(Iterator const & it) { return static_cast(*it); } }; template struct pointer_to_reference { template const Node * operator()(Iterator const & it) { return static_cast(&*it); } }; template struct unordered_tree_iterator_storage { unordered_tree_iterator_storage(ValueCompare const & cmp) {} void push(HandleType h) { data_.push_back(h); } HandleType const & top(void) { return data_.back(); } void pop(void) { data_.pop_back(); } bool empty(void) const { return data_.empty(); } #ifdef BOOST_NO_CXX11_ALLOCATOR std::vector::other > data_; #else std::vector::template rebind_alloc > data_; #endif }; template struct ordered_tree_iterator_storage: ValueExtractor { struct compare_values_by_handle: ValueExtractor, ValueCompare { compare_values_by_handle(ValueCompare const & cmp): ValueCompare(cmp) {} bool operator()(HandleType const & lhs, HandleType const & rhs) const { ValueType const & lhs_value = ValueExtractor::operator()(lhs->value); ValueType const & rhs_value = ValueExtractor::operator()(rhs->value); return ValueCompare::operator()(lhs_value, rhs_value); } }; ordered_tree_iterator_storage(ValueCompare const & cmp): data_(compare_values_by_handle(cmp)) {} void push(HandleType h) { data_.push(h); } void pop(void) { data_.pop(); } HandleType const & top(void) { return data_.top(); } bool empty(void) const BOOST_NOEXCEPT { return data_.empty(); } std::priority_queue::other>, #else std::vector::template rebind_alloc >, #endif compare_values_by_handle> data_; }; /* tree iterator helper class * * Requirements: * Node provides child_iterator * ValueExtractor can convert Node->value to ValueType * * */ template , typename ValueExtractor = identity, typename PointerExtractor = dereferencer, bool check_null_pointer = false, bool ordered_iterator = false, typename ValueCompare = std::less > class tree_iterator: public boost::iterator_adaptor, const Node *, ValueType, boost::forward_traversal_tag >, ValueExtractor, PointerExtractor { typedef boost::iterator_adaptor, const Node *, ValueType, boost::forward_traversal_tag > adaptor_type; friend class boost::iterator_core_access; typedef typename boost::conditional< ordered_iterator, ordered_tree_iterator_storage, unordered_tree_iterator_storage >::type unvisited_node_container; public: tree_iterator(void): adaptor_type(0), unvisited_nodes(ValueCompare()) {} tree_iterator(ValueCompare const & cmp): adaptor_type(0), unvisited_nodes(cmp) {} tree_iterator(const Node * it, ValueCompare const & cmp): adaptor_type(it), unvisited_nodes(cmp) { if (it) discover_nodes(it); } /* fills the iterator from a list of possible top nodes */ template tree_iterator(NodePointerIterator begin, NodePointerIterator end, const Node * top_node, ValueCompare const & cmp): adaptor_type(0), unvisited_nodes(cmp) { BOOST_STATIC_ASSERT(ordered_iterator); if (begin == end) return; adaptor_type::base_reference() = top_node; discover_nodes(top_node); for (NodePointerIterator it = begin; it != end; ++it) { const Node * current_node = static_cast(&*it); if (current_node != top_node) unvisited_nodes.push(current_node); } } bool operator!=(tree_iterator const & rhs) const { return adaptor_type::base() != rhs.base(); } bool operator==(tree_iterator const & rhs) const { return !operator!=(rhs); } const Node * get_node() const { return adaptor_type::base_reference(); } private: void increment(void) { if (unvisited_nodes.empty()) adaptor_type::base_reference() = 0; else { const Node * next = unvisited_nodes.top(); unvisited_nodes.pop(); discover_nodes(next); adaptor_type::base_reference() = next; } } ValueType const & dereference() const { return ValueExtractor::operator()(adaptor_type::base_reference()->value); } void discover_nodes(const Node * n) { for (typename Node::const_child_iterator it = n->children.begin(); it != n->children.end(); ++it) { const Node * n = PointerExtractor::operator()(it); if (check_null_pointer && n == NULL) continue; unvisited_nodes.push(n); } } unvisited_node_container unvisited_nodes; }; template struct list_iterator_converter { typename NodeList::const_iterator operator()(const Node * node) { return NodeList::s_iterator_to(*node); } Node * operator()(typename NodeList::const_iterator it) { return const_cast(static_cast(&*it)); } }; template , typename IteratorCoverter = identity > class recursive_tree_iterator: public boost::iterator_adaptor, NodeIterator, ValueType const, boost::bidirectional_traversal_tag>, ValueExtractor, IteratorCoverter { typedef boost::iterator_adaptor, NodeIterator, ValueType const, boost::bidirectional_traversal_tag> adaptor_type; friend class boost::iterator_core_access; public: recursive_tree_iterator(void): adaptor_type(0) {} explicit recursive_tree_iterator(NodeIterator const & it): adaptor_type(it) {} void increment(void) { NodeIterator next = adaptor_type::base_reference(); const Node * n = get_node(next); if (n->children.empty()) { const Node * parent = get_node(next)->get_parent(); ++next; while (true) { if (parent == NULL || next != parent->children.end()) break; next = IteratorCoverter::operator()(parent); parent = get_node(next)->get_parent(); ++next; } } else next = n->children.begin(); adaptor_type::base_reference() = next; return; } ValueType const & dereference() const { return ValueExtractor::operator()(get_node(adaptor_type::base_reference())->value); } static const Node * get_node(NodeIterator const & it) { return static_cast(&*it); } const Node * get_node() const { return get_node(adaptor_type::base_reference()); } }; } /* namespace detail */ } /* namespace heap */ } /* namespace boost */ #endif /* BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP */