skew_heap.hpp 28 KB

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