File indexing completed on 2025-12-16 09:53:06
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_HEAP_SKEW_HEAP_HPP
0010 #define BOOST_HEAP_SKEW_HEAP_HPP
0011
0012 #include <algorithm>
0013 #include <array>
0014 #include <type_traits>
0015 #include <utility>
0016
0017 #include <boost/assert.hpp>
0018
0019 #include <boost/heap/detail/heap_comparison.hpp>
0020 #include <boost/heap/detail/heap_node.hpp>
0021 #include <boost/heap/detail/stable_heap.hpp>
0022 #include <boost/heap/detail/tree_iterator.hpp>
0023
0024 #ifdef BOOST_HAS_PRAGMA_ONCE
0025 # pragma once
0026 #endif
0027
0028 #ifndef BOOST_DOXYGEN_INVOKED
0029 # ifdef BOOST_HEAP_SANITYCHECKS
0030 # define BOOST_HEAP_ASSERT BOOST_ASSERT
0031 # else
0032 # define BOOST_HEAP_ASSERT( expression ) static_assert( true, "force semicolon" )
0033 # endif
0034 #endif
0035
0036 namespace boost { namespace heap {
0037 namespace detail {
0038
0039 template < typename node_pointer, bool store_parent_pointer >
0040 struct parent_holder
0041 {
0042 parent_holder( void ) :
0043 parent_( nullptr )
0044 {}
0045
0046 void set_parent( node_pointer parent )
0047 {
0048 BOOST_HEAP_ASSERT( static_cast< node_pointer >( this ) != parent );
0049 parent_ = parent;
0050 }
0051
0052 node_pointer get_parent( void ) const
0053 {
0054 return parent_;
0055 }
0056
0057 node_pointer parent_;
0058 };
0059
0060 template < typename node_pointer >
0061 struct parent_holder< node_pointer, false >
0062 {
0063 void set_parent( node_pointer )
0064 {}
0065
0066 node_pointer get_parent( void ) const
0067 {
0068 return nullptr;
0069 }
0070 };
0071
0072
0073 template < typename value_type, bool store_parent_pointer >
0074 struct skew_heap_node : parent_holder< skew_heap_node< value_type, store_parent_pointer >*, store_parent_pointer >
0075 {
0076 typedef parent_holder< skew_heap_node< value_type, store_parent_pointer >*, store_parent_pointer > super_t;
0077
0078 typedef std::array< skew_heap_node*, 2 > child_list_type;
0079 typedef typename child_list_type::iterator child_iterator;
0080 typedef typename child_list_type::const_iterator const_child_iterator;
0081
0082 skew_heap_node( value_type const& v ) :
0083 value( v )
0084 {
0085 children.fill( 0 );
0086 }
0087
0088 skew_heap_node( value_type&& v ) :
0089 value( v )
0090 {
0091 children.fill( 0 );
0092 }
0093
0094 template < typename Alloc >
0095 skew_heap_node( skew_heap_node const& rhs, Alloc& allocator, skew_heap_node* parent ) :
0096 value( rhs.value )
0097 {
0098 super_t::set_parent( parent );
0099 node_cloner< skew_heap_node, skew_heap_node, Alloc > cloner( allocator );
0100 clone_child( 0, rhs, cloner );
0101 clone_child( 1, rhs, cloner );
0102 }
0103
0104 template < typename Cloner >
0105 void clone_child( int index, skew_heap_node const& rhs, Cloner& cloner )
0106 {
0107 if ( rhs.children[ index ] )
0108 children[ index ] = cloner( *rhs.children[ index ], this );
0109 else
0110 children[ index ] = nullptr;
0111 }
0112
0113 template < typename Alloc >
0114 void clear_subtree( Alloc& alloc )
0115 {
0116 node_disposer< skew_heap_node, skew_heap_node, Alloc > disposer( alloc );
0117 dispose_child( children[ 0 ], disposer );
0118 dispose_child( children[ 1 ], disposer );
0119 }
0120
0121 template < typename Disposer >
0122 void dispose_child( skew_heap_node* node, Disposer& disposer )
0123 {
0124 if ( node )
0125 disposer( node );
0126 }
0127
0128 std::size_t count_children( void ) const
0129 {
0130 size_t ret = 1;
0131 if ( children[ 0 ] )
0132 ret += children[ 0 ]->count_children();
0133 if ( children[ 1 ] )
0134 ret += children[ 1 ]->count_children();
0135
0136 return ret;
0137 }
0138
0139 template < typename HeapBase >
0140 bool is_heap( typename HeapBase::value_compare const& cmp ) const
0141 {
0142 for ( const_child_iterator it = children.begin(); it != children.end(); ++it ) {
0143 const skew_heap_node* child = *it;
0144
0145 if ( child == nullptr )
0146 continue;
0147
0148 if ( store_parent_pointer )
0149 BOOST_HEAP_ASSERT( child->get_parent() == this );
0150
0151 if ( cmp( HeapBase::get_value( value ), HeapBase::get_value( child->value ) )
0152 || !child->is_heap< HeapBase >( cmp ) )
0153 return false;
0154 }
0155 return true;
0156 }
0157
0158 value_type value;
0159 std::array< skew_heap_node*, 2 > children;
0160 };
0161
0162
0163 typedef parameter::parameters< boost::parameter::optional< tag::allocator >,
0164 boost::parameter::optional< tag::compare >,
0165 boost::parameter::optional< tag::stable >,
0166 boost::parameter::optional< tag::store_parent_pointer >,
0167 boost::parameter::optional< tag::stability_counter_type >,
0168 boost::parameter::optional< tag::constant_time_size >,
0169 boost::parameter::optional< tag::mutable_ > >
0170 skew_heap_signature;
0171
0172 template < typename T, typename BoundArgs >
0173 struct make_skew_heap_base
0174 {
0175 static const bool constant_time_size
0176 = parameter::binding< BoundArgs, tag::constant_time_size, std::true_type >::type::value;
0177
0178 typedef typename make_heap_base< T, BoundArgs, constant_time_size >::type base_type;
0179 typedef typename make_heap_base< T, BoundArgs, constant_time_size >::allocator_argument allocator_argument;
0180 typedef typename make_heap_base< T, BoundArgs, constant_time_size >::compare_argument compare_argument;
0181
0182 static const bool is_mutable = extract_mutable< BoundArgs >::value;
0183 static const bool store_parent_pointer
0184 = parameter::binding< BoundArgs, tag::store_parent_pointer, boost::false_type >::type::value || is_mutable;
0185
0186 typedef skew_heap_node< typename base_type::internal_type, store_parent_pointer > node_type;
0187
0188 typedef typename boost::allocator_rebind< allocator_argument, node_type >::type allocator_type;
0189
0190 struct type : base_type, allocator_type
0191 {
0192 type( compare_argument const& arg ) :
0193 base_type( arg )
0194 {}
0195
0196 type( allocator_type const& arg ) :
0197 allocator_type( arg )
0198 {}
0199
0200 type( type&& rhs ) :
0201 base_type( std::move( static_cast< base_type& >( rhs ) ) ),
0202 allocator_type( std::move( static_cast< allocator_type& >( rhs ) ) )
0203 {}
0204
0205 type( type const& rhs ) :
0206 base_type( rhs ),
0207 allocator_type( rhs )
0208 {}
0209
0210 type& operator=( type&& rhs )
0211 {
0212 base_type::operator=( std::move( static_cast< base_type& >( rhs ) ) );
0213 allocator_type::operator=( std::move( static_cast< allocator_type& >( rhs ) ) );
0214 return *this;
0215 }
0216
0217 type& operator=( type const& rhs )
0218 {
0219 base_type::operator=( static_cast< base_type const& >( rhs ) );
0220 allocator_type::operator=( static_cast< allocator_type const& >( rhs ) );
0221 return *this;
0222 }
0223 };
0224 };
0225
0226 }
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 #ifdef BOOST_DOXYGEN_INVOKED
0248 template < class T, class... Options >
0249 #else
0250 template < typename T,
0251 class A0 = boost::parameter::void_,
0252 class A1 = boost::parameter::void_,
0253 class A2 = boost::parameter::void_,
0254 class A3 = boost::parameter::void_,
0255 class A4 = boost::parameter::void_,
0256 class A5 = boost::parameter::void_,
0257 class A6 = boost::parameter::void_ >
0258 #endif
0259 class skew_heap :
0260 private detail::make_skew_heap_base< T, typename detail::skew_heap_signature::bind< A0, A1, A2, A3, A4, A5, A6 >::type >::type
0261 {
0262 typedef typename detail::skew_heap_signature::bind< A0, A1, A2, A3, A4, A5, A6 >::type bound_args;
0263 typedef detail::make_skew_heap_base< T, bound_args > base_maker;
0264 typedef typename base_maker::type super_t;
0265
0266 typedef typename super_t::internal_type internal_type;
0267 typedef typename super_t::size_holder_type size_holder;
0268 typedef typename base_maker::allocator_argument allocator_argument;
0269
0270 static const bool store_parent_pointer = base_maker::store_parent_pointer;
0271 template < typename Heap1, typename Heap2 >
0272 friend struct heap_merge_emulate;
0273
0274 struct implementation_defined : detail::extract_allocator_types< typename base_maker::allocator_argument >
0275 {
0276 typedef T value_type;
0277
0278 typedef typename base_maker::compare_argument value_compare;
0279 typedef typename base_maker::allocator_type allocator_type;
0280
0281 typedef typename base_maker::node_type node;
0282 typedef typename boost::allocator_pointer< allocator_type >::type node_pointer;
0283 typedef typename boost::allocator_const_pointer< allocator_type >::type const_node_pointer;
0284
0285 typedef detail::value_extractor< value_type, internal_type, super_t > value_extractor;
0286
0287 typedef std::array< node_pointer, 2 > child_list_type;
0288 typedef typename child_list_type::iterator child_list_iterator;
0289
0290 typedef typename std::conditional<
0291 false,
0292 detail::recursive_tree_iterator< node,
0293 child_list_iterator,
0294 const value_type,
0295 value_extractor,
0296 detail::list_iterator_converter< node, child_list_type > >,
0297 detail::tree_iterator< node,
0298 const value_type,
0299 allocator_type,
0300 value_extractor,
0301 detail::dereferencer< node >,
0302 true,
0303 false,
0304 value_compare > >::type iterator;
0305
0306 typedef iterator const_iterator;
0307
0308 typedef detail::
0309 tree_iterator< node, const value_type, allocator_type, value_extractor, detail::dereferencer< node >, true, true, value_compare >
0310 ordered_iterator;
0311
0312 typedef typename detail::extract_allocator_types< typename base_maker::allocator_argument >::reference reference;
0313 typedef detail::node_handle< node_pointer, super_t, reference > handle_type;
0314 };
0315
0316 typedef typename implementation_defined::value_extractor value_extractor;
0317 typedef typename implementation_defined::node node;
0318 typedef typename implementation_defined::node_pointer node_pointer;
0319
0320 public:
0321 typedef T value_type;
0322
0323 typedef typename implementation_defined::size_type size_type;
0324 typedef typename implementation_defined::difference_type difference_type;
0325 typedef typename implementation_defined::value_compare value_compare;
0326 typedef typename implementation_defined::allocator_type allocator_type;
0327 typedef typename implementation_defined::reference reference;
0328 typedef typename implementation_defined::const_reference const_reference;
0329 typedef typename implementation_defined::pointer pointer;
0330 typedef typename implementation_defined::const_pointer const_pointer;
0331
0332
0333 typedef typename implementation_defined::iterator iterator;
0334 typedef typename implementation_defined::const_iterator const_iterator;
0335 typedef typename implementation_defined::ordered_iterator ordered_iterator;
0336
0337 static const bool constant_time_size = super_t::constant_time_size;
0338 static const bool has_ordered_iterators = true;
0339 static const bool is_mergable = true;
0340 static const bool is_stable = detail::extract_stable< bound_args >::value;
0341 static const bool has_reserve = false;
0342 static const bool is_mutable = detail::extract_mutable< bound_args >::value;
0343
0344 typedef
0345 typename std::conditional< is_mutable, typename implementation_defined::handle_type, void* >::type handle_type;
0346
0347
0348 explicit skew_heap( value_compare const& cmp = value_compare() ) :
0349 super_t( cmp ),
0350 root( nullptr )
0351 {}
0352
0353
0354 explicit skew_heap( allocator_type const& alloc ) :
0355 super_t( alloc ),
0356 root( 0 )
0357 {}
0358
0359
0360 skew_heap( skew_heap const& rhs ) :
0361 super_t( rhs ),
0362 root( 0 )
0363 {
0364 if ( rhs.empty() )
0365 return;
0366
0367 clone_tree( rhs );
0368 size_holder::set_size( rhs.get_size() );
0369 }
0370
0371
0372 skew_heap& operator=( skew_heap const& rhs )
0373 {
0374 clear();
0375 size_holder::set_size( rhs.get_size() );
0376 static_cast< super_t& >( *this ) = rhs;
0377
0378 clone_tree( rhs );
0379 return *this;
0380 }
0381
0382
0383 skew_heap( skew_heap&& rhs ) :
0384 super_t( std::move( rhs ) ),
0385 root( rhs.root )
0386 {
0387 rhs.root = nullptr;
0388 }
0389
0390
0391 skew_heap& operator=( skew_heap&& rhs )
0392 {
0393 super_t::operator=( std::move( rhs ) );
0394 root = rhs.root;
0395 rhs.root = nullptr;
0396 return *this;
0397 }
0398
0399 ~skew_heap( void )
0400 {
0401 clear();
0402 }
0403
0404
0405
0406
0407
0408
0409
0410 typename std::conditional< is_mutable, handle_type, void >::type push( value_type const& v )
0411 {
0412 typedef typename std::conditional< is_mutable, push_handle, push_void >::type push_helper;
0413 return push_helper::push( this, v );
0414 }
0415
0416
0417
0418
0419
0420
0421
0422 template < typename... Args >
0423 typename std::conditional< is_mutable, handle_type, void >::type emplace( Args&&... args )
0424 {
0425 typedef typename std::conditional< is_mutable, push_handle, push_void >::type push_helper;
0426 return push_helper::emplace( this, std::forward< Args >( args )... );
0427 }
0428
0429
0430 bool empty( void ) const
0431 {
0432 return root == nullptr;
0433 }
0434
0435
0436 size_type size( void ) const
0437 {
0438 if ( constant_time_size )
0439 return size_holder::get_size();
0440
0441 if ( root == nullptr )
0442 return 0;
0443 else
0444 return root->count_children();
0445 }
0446
0447
0448 size_type max_size( void ) const
0449 {
0450 const allocator_type& alloc = *this;
0451 return boost::allocator_max_size( alloc );
0452 }
0453
0454
0455 void clear( void )
0456 {
0457 if ( empty() )
0458 return;
0459
0460 root->template clear_subtree< allocator_type >( *this );
0461 root->~node();
0462 allocator_type& alloc = *this;
0463 alloc.deallocate( root, 1 );
0464 root = nullptr;
0465 size_holder::set_size( 0 );
0466 }
0467
0468
0469 allocator_type get_allocator( void ) const
0470 {
0471 return *this;
0472 }
0473
0474
0475 void swap( skew_heap& rhs )
0476 {
0477 super_t::swap( rhs );
0478 std::swap( root, rhs.root );
0479 }
0480
0481
0482 const_reference top( void ) const
0483 {
0484 BOOST_ASSERT( !empty() );
0485
0486 return super_t::get_value( root->value );
0487 }
0488
0489
0490
0491
0492
0493
0494
0495 void pop( void )
0496 {
0497 BOOST_ASSERT( !empty() );
0498
0499 node_pointer top = root;
0500
0501 root = merge_children( root );
0502 size_holder::decrement();
0503
0504 if ( root )
0505 BOOST_HEAP_ASSERT( root->get_parent() == nullptr );
0506 else
0507 BOOST_HEAP_ASSERT( size_holder::get_size() == 0 );
0508
0509 top->~node();
0510 allocator_type& alloc = *this;
0511 alloc.deallocate( top, 1 );
0512 sanity_check();
0513 }
0514
0515
0516 iterator begin( void ) const
0517 {
0518 return iterator( root, super_t::value_comp() );
0519 }
0520
0521
0522 iterator end( void ) const
0523 {
0524 return iterator();
0525 }
0526
0527
0528 ordered_iterator ordered_begin( void ) const
0529 {
0530 return ordered_iterator( root, super_t::value_comp() );
0531 }
0532
0533
0534 ordered_iterator ordered_end( void ) const
0535 {
0536 return ordered_iterator( 0, super_t::value_comp() );
0537 }
0538
0539
0540
0541
0542
0543
0544
0545 void merge( skew_heap& rhs )
0546 {
0547 if ( rhs.empty() )
0548 return;
0549
0550 merge_node( rhs.root );
0551
0552 size_holder::add( rhs.get_size() );
0553 rhs.set_size( 0 );
0554 rhs.root = nullptr;
0555 sanity_check();
0556
0557 super_t::set_stability_count( ( std::max )( super_t::get_stability_count(), rhs.get_stability_count() ) );
0558 rhs.set_stability_count( 0 );
0559 }
0560
0561
0562 value_compare const& value_comp( void ) const
0563 {
0564 return super_t::value_comp();
0565 }
0566
0567
0568 template < typename HeapType >
0569 bool operator<( HeapType const& rhs ) const
0570 {
0571 return detail::heap_compare( *this, rhs );
0572 }
0573
0574
0575 template < typename HeapType >
0576 bool operator>( HeapType const& rhs ) const
0577 {
0578 return detail::heap_compare( rhs, *this );
0579 }
0580
0581
0582 template < typename HeapType >
0583 bool operator>=( HeapType const& rhs ) const
0584 {
0585 return !operator<( rhs );
0586 }
0587
0588
0589 template < typename HeapType >
0590 bool operator<=( HeapType const& rhs ) const
0591 {
0592 return !operator>( rhs );
0593 }
0594
0595
0596 template < typename HeapType >
0597 bool operator==( HeapType const& rhs ) const
0598 {
0599 return detail::heap_equality( *this, rhs );
0600 }
0601
0602
0603 template < typename HeapType >
0604 bool operator!=( HeapType const& rhs ) const
0605 {
0606 return !( *this == rhs );
0607 }
0608
0609
0610
0611 static handle_type s_handle_from_iterator( iterator const& it )
0612 {
0613 node* ptr = const_cast< node* >( it.get_node() );
0614 return handle_type( ptr );
0615 }
0616
0617
0618
0619
0620
0621
0622 void erase( handle_type object )
0623 {
0624 BOOST_STATIC_ASSERT( is_mutable );
0625 node_pointer this_node = object.node_;
0626
0627 unlink_node( this_node );
0628 size_holder::decrement();
0629
0630 sanity_check();
0631 this_node->~node();
0632 allocator_type& alloc = *this;
0633 alloc.deallocate( this_node, 1 );
0634 }
0635
0636
0637
0638
0639
0640
0641
0642 void update( handle_type handle, const_reference v )
0643 {
0644 BOOST_STATIC_ASSERT( is_mutable );
0645 if ( super_t::operator()( super_t::get_value( handle.node_->value ), v ) )
0646 increase( handle, v );
0647 else
0648 decrease( handle, v );
0649 }
0650
0651
0652
0653
0654
0655
0656
0657
0658 void update( handle_type handle )
0659 {
0660 BOOST_STATIC_ASSERT( is_mutable );
0661 node_pointer this_node = handle.node_;
0662
0663 if ( this_node->get_parent() ) {
0664 if ( super_t::operator()( super_t::get_value( this_node->get_parent()->value ),
0665 super_t::get_value( this_node->value ) ) )
0666 increase( handle );
0667 else
0668 decrease( handle );
0669 } else
0670 decrease( handle );
0671 }
0672
0673
0674
0675
0676
0677
0678
0679
0680 void increase( handle_type handle, const_reference v )
0681 {
0682 BOOST_STATIC_ASSERT( is_mutable );
0683 handle.node_->value = super_t::make_node( v );
0684 increase( handle );
0685 }
0686
0687
0688
0689
0690
0691
0692
0693
0694 void increase( handle_type handle )
0695 {
0696 BOOST_STATIC_ASSERT( is_mutable );
0697 node_pointer this_node = handle.node_;
0698
0699 if ( this_node == root )
0700 return;
0701
0702 node_pointer parent = this_node->get_parent();
0703
0704 if ( this_node == parent->children[ 0 ] )
0705 parent->children[ 0 ] = nullptr;
0706 else
0707 parent->children[ 1 ] = nullptr;
0708
0709 this_node->set_parent( nullptr );
0710 merge_node( this_node );
0711 }
0712
0713
0714
0715
0716
0717
0718
0719
0720 void decrease( handle_type handle, const_reference v )
0721 {
0722 BOOST_STATIC_ASSERT( is_mutable );
0723 handle.node_->value = super_t::make_node( v );
0724 decrease( handle );
0725 }
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735 void decrease( handle_type handle )
0736 {
0737 BOOST_STATIC_ASSERT( is_mutable );
0738 node_pointer this_node = handle.node_;
0739
0740 unlink_node( this_node );
0741 this_node->children.fill( 0 );
0742 this_node->set_parent( nullptr );
0743 merge_node( this_node );
0744 }
0745
0746 private:
0747 #if !defined( BOOST_DOXYGEN_INVOKED )
0748 struct push_void
0749 {
0750 static void push( skew_heap* self, const_reference v )
0751 {
0752 self->push_internal( v );
0753 }
0754
0755 template < class... Args >
0756 static void emplace( skew_heap* self, Args&&... args )
0757 {
0758 self->emplace_internal( std::forward< Args >( args )... );
0759 }
0760 };
0761
0762 struct push_handle
0763 {
0764 static handle_type push( skew_heap* self, const_reference v )
0765 {
0766 return handle_type( self->push_internal( v ) );
0767 }
0768
0769 template < class... Args >
0770 static handle_type emplace( skew_heap* self, Args&&... args )
0771 {
0772 return handle_type( self->emplace_internal( std::forward< Args >( args )... ) );
0773 }
0774 };
0775
0776 node_pointer push_internal( const_reference v )
0777 {
0778 size_holder::increment();
0779
0780 allocator_type& alloc = *this;
0781 node_pointer n = alloc.allocate( 1 );
0782 new ( n ) node( super_t::make_node( v ) );
0783 merge_node( n );
0784 return n;
0785 }
0786
0787 template < class... Args >
0788 node_pointer emplace_internal( Args&&... args )
0789 {
0790 size_holder::increment();
0791
0792 allocator_type& alloc = *this;
0793 node_pointer n = alloc.allocate( 1 );
0794 new ( n ) node( super_t::make_node( std::forward< Args >( args )... ) );
0795 merge_node( n );
0796 return n;
0797 }
0798
0799 void unlink_node( node_pointer node )
0800 {
0801 node_pointer parent = node->get_parent();
0802 node_pointer merged_children = merge_children( node );
0803
0804 if ( parent ) {
0805 if ( node == parent->children[ 0 ] )
0806 parent->children[ 0 ] = merged_children;
0807 else
0808 parent->children[ 1 ] = merged_children;
0809 } else
0810 root = merged_children;
0811 }
0812
0813 void clone_tree( skew_heap const& rhs )
0814 {
0815 BOOST_HEAP_ASSERT( root == nullptr );
0816 if ( rhs.empty() )
0817 return;
0818
0819 allocator_type& alloc = *this;
0820 root = alloc.allocate( 1 );
0821 new ( root ) node( *rhs.root, alloc, nullptr );
0822 }
0823
0824 void merge_node( node_pointer other )
0825 {
0826 BOOST_HEAP_ASSERT( other );
0827 if ( root != nullptr )
0828 root = merge_nodes( root, other, nullptr );
0829 else
0830 root = other;
0831 }
0832
0833 node_pointer merge_nodes( node_pointer node1, node_pointer node2, node_pointer new_parent )
0834 {
0835 if ( node1 == nullptr ) {
0836 if ( node2 )
0837 node2->set_parent( new_parent );
0838 return node2;
0839 }
0840 if ( node2 == nullptr ) {
0841 node1->set_parent( new_parent );
0842 return node1;
0843 }
0844
0845 node_pointer merged = merge_nodes_recursive( node1, node2, new_parent );
0846 return merged;
0847 }
0848
0849 node_pointer merge_children( node_pointer node )
0850 {
0851 node_pointer parent = node->get_parent();
0852 node_pointer merged_children = merge_nodes( node->children[ 0 ], node->children[ 1 ], parent );
0853
0854 return merged_children;
0855 }
0856
0857 node_pointer merge_nodes_recursive( node_pointer node1, node_pointer node2, node_pointer new_parent )
0858 {
0859 if ( super_t::operator()( node1->value, node2->value ) )
0860 std::swap( node1, node2 );
0861
0862 node* parent = node1;
0863 node* child = node2;
0864
0865 if ( parent->children[ 1 ] ) {
0866 node* merged = merge_nodes( parent->children[ 1 ], child, parent );
0867 parent->children[ 1 ] = merged;
0868 merged->set_parent( parent );
0869 } else {
0870 parent->children[ 1 ] = child;
0871 child->set_parent( parent );
0872 }
0873
0874
0875 std::swap( parent->children[ 0 ], parent->children[ 1 ] );
0876 parent->set_parent( new_parent );
0877 return parent;
0878 }
0879
0880 void sanity_check( void )
0881 {
0882 # ifdef BOOST_HEAP_SANITYCHECKS
0883 if ( root )
0884 BOOST_HEAP_ASSERT( root->template is_heap< super_t >( super_t::value_comp() ) );
0885
0886 if ( constant_time_size ) {
0887 size_type stored_size = size_holder::get_size();
0888
0889 size_type counted_size;
0890 if ( root == nullptr )
0891 counted_size = 0;
0892 else
0893 counted_size = root->count_children();
0894
0895 BOOST_HEAP_ASSERT( counted_size == stored_size );
0896 }
0897 # endif
0898 }
0899
0900 node_pointer root;
0901 #endif
0902 };
0903
0904 }}
0905
0906 #undef BOOST_HEAP_ASSERT
0907 #endif