| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- // boost heap: heap node 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_HEAP_NODE_HPP
- #define BOOST_HEAP_DETAIL_HEAP_NODE_HPP
- #include <boost/assert.hpp>
- #include <boost/core/allocator_access.hpp>
- #include <boost/intrusive/list.hpp>
- #include <boost/static_assert.hpp>
- #include <boost/type_traits/conditional.hpp>
- #ifdef BOOST_HEAP_SANITYCHECKS
- # define BOOST_HEAP_ASSERT BOOST_ASSERT
- #else
- # define BOOST_HEAP_ASSERT( expression ) static_assert( true, "force semicolon" )
- #endif
- namespace boost { namespace heap { namespace detail {
- namespace bi = boost::intrusive;
- template < bool auto_unlink = false >
- struct heap_node_base :
- bi::list_base_hook<
- typename std::conditional< auto_unlink, bi::link_mode< bi::auto_unlink >, bi::link_mode< bi::safe_link > >::type >
- {};
- typedef bi::list< heap_node_base< false > > heap_node_list;
- struct nop_disposer
- {
- template < typename T >
- void operator()( T* )
- {
- BOOST_HEAP_ASSERT( false );
- }
- };
- template < typename Node, typename HeapBase >
- bool is_heap( const Node* n, typename HeapBase::value_compare const& cmp )
- {
- for ( typename Node::const_child_iterator it = n->children.begin(); it != n->children.end(); ++it ) {
- Node const& this_node = static_cast< Node const& >( *it );
- const Node* child = static_cast< const Node* >( &this_node );
- if ( cmp( HeapBase::get_value( n->value ), HeapBase::get_value( child->value ) )
- || !is_heap< Node, HeapBase >( child, cmp ) )
- return false;
- }
- return true;
- }
- template < typename Node >
- std::size_t count_nodes( const Node* n );
- template < typename Node, typename List >
- std::size_t count_list_nodes( List const& node_list )
- {
- std::size_t ret = 0;
- for ( typename List::const_iterator it = node_list.begin(); it != node_list.end(); ++it ) {
- const Node* child = static_cast< const Node* >( &*it );
- ret += count_nodes< Node >( child );
- }
- return ret;
- }
- template < typename Node >
- std::size_t count_nodes( const Node* n )
- {
- return 1 + count_list_nodes< Node, typename Node::child_list >( n->children );
- }
- template < class Node >
- void destroy_node( Node& node )
- {
- node.~Node();
- }
- /* node cloner
- *
- * Requires `Clone Constructor':
- * template <typename Alloc>
- * Node::Node(Node const &, Alloc &)
- *
- * template <typename Alloc>
- * Node::Node(Node const &, Alloc &, Node * parent)
- *
- * */
- template < typename Node, typename NodeBase, typename Alloc >
- struct node_cloner
- {
- node_cloner( Alloc& allocator ) :
- allocator( allocator )
- {}
- Node* operator()( NodeBase const& node )
- {
- Node* ret = allocator.allocate( 1 );
- new ( ret ) Node( static_cast< Node const& >( node ), allocator );
- return ret;
- }
- Node* operator()( NodeBase const& node, Node* parent )
- {
- Node* ret = allocator.allocate( 1 );
- new ( ret ) Node( static_cast< Node const& >( node ), allocator, parent );
- return ret;
- }
- private:
- Alloc& allocator;
- };
- /* node disposer
- *
- * Requirements:
- * Node::clear_subtree(Alloc &) clears the subtree via allocator
- *
- * */
- template < typename Node, typename NodeBase, typename Alloc >
- struct node_disposer
- {
- typedef typename boost::allocator_pointer< Alloc >::type node_pointer;
- node_disposer( Alloc& alloc ) :
- alloc_( alloc )
- {}
- void operator()( NodeBase* base )
- {
- node_pointer n = static_cast< node_pointer >( base );
- n->clear_subtree( alloc_ );
- boost::heap::detail::destroy_node( *n );
- alloc_.deallocate( n, 1 );
- }
- Alloc& alloc_;
- };
- template < typename ValueType, bool constant_time_child_size = true >
- struct heap_node : heap_node_base< !constant_time_child_size >
- {
- typedef heap_node_base< !constant_time_child_size > node_base;
- public:
- typedef ValueType value_type;
- typedef bi::list< node_base, bi::constant_time_size< constant_time_child_size > > child_list;
- typedef typename child_list::iterator child_iterator;
- typedef typename child_list::const_iterator const_child_iterator;
- typedef typename child_list::size_type size_type;
- heap_node( ValueType const& v ) :
- value( v )
- {}
- template < class... Args >
- heap_node( Args&&... args ) :
- value( std::forward< Args >( args )... )
- {}
- /* protected: */
- heap_node( heap_node const& rhs ) :
- value( rhs.value )
- {
- /* we don't copy the child list, but clone it later */
- }
- public:
- template < typename Alloc >
- heap_node( heap_node const& rhs, Alloc& allocator ) :
- value( rhs.value )
- {
- children.clone_from( rhs.children, node_cloner< heap_node, node_base, Alloc >( allocator ), nop_disposer() );
- }
- size_type child_count( void ) const
- {
- BOOST_STATIC_ASSERT( constant_time_child_size );
- return children.size();
- }
- void add_child( heap_node* n )
- {
- children.push_back( *n );
- }
- template < typename Alloc >
- void clear_subtree( Alloc& alloc )
- {
- children.clear_and_dispose( node_disposer< heap_node, node_base, Alloc >( alloc ) );
- }
- void swap_children( heap_node* rhs )
- {
- children.swap( rhs->children );
- }
- ValueType value;
- child_list children;
- };
- template < typename value_type >
- struct parent_pointing_heap_node : heap_node< value_type >
- {
- typedef heap_node< value_type > super_t;
- parent_pointing_heap_node( value_type const& v ) :
- super_t( v ),
- parent( nullptr )
- {}
- template < class... Args >
- parent_pointing_heap_node( Args&&... args ) :
- super_t( std::forward< Args >( args )... ),
- parent( nullptr )
- {}
- template < typename Alloc >
- struct node_cloner
- {
- node_cloner( Alloc& allocator, parent_pointing_heap_node* parent ) :
- allocator( allocator ),
- parent_( parent )
- {}
- parent_pointing_heap_node* operator()( typename super_t::node_base const& node )
- {
- parent_pointing_heap_node* ret = allocator.allocate( 1 );
- new ( ret )
- parent_pointing_heap_node( static_cast< parent_pointing_heap_node const& >( node ), allocator, parent_ );
- return ret;
- }
- private:
- Alloc& allocator;
- parent_pointing_heap_node* parent_;
- };
- template < typename Alloc >
- parent_pointing_heap_node( parent_pointing_heap_node const& rhs,
- Alloc& allocator,
- parent_pointing_heap_node* parent ) :
- super_t( static_cast< super_t const& >( rhs ) ),
- parent( parent )
- {
- super_t::children.clone_from( rhs.children, node_cloner< Alloc >( allocator, this ), nop_disposer() );
- }
- void update_children( void )
- {
- typedef heap_node_list::iterator node_list_iterator;
- for ( node_list_iterator it = super_t::children.begin(); it != super_t::children.end(); ++it ) {
- parent_pointing_heap_node* child = static_cast< parent_pointing_heap_node* >( &*it );
- child->parent = this;
- }
- }
- void remove_from_parent( void )
- {
- BOOST_HEAP_ASSERT( parent );
- parent->children.erase( heap_node_list::s_iterator_to( *this ) );
- parent = nullptr;
- }
- void add_child( parent_pointing_heap_node* n )
- {
- BOOST_HEAP_ASSERT( n->parent == nullptr );
- n->parent = this;
- super_t::add_child( n );
- }
- parent_pointing_heap_node* get_parent( void )
- {
- return parent;
- }
- const parent_pointing_heap_node* get_parent( void ) const
- {
- return parent;
- }
- parent_pointing_heap_node* parent;
- };
- template < typename value_type >
- struct marked_heap_node : parent_pointing_heap_node< value_type >
- {
- typedef parent_pointing_heap_node< value_type > super_t;
- marked_heap_node( value_type const& v ) :
- super_t( v ),
- mark( false )
- {}
- template < class... Args >
- marked_heap_node( Args&&... args ) :
- super_t( std::forward< Args >( args )... ),
- mark( false )
- {}
- marked_heap_node* get_parent( void )
- {
- return static_cast< marked_heap_node* >( super_t::parent );
- }
- const marked_heap_node* get_parent( void ) const
- {
- return static_cast< marked_heap_node* >( super_t::parent );
- }
- bool mark;
- };
- template < typename Node >
- struct cmp_by_degree
- {
- template < typename NodeBase >
- bool operator()( NodeBase const& left, NodeBase const& right )
- {
- return static_cast< const Node* >( &left )->child_count() < static_cast< const Node* >( &right )->child_count();
- }
- };
- template < typename List, typename Node, typename Cmp >
- Node* find_max_child( List const& list, Cmp const& cmp )
- {
- BOOST_HEAP_ASSERT( !list.empty() );
- const Node* ret = static_cast< const Node* >( &list.front() );
- for ( typename List::const_iterator it = list.begin(); it != list.end(); ++it ) {
- const Node* current = static_cast< const Node* >( &*it );
- if ( cmp( ret->value, current->value ) )
- ret = current;
- }
- return const_cast< Node* >( ret );
- }
- }}} // namespace boost::heap::detail
- #undef BOOST_HEAP_ASSERT
- #endif /* BOOST_HEAP_DETAIL_HEAP_NODE_HPP */
|