pairing_heap.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. // boost heap: pairing 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_PAIRING_HEAP_HPP
  9. #define BOOST_HEAP_PAIRING_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/heap/policies.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. pairing_heap_signature;
  37. template < typename T, typename Parspec >
  38. struct make_pairing_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 heap_node< typename base_type::internal_type, false > 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& arg ) :
  53. allocator_type( arg )
  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< const allocator_type& >( rhs ) );
  73. return *this;
  74. }
  75. };
  76. };
  77. } // namespace detail
  78. /**
  79. * \class pairing_heap
  80. * \brief pairing heap
  81. *
  82. * Pairing heaps are self-adjusting binary heaps. Although design and implementation are rather simple,
  83. * the complexity analysis is yet unsolved. For details, consult:
  84. *
  85. * Pettie, Seth (2005), "Towards a final analysis of pairing heaps",
  86. * Proc. 46th Annual IEEE Symposium on Foundations of Computer Science, pp. 174-183
  87. *
  88. * The template parameter T is the type to be managed by the container.
  89. * The user can specify additional options and if no options are provided default options are used.
  90. *
  91. * The container supports the following options:
  92. * - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
  93. * - \c boost::heap::stable<>, defaults to \c stable<false>
  94. * - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
  95. * - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
  96. * - \c boost::heap::constant_time_size<>, defaults to \c constant_time_size<true>
  97. *
  98. *
  99. */
  100. #ifdef BOOST_DOXYGEN_INVOKED
  101. template < class T, class... Options >
  102. #else
  103. template < typename T,
  104. class A0 = boost::parameter::void_,
  105. class A1 = boost::parameter::void_,
  106. class A2 = boost::parameter::void_,
  107. class A3 = boost::parameter::void_,
  108. class A4 = boost::parameter::void_ >
  109. #endif
  110. class pairing_heap :
  111. private detail::make_pairing_heap_base< T, typename detail::pairing_heap_signature::bind< A0, A1, A2, A3, A4 >::type >::type
  112. {
  113. typedef typename detail::pairing_heap_signature::bind< A0, A1, A2, A3, A4 >::type bound_args;
  114. typedef detail::make_pairing_heap_base< T, bound_args > base_maker;
  115. typedef typename base_maker::type super_t;
  116. typedef typename super_t::internal_type internal_type;
  117. typedef typename super_t::size_holder_type size_holder;
  118. typedef typename base_maker::allocator_argument allocator_argument;
  119. private:
  120. template < typename Heap1, typename Heap2 >
  121. friend struct heap_merge_emulate;
  122. #ifndef BOOST_DOXYGEN_INVOKED
  123. struct implementation_defined : detail::extract_allocator_types< typename base_maker::allocator_argument >
  124. {
  125. typedef T value_type;
  126. typedef typename detail::extract_allocator_types< typename base_maker::allocator_argument >::size_type size_type;
  127. typedef typename detail::extract_allocator_types< typename base_maker::allocator_argument >::reference reference;
  128. typedef typename base_maker::compare_argument value_compare;
  129. typedef typename base_maker::allocator_type allocator_type;
  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::heap_node_list node_list_type;
  133. typedef typename node_list_type::iterator node_list_iterator;
  134. typedef typename node_list_type::const_iterator node_list_const_iterator;
  135. typedef typename base_maker::node_type node;
  136. typedef detail::value_extractor< value_type, internal_type, super_t > value_extractor;
  137. typedef typename super_t::internal_compare internal_compare;
  138. typedef detail::node_handle< node_pointer, super_t, reference > handle_type;
  139. typedef detail::tree_iterator< node,
  140. const value_type,
  141. allocator_type,
  142. value_extractor,
  143. detail::pointer_to_reference< node >,
  144. false,
  145. false,
  146. value_compare >
  147. iterator;
  148. typedef iterator const_iterator;
  149. typedef detail::tree_iterator< node,
  150. const value_type,
  151. allocator_type,
  152. value_extractor,
  153. detail::pointer_to_reference< node >,
  154. false,
  155. true,
  156. value_compare >
  157. ordered_iterator;
  158. };
  159. typedef typename implementation_defined::node node;
  160. typedef typename implementation_defined::node_pointer node_pointer;
  161. typedef typename implementation_defined::node_list_type node_list_type;
  162. typedef typename implementation_defined::node_list_iterator node_list_iterator;
  163. typedef typename implementation_defined::node_list_const_iterator node_list_const_iterator;
  164. typedef typename implementation_defined::internal_compare internal_compare;
  165. typedef boost::intrusive::list< detail::heap_node_base< true >, boost::intrusive::constant_time_size< false > >
  166. node_child_list;
  167. #endif
  168. public:
  169. typedef T value_type;
  170. typedef typename implementation_defined::size_type size_type;
  171. typedef typename implementation_defined::difference_type difference_type;
  172. typedef typename implementation_defined::value_compare value_compare;
  173. typedef typename implementation_defined::allocator_type allocator_type;
  174. typedef typename implementation_defined::reference reference;
  175. typedef typename implementation_defined::const_reference const_reference;
  176. typedef typename implementation_defined::pointer pointer;
  177. typedef typename implementation_defined::const_pointer const_pointer;
  178. /// \copydoc boost::heap::priority_queue::iterator
  179. typedef typename implementation_defined::iterator iterator;
  180. typedef typename implementation_defined::const_iterator const_iterator;
  181. typedef typename implementation_defined::ordered_iterator ordered_iterator;
  182. typedef typename implementation_defined::handle_type handle_type;
  183. static const bool constant_time_size = super_t::constant_time_size;
  184. static const bool has_ordered_iterators = true;
  185. static const bool is_mergable = true;
  186. static const bool is_stable = detail::extract_stable< bound_args >::value;
  187. static const bool has_reserve = false;
  188. /// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
  189. explicit pairing_heap( value_compare const& cmp = value_compare() ) :
  190. super_t( cmp ),
  191. root( nullptr )
  192. {}
  193. /// \copydoc boost::heap::priority_queue::priority_queue(allocator_type const &)
  194. explicit pairing_heap( allocator_type const& alloc ) :
  195. super_t( alloc ),
  196. root( nullptr )
  197. {}
  198. /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
  199. pairing_heap( pairing_heap const& rhs ) :
  200. super_t( rhs ),
  201. root( nullptr )
  202. {
  203. if ( rhs.empty() )
  204. return;
  205. clone_tree( rhs );
  206. size_holder::set_size( rhs.get_size() );
  207. }
  208. /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
  209. pairing_heap( pairing_heap&& rhs ) :
  210. super_t( std::move( rhs ) ),
  211. root( rhs.root )
  212. {
  213. rhs.root = nullptr;
  214. }
  215. /// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
  216. pairing_heap& operator=( pairing_heap&& rhs )
  217. {
  218. super_t::operator=( std::move( rhs ) );
  219. root = rhs.root;
  220. rhs.root = nullptr;
  221. return *this;
  222. }
  223. /// \copydoc boost::heap::priority_queue::operator=(priority_queue const & rhs)
  224. pairing_heap& operator=( pairing_heap const& rhs )
  225. {
  226. clear();
  227. size_holder::set_size( rhs.get_size() );
  228. static_cast< super_t& >( *this ) = rhs;
  229. clone_tree( rhs );
  230. return *this;
  231. }
  232. ~pairing_heap( void )
  233. {
  234. while ( !empty() )
  235. pop();
  236. }
  237. /// \copydoc boost::heap::priority_queue::empty
  238. bool empty( void ) const
  239. {
  240. return root == nullptr;
  241. }
  242. /// \copydoc boost::heap::binomial_heap::size
  243. size_type size( void ) const
  244. {
  245. if ( constant_time_size )
  246. return size_holder::get_size();
  247. if ( root == nullptr )
  248. return 0;
  249. else
  250. return detail::count_nodes( root );
  251. }
  252. /// \copydoc boost::heap::priority_queue::max_size
  253. size_type max_size( void ) const
  254. {
  255. const allocator_type& alloc = *this;
  256. return boost::allocator_max_size( alloc );
  257. }
  258. /// \copydoc boost::heap::priority_queue::clear
  259. void clear( void )
  260. {
  261. if ( empty() )
  262. return;
  263. root->template clear_subtree< allocator_type >( *this );
  264. root->~node();
  265. allocator_type& alloc = *this;
  266. alloc.deallocate( root, 1 );
  267. root = nullptr;
  268. size_holder::set_size( 0 );
  269. }
  270. /// \copydoc boost::heap::priority_queue::get_allocator
  271. allocator_type get_allocator( void ) const
  272. {
  273. return *this;
  274. }
  275. /// \copydoc boost::heap::priority_queue::swap
  276. void swap( pairing_heap& rhs )
  277. {
  278. super_t::swap( rhs );
  279. std::swap( root, rhs.root );
  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( root->value );
  286. }
  287. /**
  288. * \b Effects: Adds a new element to the priority queue. Returns handle to element
  289. *
  290. * \cond
  291. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  292. * \endcond
  293. *
  294. * \b Complexity: 2**2*log(log(N)) (amortized).
  295. *
  296. * */
  297. handle_type push( value_type const& v )
  298. {
  299. size_holder::increment();
  300. allocator_type& alloc = *this;
  301. node_pointer n = alloc.allocate( 1 );
  302. new ( n ) node( super_t::make_node( v ) );
  303. merge_node( n );
  304. return handle_type( n );
  305. }
  306. /**
  307. * \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place. Returns
  308. * handle to element.
  309. *
  310. * \cond
  311. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  312. * \endcond
  313. *
  314. * \b Complexity: 2**2*log(log(N)) (amortized).
  315. *
  316. * */
  317. template < class... Args >
  318. handle_type emplace( Args&&... args )
  319. {
  320. size_holder::increment();
  321. allocator_type& alloc = *this;
  322. node_pointer n = alloc.allocate( 1 );
  323. new ( n ) node( super_t::make_node( std::forward< Args >( args )... ) );
  324. merge_node( n );
  325. return handle_type( n );
  326. }
  327. /**
  328. * \b Effects: Removes the top element from the priority queue.
  329. *
  330. * \b Complexity: Logarithmic (amortized).
  331. *
  332. * */
  333. void pop( void )
  334. {
  335. BOOST_ASSERT( !empty() );
  336. erase( handle_type( root ) );
  337. }
  338. /**
  339. * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
  340. *
  341. * \cond
  342. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  343. * \endcond
  344. *
  345. * \b Complexity: 2**2*log(log(N)) (amortized).
  346. *
  347. * */
  348. void update( handle_type handle, const_reference v )
  349. {
  350. handle.node_->value = super_t::make_node( v );
  351. update( handle );
  352. }
  353. /**
  354. * \b Effects: Updates the heap after the element handled by \c handle has been changed.
  355. *
  356. * \cond
  357. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  358. * \endcond
  359. *
  360. * \b Complexity: 2**2*log(log(N)) (amortized).
  361. *
  362. * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
  363. * */
  364. void update( handle_type handle )
  365. {
  366. node_pointer n = handle.node_;
  367. n->unlink();
  368. if ( !n->children.empty() )
  369. n = merge_nodes( n, merge_node_list( n->children ) );
  370. if ( n != root )
  371. merge_node( n );
  372. }
  373. /**
  374. * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
  375. *
  376. * \cond
  377. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  378. * \endcond
  379. *
  380. * \b Complexity: 2**2*log(log(N)) (amortized).
  381. *
  382. * \b Note: The new value is expected to be greater than the current one
  383. * */
  384. void increase( handle_type handle, const_reference v )
  385. {
  386. update( handle, v );
  387. }
  388. /**
  389. * \b Effects: Updates the heap after the element handled by \c handle has been changed.
  390. *
  391. * \cond
  392. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  393. * \endcond
  394. *
  395. * \b Complexity: 2**2*log(log(N)) (amortized).
  396. *
  397. * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
  398. * */
  399. void increase( handle_type handle )
  400. {
  401. update( handle );
  402. }
  403. /**
  404. * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
  405. *
  406. * \cond
  407. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  408. * \endcond
  409. *
  410. * \b Complexity: 2**2*log(log(N)) (amortized).
  411. *
  412. * \b Note: The new value is expected to be less than the current one
  413. * */
  414. void decrease( handle_type handle, const_reference v )
  415. {
  416. update( handle, v );
  417. }
  418. /**
  419. * \b Effects: Updates the heap after the element handled by \c handle has been changed.
  420. *
  421. * \cond
  422. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  423. * \endcond
  424. *
  425. * \b Complexity: 2**2*log(log(N)) (amortized).
  426. *
  427. * \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has
  428. * been updated, the behavior of the data structure is undefined!
  429. * */
  430. void decrease( handle_type handle )
  431. {
  432. update( handle );
  433. }
  434. /**
  435. * \b Effects: Removes the element handled by \c handle from the priority_queue.
  436. *
  437. * \cond
  438. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  439. * \endcond
  440. *
  441. * \b Complexity: 2**2*log(log(N)) (amortized).
  442. * */
  443. void erase( handle_type handle )
  444. {
  445. node_pointer n = handle.node_;
  446. if ( n != root ) {
  447. n->unlink();
  448. if ( !n->children.empty() )
  449. merge_node( merge_node_list( n->children ) );
  450. } else {
  451. if ( !n->children.empty() )
  452. root = merge_node_list( n->children );
  453. else
  454. root = nullptr;
  455. }
  456. size_holder::decrement();
  457. n->~node();
  458. allocator_type& alloc = *this;
  459. alloc.deallocate( n, 1 );
  460. }
  461. /// \copydoc boost::heap::priority_queue::begin
  462. iterator begin( void ) const
  463. {
  464. return iterator( root, super_t::value_comp() );
  465. }
  466. /// \copydoc boost::heap::priority_queue::end
  467. iterator end( void ) const
  468. {
  469. return iterator( super_t::value_comp() );
  470. }
  471. /// \copydoc boost::heap::fibonacci_heap::ordered_begin
  472. ordered_iterator ordered_begin( void ) const
  473. {
  474. return ordered_iterator( root, super_t::value_comp() );
  475. }
  476. /// \copydoc boost::heap::fibonacci_heap::ordered_begin
  477. ordered_iterator ordered_end( void ) const
  478. {
  479. return ordered_iterator( nullptr, super_t::value_comp() );
  480. }
  481. /// \copydoc boost::heap::d_ary_heap_mutable::s_handle_from_iterator
  482. static handle_type s_handle_from_iterator( iterator const& it )
  483. {
  484. node* ptr = const_cast< node* >( it.get_node() );
  485. return handle_type( ptr );
  486. }
  487. /**
  488. * \b Effects: Merge all elements from rhs into this
  489. *
  490. * \cond
  491. * \b Complexity: \f$2^2log(log(N))\f$ (amortized).
  492. * \endcond
  493. *
  494. * \b Complexity: 2**2*log(log(N)) (amortized).
  495. *
  496. * */
  497. void merge( pairing_heap& rhs )
  498. {
  499. if ( rhs.empty() )
  500. return;
  501. merge_node( rhs.root );
  502. size_holder::add( rhs.get_size() );
  503. rhs.set_size( 0 );
  504. rhs.root = nullptr;
  505. super_t::set_stability_count( ( std::max )( super_t::get_stability_count(), rhs.get_stability_count() ) );
  506. rhs.set_stability_count( 0 );
  507. }
  508. /// \copydoc boost::heap::priority_queue::value_comp
  509. value_compare const& value_comp( void ) const
  510. {
  511. return super_t::value_comp();
  512. }
  513. /// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
  514. template < typename HeapType >
  515. bool operator<( HeapType const& rhs ) const
  516. {
  517. return detail::heap_compare( *this, rhs );
  518. }
  519. /// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
  520. template < typename HeapType >
  521. bool operator>( HeapType const& rhs ) const
  522. {
  523. return detail::heap_compare( rhs, *this );
  524. }
  525. /// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
  526. template < typename HeapType >
  527. bool operator>=( HeapType const& rhs ) const
  528. {
  529. return !operator<( rhs );
  530. }
  531. /// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
  532. template < typename HeapType >
  533. bool operator<=( HeapType const& rhs ) const
  534. {
  535. return !operator>( rhs );
  536. }
  537. /// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
  538. template < typename HeapType >
  539. bool operator==( HeapType const& rhs ) const
  540. {
  541. return detail::heap_equality( *this, rhs );
  542. }
  543. /// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
  544. template < typename HeapType >
  545. bool operator!=( HeapType const& rhs ) const
  546. {
  547. return !( *this == rhs );
  548. }
  549. private:
  550. #if !defined( BOOST_DOXYGEN_INVOKED )
  551. void clone_tree( pairing_heap const& rhs )
  552. {
  553. BOOST_HEAP_ASSERT( root == nullptr );
  554. if ( rhs.empty() )
  555. return;
  556. root = allocator_type::allocate( 1 );
  557. new ( root ) node( static_cast< node const& >( *rhs.root ), static_cast< allocator_type& >( *this ) );
  558. }
  559. void merge_node( node_pointer other )
  560. {
  561. BOOST_HEAP_ASSERT( other );
  562. if ( root != nullptr )
  563. root = merge_nodes( root, other );
  564. else
  565. root = other;
  566. }
  567. node_pointer merge_node_list( node_child_list& children )
  568. {
  569. BOOST_HEAP_ASSERT( !children.empty() );
  570. node_pointer merged = merge_first_pair( children );
  571. if ( children.empty() )
  572. return merged;
  573. node_child_list node_list;
  574. node_list.push_back( *merged );
  575. do {
  576. node_pointer next_merged = merge_first_pair( children );
  577. node_list.push_back( *next_merged );
  578. } while ( !children.empty() );
  579. return merge_node_list( node_list );
  580. }
  581. node_pointer merge_first_pair( node_child_list& children )
  582. {
  583. BOOST_HEAP_ASSERT( !children.empty() );
  584. node_pointer first_child = static_cast< node_pointer >( &children.front() );
  585. children.pop_front();
  586. if ( children.empty() )
  587. return first_child;
  588. node_pointer second_child = static_cast< node_pointer >( &children.front() );
  589. children.pop_front();
  590. return merge_nodes( first_child, second_child );
  591. }
  592. node_pointer merge_nodes( node_pointer node1, node_pointer node2 )
  593. {
  594. if ( super_t::operator()( node1->value, node2->value ) )
  595. std::swap( node1, node2 );
  596. node2->unlink();
  597. node1->children.push_front( *node2 );
  598. return node1;
  599. }
  600. node_pointer root;
  601. #endif
  602. };
  603. }} // namespace boost::heap
  604. #undef BOOST_HEAP_ASSERT
  605. #endif /* BOOST_HEAP_PAIRING_HEAP_HPP */