binomial_heap.hpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. // boost heap: binomial heap
  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_BINOMIAL_HEAP_HPP
  9. #define BOOST_HEAP_BINOMIAL_HEAP_HPP
  10. #include <algorithm>
  11. #include <type_traits>
  12. #include <utility>
  13. #include <boost/assert.hpp>
  14. #include <boost/heap/detail/heap_comparison.hpp>
  15. #include <boost/heap/detail/heap_node.hpp>
  16. #include <boost/heap/detail/stable_heap.hpp>
  17. #include <boost/heap/detail/tree_iterator.hpp>
  18. #include <boost/type_traits/integral_constant.hpp>
  19. #ifdef BOOST_HAS_PRAGMA_ONCE
  20. # pragma once
  21. #endif
  22. #ifndef BOOST_DOXYGEN_INVOKED
  23. # ifdef BOOST_HEAP_SANITYCHECKS
  24. # define BOOST_HEAP_ASSERT BOOST_ASSERT
  25. # else
  26. # define BOOST_HEAP_ASSERT( expression ) static_assert( true, "force semicolon" )
  27. # endif
  28. #endif
  29. namespace boost { namespace heap {
  30. namespace detail {
  31. typedef parameter::parameters< boost::parameter::optional< tag::allocator >,
  32. boost::parameter::optional< tag::compare >,
  33. boost::parameter::optional< tag::stable >,
  34. boost::parameter::optional< tag::constant_time_size >,
  35. boost::parameter::optional< tag::stability_counter_type > >
  36. binomial_heap_signature;
  37. template < typename T, typename Parspec >
  38. struct make_binomial_heap_base
  39. {
  40. static const bool constant_time_size
  41. = parameter::binding< Parspec, tag::constant_time_size, std::true_type >::type::value;
  42. typedef typename detail::make_heap_base< T, Parspec, constant_time_size >::type base_type;
  43. typedef typename detail::make_heap_base< T, Parspec, constant_time_size >::allocator_argument allocator_argument;
  44. typedef typename detail::make_heap_base< T, Parspec, constant_time_size >::compare_argument compare_argument;
  45. typedef parent_pointing_heap_node< typename base_type::internal_type > node_type;
  46. typedef typename boost::allocator_rebind< allocator_argument, node_type >::type allocator_type;
  47. struct type : base_type, allocator_type
  48. {
  49. type( compare_argument const& arg ) :
  50. base_type( arg )
  51. {}
  52. type( allocator_type const& alloc ) :
  53. allocator_type( alloc )
  54. {}
  55. type( type const& rhs ) :
  56. base_type( rhs ),
  57. allocator_type( rhs )
  58. {}
  59. type( type&& rhs ) :
  60. base_type( std::move( static_cast< base_type& >( rhs ) ) ),
  61. allocator_type( std::move( static_cast< allocator_type& >( rhs ) ) )
  62. {}
  63. type& operator=( type&& rhs )
  64. {
  65. base_type::operator=( std::move( static_cast< base_type& >( rhs ) ) );
  66. allocator_type::operator=( std::move( static_cast< allocator_type& >( rhs ) ) );
  67. return *this;
  68. }
  69. type& operator=( type const& rhs )
  70. {
  71. base_type::operator=( static_cast< base_type const& >( rhs ) );
  72. allocator_type::operator=( static_cast< allocator_type const& >( rhs ) );
  73. return *this;
  74. }
  75. };
  76. };
  77. } // namespace detail
  78. /**
  79. * \class binomial_heap
  80. * \brief binomial heap
  81. *
  82. * The template parameter T is the type to be managed by the container.
  83. * The user can specify additional options and if no options are provided default options are used.
  84. *
  85. * The container supports the following options:
  86. * - \c boost::heap::stable<>, defaults to \c stable<false>
  87. * - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
  88. * - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
  89. * - \c boost::heap::constant_time_size<>, defaults to \c constant_time_size<true>
  90. * - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
  91. *
  92. */
  93. #ifdef BOOST_DOXYGEN_INVOKED
  94. template < class T, class... Options >
  95. #else
  96. template < typename T,
  97. class A0 = boost::parameter::void_,
  98. class A1 = boost::parameter::void_,
  99. class A2 = boost::parameter::void_,
  100. class A3 = boost::parameter::void_ >
  101. #endif
  102. class binomial_heap :
  103. private detail::make_binomial_heap_base< T, typename detail::binomial_heap_signature::bind< A0, A1, A2, A3 >::type >::type
  104. {
  105. typedef typename detail::binomial_heap_signature::bind< A0, A1, A2, A3 >::type bound_args;
  106. typedef detail::make_binomial_heap_base< T, bound_args > base_maker;
  107. typedef typename base_maker::type super_t;
  108. typedef typename super_t::internal_type internal_type;
  109. typedef typename super_t::size_holder_type size_holder;
  110. typedef typename super_t::stability_counter_type stability_counter_type;
  111. typedef typename base_maker::allocator_argument allocator_argument;
  112. template < typename Heap1, typename Heap2 >
  113. friend struct heap_merge_emulate;
  114. public:
  115. static const bool constant_time_size = super_t::constant_time_size;
  116. static const bool has_ordered_iterators = true;
  117. static const bool is_mergable = true;
  118. static const bool is_stable = detail::extract_stable< bound_args >::value;
  119. static const bool has_reserve = false;
  120. private:
  121. #ifndef BOOST_DOXYGEN_INVOKED
  122. struct implementation_defined : detail::extract_allocator_types< typename base_maker::allocator_argument >
  123. {
  124. typedef T value_type;
  125. typedef typename detail::extract_allocator_types< typename base_maker::allocator_argument >::size_type size_type;
  126. typedef typename detail::extract_allocator_types< typename base_maker::allocator_argument >::reference reference;
  127. typedef typename base_maker::compare_argument value_compare;
  128. typedef typename base_maker::allocator_type allocator_type;
  129. typedef typename base_maker::node_type node;
  130. typedef typename boost::allocator_pointer< allocator_type >::type node_pointer;
  131. typedef typename boost::allocator_const_pointer< allocator_type >::type const_node_pointer;
  132. typedef detail::node_handle< node_pointer, super_t, reference > handle_type;
  133. typedef typename base_maker::node_type node_type;
  134. typedef boost::intrusive::list< detail::heap_node_base< false >, boost::intrusive::constant_time_size< true > >
  135. node_list_type;
  136. typedef typename node_list_type::iterator node_list_iterator;
  137. typedef typename node_list_type::const_iterator node_list_const_iterator;
  138. typedef detail::value_extractor< value_type, internal_type, super_t > value_extractor;
  139. typedef detail::recursive_tree_iterator< node_type,
  140. node_list_const_iterator,
  141. const value_type,
  142. value_extractor,
  143. detail::list_iterator_converter< node_type, node_list_type > >
  144. iterator;
  145. typedef iterator const_iterator;
  146. typedef detail::tree_iterator< node_type,
  147. const value_type,
  148. allocator_type,
  149. value_extractor,
  150. detail::list_iterator_converter< node_type, node_list_type >,
  151. true,
  152. true,
  153. value_compare >
  154. ordered_iterator;
  155. };
  156. #endif
  157. public:
  158. typedef T value_type;
  159. typedef typename implementation_defined::size_type size_type;
  160. typedef typename implementation_defined::difference_type difference_type;
  161. typedef typename implementation_defined::value_compare value_compare;
  162. typedef typename implementation_defined::allocator_type allocator_type;
  163. typedef typename implementation_defined::reference reference;
  164. typedef typename implementation_defined::const_reference const_reference;
  165. typedef typename implementation_defined::pointer pointer;
  166. typedef typename implementation_defined::const_pointer const_pointer;
  167. /// \copydoc boost::heap::priority_queue::iterator
  168. typedef typename implementation_defined::iterator iterator;
  169. typedef typename implementation_defined::const_iterator const_iterator;
  170. typedef typename implementation_defined::ordered_iterator ordered_iterator;
  171. typedef typename implementation_defined::handle_type handle_type;
  172. private:
  173. typedef typename implementation_defined::node_type node_type;
  174. typedef typename implementation_defined::node_list_type node_list_type;
  175. typedef typename implementation_defined::node_pointer node_pointer;
  176. typedef typename implementation_defined::const_node_pointer const_node_pointer;
  177. typedef typename implementation_defined::node_list_iterator node_list_iterator;
  178. typedef typename implementation_defined::node_list_const_iterator node_list_const_iterator;
  179. typedef typename super_t::internal_compare internal_compare;
  180. public:
  181. /// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
  182. explicit binomial_heap( value_compare const& cmp = value_compare() ) :
  183. super_t( cmp ),
  184. top_element( 0 )
  185. {}
  186. /// \copydoc boost::heap::priority_queue::priority_queue(allocator_type const &)
  187. explicit binomial_heap( allocator_type const& alloc ) :
  188. super_t( alloc ),
  189. top_element( 0 )
  190. {}
  191. /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
  192. binomial_heap( binomial_heap const& rhs ) :
  193. super_t( rhs ),
  194. top_element( 0 )
  195. {
  196. if ( rhs.empty() )
  197. return;
  198. clone_forest( rhs );
  199. size_holder::set_size( rhs.get_size() );
  200. }
  201. /// \copydoc boost::heap::priority_queue::operator=(priority_queue const &)
  202. binomial_heap& operator=( binomial_heap const& rhs )
  203. {
  204. clear();
  205. size_holder::set_size( rhs.get_size() );
  206. static_cast< super_t& >( *this ) = rhs;
  207. if ( rhs.empty() )
  208. top_element = nullptr;
  209. else
  210. clone_forest( rhs );
  211. return *this;
  212. }
  213. /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
  214. binomial_heap( binomial_heap&& rhs ) :
  215. super_t( std::move( rhs ) ),
  216. top_element( rhs.top_element )
  217. {
  218. trees.splice( trees.begin(), rhs.trees );
  219. rhs.top_element = nullptr;
  220. }
  221. /// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
  222. binomial_heap& operator=( binomial_heap&& rhs )
  223. {
  224. clear();
  225. super_t::operator=( std::move( rhs ) );
  226. trees.splice( trees.begin(), rhs.trees );
  227. top_element = rhs.top_element;
  228. rhs.top_element = nullptr;
  229. return *this;
  230. }
  231. ~binomial_heap( void )
  232. {
  233. clear();
  234. }
  235. /// \copydoc boost::heap::priority_queue::empty
  236. bool empty( void ) const
  237. {
  238. return top_element == nullptr;
  239. }
  240. /**
  241. * \b Effects: Returns the number of elements contained in the priority queue.
  242. *
  243. * \b Complexity: Constant, if configured with constant_time_size<true>, otherwise linear.
  244. *
  245. * */
  246. size_type size( void ) const
  247. {
  248. if ( constant_time_size )
  249. return size_holder::get_size();
  250. if ( empty() )
  251. return 0;
  252. else
  253. return detail::count_list_nodes< node_type, node_list_type >( trees );
  254. }
  255. /// \copydoc boost::heap::priority_queue::max_size
  256. size_type max_size( void ) const
  257. {
  258. const allocator_type& alloc = *this;
  259. return boost::allocator_max_size( alloc );
  260. }
  261. /// \copydoc boost::heap::priority_queue::clear
  262. void clear( void )
  263. {
  264. typedef detail::node_disposer< node_type, typename node_list_type::value_type, allocator_type > disposer;
  265. trees.clear_and_dispose( disposer( *this ) );
  266. size_holder::set_size( 0 );
  267. top_element = nullptr;
  268. }
  269. /// \copydoc boost::heap::priority_queue::get_allocator
  270. allocator_type get_allocator( void ) const
  271. {
  272. return *this;
  273. }
  274. /// \copydoc boost::heap::priority_queue::swap
  275. void swap( binomial_heap& rhs )
  276. {
  277. super_t::swap( rhs );
  278. std::swap( top_element, rhs.top_element );
  279. trees.swap( rhs.trees );
  280. }
  281. /// \copydoc boost::heap::priority_queue::top
  282. const_reference top( void ) const
  283. {
  284. BOOST_ASSERT( !empty() );
  285. return super_t::get_value( top_element->value );
  286. }
  287. /**
  288. * \b Effects: Adds a new element to the priority queue. Returns handle to element
  289. *
  290. * \b Complexity: Logarithmic.
  291. *
  292. * */
  293. handle_type push( value_type const& v )
  294. {
  295. allocator_type& alloc = *this;
  296. node_pointer n = alloc.allocate( 1 );
  297. new ( n ) node_type( super_t::make_node( v ) );
  298. insert_node( trees.begin(), n );
  299. if ( !top_element || super_t::operator()( top_element->value, n->value ) )
  300. top_element = n;
  301. size_holder::increment();
  302. sanity_check();
  303. return handle_type( n );
  304. }
  305. /**
  306. * \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place. Returns
  307. * handle to element.
  308. *
  309. * \b Complexity: Logarithmic.
  310. *
  311. * */
  312. template < class... Args >
  313. handle_type emplace( Args&&... args )
  314. {
  315. allocator_type& alloc = *this;
  316. node_pointer n = alloc.allocate( 1 );
  317. new ( n ) node_type( super_t::make_node( std::forward< Args >( args )... ) );
  318. insert_node( trees.begin(), n );
  319. if ( !top_element || super_t::operator()( top_element->value, n->value ) )
  320. top_element = n;
  321. size_holder::increment();
  322. sanity_check();
  323. return handle_type( n );
  324. }
  325. /**
  326. * \b Effects: Removes the top element from the priority queue.
  327. *
  328. * \b Complexity: Logarithmic.
  329. *
  330. * */
  331. void pop( void )
  332. {
  333. BOOST_ASSERT( !empty() );
  334. node_pointer element = top_element;
  335. trees.erase( node_list_type::s_iterator_to( *element ) );
  336. size_holder::decrement();
  337. if ( element->child_count() ) {
  338. size_type sz = ( 1 << element->child_count() ) - 1;
  339. binomial_heap children( value_comp(), element->children, sz );
  340. if ( trees.empty() ) {
  341. stability_counter_type stability_count = super_t::get_stability_count();
  342. size_t size = constant_time_size ? size_holder::get_size() : 0;
  343. swap( children );
  344. super_t::set_stability_count( stability_count );
  345. if ( constant_time_size )
  346. size_holder::set_size( size );
  347. } else
  348. merge_and_clear_nodes( children );
  349. }
  350. if ( trees.empty() )
  351. top_element = nullptr;
  352. else
  353. update_top_element();
  354. element->~node_type();
  355. allocator_type& alloc = *this;
  356. alloc.deallocate( element, 1 );
  357. sanity_check();
  358. }
  359. /**
  360. * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
  361. *
  362. * \b Complexity: Logarithmic.
  363. *
  364. * */
  365. void update( handle_type handle, const_reference v )
  366. {
  367. if ( super_t::operator()( super_t::get_value( handle.node_->value ), v ) )
  368. increase( handle, v );
  369. else
  370. decrease( handle, v );
  371. }
  372. /**
  373. * \b Effects: Updates the heap after the element handled by \c handle has been changed.
  374. *
  375. * \b Complexity: Logarithmic.
  376. *
  377. * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
  378. * */
  379. void update( handle_type handle )
  380. {
  381. node_pointer this_node = handle.node_;
  382. if ( this_node->parent ) {
  383. if ( super_t::operator()( super_t::get_value( this_node->parent->value ),
  384. super_t::get_value( this_node->value ) ) )
  385. increase( handle );
  386. else
  387. decrease( handle );
  388. } else
  389. decrease( handle );
  390. }
  391. /**
  392. * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
  393. *
  394. * \b Complexity: Logarithmic.
  395. *
  396. * \b Note: The new value is expected to be greater than the current one
  397. * */
  398. void increase( handle_type handle, const_reference v )
  399. {
  400. handle.node_->value = super_t::make_node( v );
  401. increase( handle );
  402. }
  403. /**
  404. * \b Effects: Updates the heap after the element handled by \c handle has been changed.
  405. *
  406. * \b Complexity: Logarithmic.
  407. *
  408. * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
  409. * */
  410. void increase( handle_type handle )
  411. {
  412. node_pointer n = handle.node_;
  413. siftup( n, *this );
  414. update_top_element();
  415. sanity_check();
  416. }
  417. /**
  418. * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
  419. *
  420. * \b Complexity: Logarithmic.
  421. *
  422. * \b Note: The new value is expected to be less than the current one
  423. * */
  424. void decrease( handle_type handle, const_reference v )
  425. {
  426. handle.node_->value = super_t::make_node( v );
  427. decrease( handle );
  428. }
  429. /**
  430. * \b Effects: Updates the heap after the element handled by \c handle has been changed.
  431. *
  432. * \b Complexity: Logarithmic.
  433. *
  434. * \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has
  435. * been updated, the behavior of the data structure is undefined!
  436. * */
  437. void decrease( handle_type handle )
  438. {
  439. node_pointer n = handle.node_;
  440. siftdown( n );
  441. update_top_element();
  442. }
  443. /**
  444. * \b Effects: Merge with priority queue rhs.
  445. *
  446. * \b Complexity: Logarithmic.
  447. *
  448. * */
  449. void merge( binomial_heap& rhs )
  450. {
  451. if ( rhs.empty() )
  452. return;
  453. if ( empty() ) {
  454. swap( rhs );
  455. return;
  456. }
  457. size_type new_size = size_holder::get_size() + rhs.get_size();
  458. merge_and_clear_nodes( rhs );
  459. size_holder::set_size( new_size );
  460. rhs.set_size( 0 );
  461. rhs.top_element = nullptr;
  462. super_t::set_stability_count( ( std::max )( super_t::get_stability_count(), rhs.get_stability_count() ) );
  463. rhs.set_stability_count( 0 );
  464. }
  465. public:
  466. /// \copydoc boost::heap::priority_queue::begin
  467. iterator begin( void ) const
  468. {
  469. return iterator( trees.begin() );
  470. }
  471. /// \copydoc boost::heap::priority_queue::end
  472. iterator end( void ) const
  473. {
  474. return iterator( trees.end() );
  475. }
  476. /// \copydoc boost::heap::fibonacci_heap::ordered_begin
  477. ordered_iterator ordered_begin( void ) const
  478. {
  479. return ordered_iterator( trees.begin(), trees.end(), top_element, super_t::value_comp() );
  480. }
  481. /// \copydoc boost::heap::fibonacci_heap::ordered_end
  482. ordered_iterator ordered_end( void ) const
  483. {
  484. return ordered_iterator( nullptr, super_t::value_comp() );
  485. }
  486. /**
  487. * \b Effects: Removes the element handled by \c handle from the priority_queue.
  488. *
  489. * \b Complexity: Logarithmic.
  490. * */
  491. void erase( handle_type handle )
  492. {
  493. node_pointer n = handle.node_;
  494. siftup( n, force_inf() );
  495. top_element = n;
  496. pop();
  497. }
  498. /// \copydoc boost::heap::d_ary_heap_mutable::s_handle_from_iterator
  499. static handle_type s_handle_from_iterator( iterator const& it )
  500. {
  501. node_type* ptr = const_cast< node_type* >( it.get_node() );
  502. return handle_type( ptr );
  503. }
  504. /// \copydoc boost::heap::priority_queue::value_comp
  505. value_compare const& value_comp( void ) const
  506. {
  507. return super_t::value_comp();
  508. }
  509. /// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
  510. template < typename HeapType >
  511. bool operator<( HeapType const& rhs ) const
  512. {
  513. return detail::heap_compare( *this, rhs );
  514. }
  515. /// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
  516. template < typename HeapType >
  517. bool operator>( HeapType const& rhs ) const
  518. {
  519. return detail::heap_compare( rhs, *this );
  520. }
  521. /// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
  522. template < typename HeapType >
  523. bool operator>=( HeapType const& rhs ) const
  524. {
  525. return !operator<( rhs );
  526. }
  527. /// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
  528. template < typename HeapType >
  529. bool operator<=( HeapType const& rhs ) const
  530. {
  531. return !operator>( rhs );
  532. }
  533. /// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
  534. template < typename HeapType >
  535. bool operator==( HeapType const& rhs ) const
  536. {
  537. return detail::heap_equality( *this, rhs );
  538. }
  539. /// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
  540. template < typename HeapType >
  541. bool operator!=( HeapType const& rhs ) const
  542. {
  543. return !( *this == rhs );
  544. }
  545. private:
  546. #if !defined( BOOST_DOXYGEN_INVOKED )
  547. void merge_and_clear_nodes( binomial_heap& rhs )
  548. {
  549. BOOST_HEAP_ASSERT( !empty() );
  550. BOOST_HEAP_ASSERT( !rhs.empty() );
  551. node_list_iterator this_iterator = trees.begin();
  552. node_pointer carry_node = nullptr;
  553. while ( !rhs.trees.empty() ) {
  554. node_pointer rhs_node = static_cast< node_pointer >( &rhs.trees.front() );
  555. size_type rhs_degree = rhs_node->child_count();
  556. if ( super_t::operator()( top_element->value, rhs_node->value ) )
  557. top_element = rhs_node;
  558. try_again:
  559. node_pointer this_node = static_cast< node_pointer >( &*this_iterator );
  560. size_type this_degree = this_node->child_count();
  561. sorted_by_degree();
  562. rhs.sorted_by_degree();
  563. if ( this_degree == rhs_degree ) {
  564. if ( carry_node ) {
  565. if ( carry_node->child_count() < this_degree ) {
  566. trees.insert( this_iterator, *carry_node );
  567. carry_node = nullptr;
  568. } else {
  569. rhs.trees.pop_front();
  570. carry_node = merge_trees( carry_node, rhs_node );
  571. }
  572. ++this_iterator;
  573. } else {
  574. this_iterator = trees.erase( this_iterator );
  575. rhs.trees.pop_front();
  576. carry_node = merge_trees( this_node, rhs_node );
  577. }
  578. if ( this_iterator == trees.end() )
  579. break;
  580. else
  581. continue;
  582. }
  583. if ( this_degree < rhs_degree ) {
  584. if ( carry_node ) {
  585. if ( carry_node->child_count() < this_degree ) {
  586. trees.insert( this_iterator, *carry_node );
  587. carry_node = nullptr;
  588. ++this_iterator;
  589. } else if ( carry_node->child_count() == rhs_degree ) {
  590. rhs.trees.pop_front();
  591. carry_node = merge_trees( carry_node, rhs_node );
  592. continue;
  593. } else {
  594. this_iterator = trees.erase( this_iterator );
  595. carry_node = merge_trees( this_node, carry_node );
  596. }
  597. goto try_again;
  598. } else {
  599. ++this_iterator;
  600. if ( this_iterator == trees.end() )
  601. break;
  602. goto try_again;
  603. }
  604. if ( this_iterator == trees.end() )
  605. break;
  606. else
  607. continue;
  608. }
  609. if ( this_degree > rhs_degree ) {
  610. rhs.trees.pop_front();
  611. if ( carry_node ) {
  612. if ( carry_node->child_count() < rhs_degree ) {
  613. trees.insert( this_iterator, *carry_node );
  614. trees.insert( this_iterator, *rhs_node );
  615. carry_node = nullptr;
  616. } else
  617. carry_node = merge_trees( rhs_node, carry_node );
  618. } else
  619. trees.insert( this_iterator, *rhs_node );
  620. }
  621. }
  622. if ( !rhs.trees.empty() ) {
  623. if ( carry_node ) {
  624. node_list_iterator rhs_it = rhs.trees.begin();
  625. while ( static_cast< node_pointer >( &*rhs_it )->child_count() < carry_node->child_count() )
  626. ++rhs_it;
  627. rhs.insert_node( rhs_it, carry_node );
  628. rhs.increment();
  629. sorted_by_degree();
  630. rhs.sorted_by_degree();
  631. if ( trees.empty() ) {
  632. trees.splice( trees.end(), rhs.trees, rhs.trees.begin(), rhs.trees.end() );
  633. update_top_element();
  634. } else
  635. merge_and_clear_nodes( rhs );
  636. } else
  637. trees.splice( trees.end(), rhs.trees, rhs.trees.begin(), rhs.trees.end() );
  638. return;
  639. }
  640. if ( carry_node )
  641. insert_node( this_iterator, carry_node );
  642. }
  643. void clone_forest( binomial_heap const& rhs )
  644. {
  645. BOOST_HEAP_ASSERT( trees.empty() );
  646. typedef typename node_type::template node_cloner< allocator_type > node_cloner;
  647. trees.clone_from( rhs.trees, node_cloner( *this, nullptr ), detail::nop_disposer() );
  648. update_top_element();
  649. }
  650. struct force_inf
  651. {
  652. template < typename X >
  653. bool operator()( X const&, X const& ) const
  654. {
  655. return false;
  656. }
  657. };
  658. template < typename Compare >
  659. void siftup( node_pointer n, Compare const& cmp )
  660. {
  661. while ( n->parent ) {
  662. node_pointer parent = n->parent;
  663. node_pointer grand_parent = parent->parent;
  664. if ( cmp( n->value, parent->value ) )
  665. return;
  666. n->remove_from_parent();
  667. n->swap_children( parent );
  668. n->update_children();
  669. parent->update_children();
  670. if ( grand_parent ) {
  671. parent->remove_from_parent();
  672. grand_parent->add_child( n );
  673. } else {
  674. node_list_iterator it = trees.erase( node_list_type::s_iterator_to( *parent ) );
  675. trees.insert( it, *n );
  676. }
  677. n->add_child( parent );
  678. }
  679. }
  680. void siftdown( node_pointer n )
  681. {
  682. while ( n->child_count() ) {
  683. node_pointer max_child
  684. = detail::find_max_child< node_list_type, node_type, internal_compare >( n->children,
  685. super_t::get_internal_cmp() );
  686. if ( super_t::operator()( max_child->value, n->value ) )
  687. return;
  688. max_child->remove_from_parent();
  689. n->swap_children( max_child );
  690. n->update_children();
  691. max_child->update_children();
  692. node_pointer parent = n->parent;
  693. if ( parent ) {
  694. n->remove_from_parent();
  695. max_child->add_child( n );
  696. parent->add_child( max_child );
  697. } else {
  698. node_list_iterator position = trees.erase( node_list_type::s_iterator_to( *n ) );
  699. max_child->add_child( n );
  700. trees.insert( position, *max_child );
  701. }
  702. }
  703. }
  704. void insert_node( node_list_iterator it, node_pointer n )
  705. {
  706. if ( it != trees.end() )
  707. BOOST_HEAP_ASSERT( static_cast< node_pointer >( &*it )->child_count() >= n->child_count() );
  708. while ( true ) {
  709. BOOST_HEAP_ASSERT( !n->is_linked() );
  710. if ( it == trees.end() )
  711. break;
  712. node_pointer this_node = static_cast< node_pointer >( &*it );
  713. size_type this_degree = this_node->child_count();
  714. size_type n_degree = n->child_count();
  715. if ( this_degree == n_degree ) {
  716. BOOST_HEAP_ASSERT( it->is_linked() );
  717. it = trees.erase( it );
  718. n = merge_trees( n, this_node );
  719. } else
  720. break;
  721. }
  722. trees.insert( it, *n );
  723. }
  724. // private constructor, just used in pop()
  725. explicit binomial_heap( value_compare const& cmp, node_list_type& child_list, size_type size ) :
  726. super_t( cmp )
  727. {
  728. size_holder::set_size( size );
  729. if ( size )
  730. top_element = static_cast< node_pointer >( &*child_list.begin() ); // not correct, but we will reset it later
  731. else
  732. top_element = nullptr;
  733. for ( node_list_iterator it = child_list.begin(); it != child_list.end(); ++it ) {
  734. node_pointer n = static_cast< node_pointer >( &*it );
  735. n->parent = nullptr;
  736. }
  737. trees.splice( trees.end(), child_list, child_list.begin(), child_list.end() );
  738. trees.sort( detail::cmp_by_degree< node_type >() );
  739. }
  740. node_pointer merge_trees( node_pointer node1, node_pointer node2 )
  741. {
  742. BOOST_HEAP_ASSERT( node1->child_count() == node2->child_count() );
  743. if ( super_t::operator()( node1->value, node2->value ) )
  744. std::swap( node1, node2 );
  745. if ( node2->parent )
  746. node2->remove_from_parent();
  747. node1->add_child( node2 );
  748. return node1;
  749. }
  750. void update_top_element( void )
  751. {
  752. top_element
  753. = detail::find_max_child< node_list_type, node_type, internal_compare >( trees,
  754. super_t::get_internal_cmp() );
  755. }
  756. void sorted_by_degree( void ) const
  757. {
  758. # ifdef BOOST_HEAP_SANITYCHECKS
  759. int degree = -1;
  760. for ( node_list_const_iterator it = trees.begin(); it != trees.end(); ++it ) {
  761. const_node_pointer n = static_cast< const_node_pointer >( &*it );
  762. BOOST_HEAP_ASSERT( int( n->child_count() ) > degree );
  763. degree = n->child_count();
  764. BOOST_HEAP_ASSERT( ( detail::is_heap< node_type, super_t >( n, *this ) ) );
  765. size_type child_nodes = detail::count_nodes< node_type >( n );
  766. BOOST_HEAP_ASSERT( child_nodes
  767. == size_type( 1 << static_cast< const_node_pointer >( &*it )->child_count() ) );
  768. }
  769. # endif
  770. }
  771. void sanity_check( void )
  772. {
  773. # ifdef BOOST_HEAP_SANITYCHECKS
  774. sorted_by_degree();
  775. if ( !empty() ) {
  776. node_pointer found_top
  777. = detail::find_max_child< node_list_type, node_type, internal_compare >( trees,
  778. super_t::get_internal_cmp() );
  779. BOOST_HEAP_ASSERT( top_element == found_top );
  780. }
  781. if ( constant_time_size ) {
  782. size_t counted = detail::count_list_nodes< node_type, node_list_type >( trees );
  783. size_t stored = size_holder::get_size();
  784. BOOST_HEAP_ASSERT( counted == stored );
  785. }
  786. # endif
  787. }
  788. node_pointer top_element;
  789. node_list_type trees;
  790. #endif // BOOST_DOXYGEN_INVOKED
  791. };
  792. }} // namespace boost::heap
  793. #undef BOOST_HEAP_ASSERT
  794. #endif /* BOOST_HEAP_D_ARY_HEAP_HPP */