pairing_heap.hpp 23 KB

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