heap_node.hpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. // boost heap: heap node 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_HEAP_NODE_HPP
  9. #define BOOST_HEAP_DETAIL_HEAP_NODE_HPP
  10. #include <boost/assert.hpp>
  11. #include <boost/core/allocator_access.hpp>
  12. #include <boost/intrusive/list.hpp>
  13. #include <boost/static_assert.hpp>
  14. #include <boost/type_traits/conditional.hpp>
  15. #ifdef BOOST_HEAP_SANITYCHECKS
  16. # define BOOST_HEAP_ASSERT BOOST_ASSERT
  17. #else
  18. # define BOOST_HEAP_ASSERT( expression ) static_assert( true, "force semicolon" )
  19. #endif
  20. namespace boost { namespace heap { namespace detail {
  21. namespace bi = boost::intrusive;
  22. template < bool auto_unlink = false >
  23. struct heap_node_base :
  24. bi::list_base_hook<
  25. typename std::conditional< auto_unlink, bi::link_mode< bi::auto_unlink >, bi::link_mode< bi::safe_link > >::type >
  26. {};
  27. typedef bi::list< heap_node_base< false > > heap_node_list;
  28. struct nop_disposer
  29. {
  30. template < typename T >
  31. void operator()( T* )
  32. {
  33. BOOST_HEAP_ASSERT( false );
  34. }
  35. };
  36. template < typename Node, typename HeapBase >
  37. bool is_heap( const Node* n, typename HeapBase::value_compare const& cmp )
  38. {
  39. for ( typename Node::const_child_iterator it = n->children.begin(); it != n->children.end(); ++it ) {
  40. Node const& this_node = static_cast< Node const& >( *it );
  41. const Node* child = static_cast< const Node* >( &this_node );
  42. if ( cmp( HeapBase::get_value( n->value ), HeapBase::get_value( child->value ) )
  43. || !is_heap< Node, HeapBase >( child, cmp ) )
  44. return false;
  45. }
  46. return true;
  47. }
  48. template < typename Node >
  49. std::size_t count_nodes( const Node* n );
  50. template < typename Node, typename List >
  51. std::size_t count_list_nodes( List const& node_list )
  52. {
  53. std::size_t ret = 0;
  54. for ( typename List::const_iterator it = node_list.begin(); it != node_list.end(); ++it ) {
  55. const Node* child = static_cast< const Node* >( &*it );
  56. ret += count_nodes< Node >( child );
  57. }
  58. return ret;
  59. }
  60. template < typename Node >
  61. std::size_t count_nodes( const Node* n )
  62. {
  63. return 1 + count_list_nodes< Node, typename Node::child_list >( n->children );
  64. }
  65. template < class Node >
  66. void destroy_node( Node& node )
  67. {
  68. node.~Node();
  69. }
  70. /* node cloner
  71. *
  72. * Requires `Clone Constructor':
  73. * template <typename Alloc>
  74. * Node::Node(Node const &, Alloc &)
  75. *
  76. * template <typename Alloc>
  77. * Node::Node(Node const &, Alloc &, Node * parent)
  78. *
  79. * */
  80. template < typename Node, typename NodeBase, typename Alloc >
  81. struct node_cloner
  82. {
  83. node_cloner( Alloc& allocator ) :
  84. allocator( allocator )
  85. {}
  86. Node* operator()( NodeBase const& node )
  87. {
  88. Node* ret = allocator.allocate( 1 );
  89. new ( ret ) Node( static_cast< Node const& >( node ), allocator );
  90. return ret;
  91. }
  92. Node* operator()( NodeBase const& node, Node* parent )
  93. {
  94. Node* ret = allocator.allocate( 1 );
  95. new ( ret ) Node( static_cast< Node const& >( node ), allocator, parent );
  96. return ret;
  97. }
  98. private:
  99. Alloc& allocator;
  100. };
  101. /* node disposer
  102. *
  103. * Requirements:
  104. * Node::clear_subtree(Alloc &) clears the subtree via allocator
  105. *
  106. * */
  107. template < typename Node, typename NodeBase, typename Alloc >
  108. struct node_disposer
  109. {
  110. typedef typename boost::allocator_pointer< Alloc >::type node_pointer;
  111. node_disposer( Alloc& alloc ) :
  112. alloc_( alloc )
  113. {}
  114. void operator()( NodeBase* base )
  115. {
  116. node_pointer n = static_cast< node_pointer >( base );
  117. n->clear_subtree( alloc_ );
  118. boost::heap::detail::destroy_node( *n );
  119. alloc_.deallocate( n, 1 );
  120. }
  121. Alloc& alloc_;
  122. };
  123. template < typename ValueType, bool constant_time_child_size = true >
  124. struct heap_node : heap_node_base< !constant_time_child_size >
  125. {
  126. typedef heap_node_base< !constant_time_child_size > node_base;
  127. public:
  128. typedef ValueType value_type;
  129. typedef bi::list< node_base, bi::constant_time_size< constant_time_child_size > > child_list;
  130. typedef typename child_list::iterator child_iterator;
  131. typedef typename child_list::const_iterator const_child_iterator;
  132. typedef typename child_list::size_type size_type;
  133. heap_node( ValueType const& v ) :
  134. value( v )
  135. {}
  136. template < class... Args >
  137. heap_node( Args&&... args ) :
  138. value( std::forward< Args >( args )... )
  139. {}
  140. /* protected: */
  141. heap_node( heap_node const& rhs ) :
  142. value( rhs.value )
  143. {
  144. /* we don't copy the child list, but clone it later */
  145. }
  146. public:
  147. template < typename Alloc >
  148. heap_node( heap_node const& rhs, Alloc& allocator ) :
  149. value( rhs.value )
  150. {
  151. children.clone_from( rhs.children, node_cloner< heap_node, node_base, Alloc >( allocator ), nop_disposer() );
  152. }
  153. size_type child_count( void ) const
  154. {
  155. BOOST_STATIC_ASSERT( constant_time_child_size );
  156. return children.size();
  157. }
  158. void add_child( heap_node* n )
  159. {
  160. children.push_back( *n );
  161. }
  162. template < typename Alloc >
  163. void clear_subtree( Alloc& alloc )
  164. {
  165. children.clear_and_dispose( node_disposer< heap_node, node_base, Alloc >( alloc ) );
  166. }
  167. void swap_children( heap_node* rhs )
  168. {
  169. children.swap( rhs->children );
  170. }
  171. ValueType value;
  172. child_list children;
  173. };
  174. template < typename value_type >
  175. struct parent_pointing_heap_node : heap_node< value_type >
  176. {
  177. typedef heap_node< value_type > super_t;
  178. parent_pointing_heap_node( value_type const& v ) :
  179. super_t( v ),
  180. parent( nullptr )
  181. {}
  182. template < class... Args >
  183. parent_pointing_heap_node( Args&&... args ) :
  184. super_t( std::forward< Args >( args )... ),
  185. parent( nullptr )
  186. {}
  187. template < typename Alloc >
  188. struct node_cloner
  189. {
  190. node_cloner( Alloc& allocator, parent_pointing_heap_node* parent ) :
  191. allocator( allocator ),
  192. parent_( parent )
  193. {}
  194. parent_pointing_heap_node* operator()( typename super_t::node_base const& node )
  195. {
  196. parent_pointing_heap_node* ret = allocator.allocate( 1 );
  197. new ( ret )
  198. parent_pointing_heap_node( static_cast< parent_pointing_heap_node const& >( node ), allocator, parent_ );
  199. return ret;
  200. }
  201. private:
  202. Alloc& allocator;
  203. parent_pointing_heap_node* parent_;
  204. };
  205. template < typename Alloc >
  206. parent_pointing_heap_node( parent_pointing_heap_node const& rhs,
  207. Alloc& allocator,
  208. parent_pointing_heap_node* parent ) :
  209. super_t( static_cast< super_t const& >( rhs ) ),
  210. parent( parent )
  211. {
  212. super_t::children.clone_from( rhs.children, node_cloner< Alloc >( allocator, this ), nop_disposer() );
  213. }
  214. void update_children( void )
  215. {
  216. typedef heap_node_list::iterator node_list_iterator;
  217. for ( node_list_iterator it = super_t::children.begin(); it != super_t::children.end(); ++it ) {
  218. parent_pointing_heap_node* child = static_cast< parent_pointing_heap_node* >( &*it );
  219. child->parent = this;
  220. }
  221. }
  222. void remove_from_parent( void )
  223. {
  224. BOOST_HEAP_ASSERT( parent );
  225. parent->children.erase( heap_node_list::s_iterator_to( *this ) );
  226. parent = nullptr;
  227. }
  228. void add_child( parent_pointing_heap_node* n )
  229. {
  230. BOOST_HEAP_ASSERT( n->parent == nullptr );
  231. n->parent = this;
  232. super_t::add_child( n );
  233. }
  234. parent_pointing_heap_node* get_parent( void )
  235. {
  236. return parent;
  237. }
  238. const parent_pointing_heap_node* get_parent( void ) const
  239. {
  240. return parent;
  241. }
  242. parent_pointing_heap_node* parent;
  243. };
  244. template < typename value_type >
  245. struct marked_heap_node : parent_pointing_heap_node< value_type >
  246. {
  247. typedef parent_pointing_heap_node< value_type > super_t;
  248. marked_heap_node( value_type const& v ) :
  249. super_t( v ),
  250. mark( false )
  251. {}
  252. template < class... Args >
  253. marked_heap_node( Args&&... args ) :
  254. super_t( std::forward< Args >( args )... ),
  255. mark( false )
  256. {}
  257. marked_heap_node* get_parent( void )
  258. {
  259. return static_cast< marked_heap_node* >( super_t::parent );
  260. }
  261. const marked_heap_node* get_parent( void ) const
  262. {
  263. return static_cast< marked_heap_node* >( super_t::parent );
  264. }
  265. bool mark;
  266. };
  267. template < typename Node >
  268. struct cmp_by_degree
  269. {
  270. template < typename NodeBase >
  271. bool operator()( NodeBase const& left, NodeBase const& right )
  272. {
  273. return static_cast< const Node* >( &left )->child_count() < static_cast< const Node* >( &right )->child_count();
  274. }
  275. };
  276. template < typename List, typename Node, typename Cmp >
  277. Node* find_max_child( List const& list, Cmp const& cmp )
  278. {
  279. BOOST_HEAP_ASSERT( !list.empty() );
  280. const Node* ret = static_cast< const Node* >( &list.front() );
  281. for ( typename List::const_iterator it = list.begin(); it != list.end(); ++it ) {
  282. const Node* current = static_cast< const Node* >( &*it );
  283. if ( cmp( ret->value, current->value ) )
  284. ret = current;
  285. }
  286. return const_cast< Node* >( ret );
  287. }
  288. }}} // namespace boost::heap::detail
  289. #undef BOOST_HEAP_ASSERT
  290. #endif /* BOOST_HEAP_DETAIL_HEAP_NODE_HPP */