File indexing completed on 2025-12-16 09:53:06
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_HEAP_PAIRING_HEAP_HPP
0010 #define BOOST_HEAP_PAIRING_HEAP_HPP
0011
0012 #include <algorithm>
0013 #include <type_traits>
0014 #include <utility>
0015
0016 #include <boost/assert.hpp>
0017
0018 #include <boost/heap/detail/heap_comparison.hpp>
0019 #include <boost/heap/detail/heap_node.hpp>
0020 #include <boost/heap/detail/stable_heap.hpp>
0021 #include <boost/heap/detail/tree_iterator.hpp>
0022 #include <boost/heap/policies.hpp>
0023
0024 #ifdef BOOST_HAS_PRAGMA_ONCE
0025 # pragma once
0026 #endif
0027
0028
0029 #ifndef BOOST_DOXYGEN_INVOKED
0030 # ifdef BOOST_HEAP_SANITYCHECKS
0031 # define BOOST_HEAP_ASSERT BOOST_ASSERT
0032 # else
0033 # define BOOST_HEAP_ASSERT( expression ) static_assert( true, "force semicolon" )
0034 # endif
0035 #endif
0036
0037 namespace boost { namespace heap {
0038 namespace detail {
0039
0040 typedef parameter::parameters< boost::parameter::optional< tag::allocator >,
0041 boost::parameter::optional< tag::compare >,
0042 boost::parameter::optional< tag::stable >,
0043 boost::parameter::optional< tag::constant_time_size >,
0044 boost::parameter::optional< tag::stability_counter_type > >
0045 pairing_heap_signature;
0046
0047 template < typename T, typename Parspec >
0048 struct make_pairing_heap_base
0049 {
0050 static const bool constant_time_size
0051 = parameter::binding< Parspec, tag::constant_time_size, std::true_type >::type::value;
0052 typedef typename detail::make_heap_base< T, Parspec, constant_time_size >::type base_type;
0053 typedef typename detail::make_heap_base< T, Parspec, constant_time_size >::allocator_argument allocator_argument;
0054 typedef typename detail::make_heap_base< T, Parspec, constant_time_size >::compare_argument compare_argument;
0055
0056 typedef heap_node< typename base_type::internal_type, false > node_type;
0057
0058 typedef typename boost::allocator_rebind< allocator_argument, node_type >::type allocator_type;
0059
0060 struct type : base_type, allocator_type
0061 {
0062 type( compare_argument const& arg ) :
0063 base_type( arg )
0064 {}
0065
0066 type( allocator_type const& arg ) :
0067 allocator_type( arg )
0068 {}
0069
0070 type( type const& rhs ) :
0071 base_type( rhs ),
0072 allocator_type( rhs )
0073 {}
0074
0075 type( type&& rhs ) :
0076 base_type( std::move( static_cast< base_type& >( rhs ) ) ),
0077 allocator_type( std::move( static_cast< allocator_type& >( rhs ) ) )
0078 {}
0079
0080 type& operator=( type&& rhs )
0081 {
0082 base_type::operator=( std::move( static_cast< base_type& >( rhs ) ) );
0083 allocator_type::operator=( std::move( static_cast< allocator_type& >( rhs ) ) );
0084 return *this;
0085 }
0086
0087 type& operator=( type const& rhs )
0088 {
0089 base_type::operator=( static_cast< base_type const& >( rhs ) );
0090 allocator_type::operator=( static_cast< const allocator_type& >( rhs ) );
0091 return *this;
0092 }
0093 };
0094 };
0095
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 #ifdef BOOST_DOXYGEN_INVOKED
0121 template < class T, class... Options >
0122 #else
0123 template < typename T,
0124 class A0 = boost::parameter::void_,
0125 class A1 = boost::parameter::void_,
0126 class A2 = boost::parameter::void_,
0127 class A3 = boost::parameter::void_,
0128 class A4 = boost::parameter::void_ >
0129 #endif
0130 class pairing_heap :
0131 private detail::make_pairing_heap_base< T, typename detail::pairing_heap_signature::bind< A0, A1, A2, A3, A4 >::type >::type
0132 {
0133 typedef typename detail::pairing_heap_signature::bind< A0, A1, A2, A3, A4 >::type bound_args;
0134 typedef detail::make_pairing_heap_base< T, bound_args > base_maker;
0135 typedef typename base_maker::type super_t;
0136
0137 typedef typename super_t::internal_type internal_type;
0138 typedef typename super_t::size_holder_type size_holder;
0139 typedef typename base_maker::allocator_argument allocator_argument;
0140
0141 private:
0142 template < typename Heap1, typename Heap2 >
0143 friend struct heap_merge_emulate;
0144
0145 #ifndef BOOST_DOXYGEN_INVOKED
0146 struct implementation_defined : detail::extract_allocator_types< typename base_maker::allocator_argument >
0147 {
0148 typedef T value_type;
0149 typedef typename detail::extract_allocator_types< typename base_maker::allocator_argument >::size_type size_type;
0150 typedef typename detail::extract_allocator_types< typename base_maker::allocator_argument >::reference reference;
0151
0152 typedef typename base_maker::compare_argument value_compare;
0153 typedef typename base_maker::allocator_type allocator_type;
0154
0155 typedef typename boost::allocator_pointer< allocator_type >::type node_pointer;
0156 typedef typename boost::allocator_const_pointer< allocator_type >::type const_node_pointer;
0157
0158 typedef detail::heap_node_list node_list_type;
0159 typedef typename node_list_type::iterator node_list_iterator;
0160 typedef typename node_list_type::const_iterator node_list_const_iterator;
0161
0162 typedef typename base_maker::node_type node;
0163
0164 typedef detail::value_extractor< value_type, internal_type, super_t > value_extractor;
0165 typedef typename super_t::internal_compare internal_compare;
0166 typedef detail::node_handle< node_pointer, super_t, reference > handle_type;
0167
0168 typedef detail::tree_iterator< node,
0169 const value_type,
0170 allocator_type,
0171 value_extractor,
0172 detail::pointer_to_reference< node >,
0173 false,
0174 false,
0175 value_compare >
0176 iterator;
0177
0178 typedef iterator const_iterator;
0179
0180 typedef detail::tree_iterator< node,
0181 const value_type,
0182 allocator_type,
0183 value_extractor,
0184 detail::pointer_to_reference< node >,
0185 false,
0186 true,
0187 value_compare >
0188 ordered_iterator;
0189 };
0190
0191 typedef typename implementation_defined::node node;
0192 typedef typename implementation_defined::node_pointer node_pointer;
0193 typedef typename implementation_defined::node_list_type node_list_type;
0194 typedef typename implementation_defined::node_list_iterator node_list_iterator;
0195 typedef typename implementation_defined::node_list_const_iterator node_list_const_iterator;
0196 typedef typename implementation_defined::internal_compare internal_compare;
0197
0198 typedef boost::intrusive::list< detail::heap_node_base< true >, boost::intrusive::constant_time_size< false > >
0199 node_child_list;
0200 #endif
0201
0202 public:
0203 typedef T value_type;
0204
0205 typedef typename implementation_defined::size_type size_type;
0206 typedef typename implementation_defined::difference_type difference_type;
0207 typedef typename implementation_defined::value_compare value_compare;
0208 typedef typename implementation_defined::allocator_type allocator_type;
0209 typedef typename implementation_defined::reference reference;
0210 typedef typename implementation_defined::const_reference const_reference;
0211 typedef typename implementation_defined::pointer pointer;
0212 typedef typename implementation_defined::const_pointer const_pointer;
0213
0214 typedef typename implementation_defined::iterator iterator;
0215 typedef typename implementation_defined::const_iterator const_iterator;
0216 typedef typename implementation_defined::ordered_iterator ordered_iterator;
0217
0218 typedef typename implementation_defined::handle_type handle_type;
0219
0220 static const bool constant_time_size = super_t::constant_time_size;
0221 static const bool has_ordered_iterators = true;
0222 static const bool is_mergable = true;
0223 static const bool is_stable = detail::extract_stable< bound_args >::value;
0224 static const bool has_reserve = false;
0225
0226
0227 explicit pairing_heap( value_compare const& cmp = value_compare() ) :
0228 super_t( cmp ),
0229 root( nullptr )
0230 {}
0231
0232
0233 explicit pairing_heap( allocator_type const& alloc ) :
0234 super_t( alloc ),
0235 root( nullptr )
0236 {}
0237
0238
0239 pairing_heap( pairing_heap const& rhs ) :
0240 super_t( rhs ),
0241 root( nullptr )
0242 {
0243 if ( rhs.empty() )
0244 return;
0245
0246 clone_tree( rhs );
0247 size_holder::set_size( rhs.get_size() );
0248 }
0249
0250
0251 pairing_heap( pairing_heap&& rhs ) :
0252 super_t( std::move( rhs ) ),
0253 root( rhs.root )
0254 {
0255 rhs.root = nullptr;
0256 }
0257
0258
0259 pairing_heap& operator=( pairing_heap&& rhs )
0260 {
0261 super_t::operator=( std::move( rhs ) );
0262 root = rhs.root;
0263 rhs.root = nullptr;
0264 return *this;
0265 }
0266
0267
0268 pairing_heap& operator=( pairing_heap const& rhs )
0269 {
0270 clear();
0271 size_holder::set_size( rhs.get_size() );
0272 static_cast< super_t& >( *this ) = rhs;
0273
0274 clone_tree( rhs );
0275 return *this;
0276 }
0277
0278 ~pairing_heap( void )
0279 {
0280 while ( !empty() )
0281 pop();
0282 }
0283
0284
0285 bool empty( void ) const
0286 {
0287 return root == nullptr;
0288 }
0289
0290
0291 size_type size( void ) const
0292 {
0293 if ( constant_time_size )
0294 return size_holder::get_size();
0295
0296 if ( root == nullptr )
0297 return 0;
0298 else
0299 return detail::count_nodes( root );
0300 }
0301
0302
0303 size_type max_size( void ) const
0304 {
0305 const allocator_type& alloc = *this;
0306 return boost::allocator_max_size( alloc );
0307 }
0308
0309
0310 void clear( void )
0311 {
0312 if ( empty() )
0313 return;
0314
0315 root->template clear_subtree< allocator_type >( *this );
0316 root->~node();
0317 allocator_type& alloc = *this;
0318 alloc.deallocate( root, 1 );
0319 root = nullptr;
0320 size_holder::set_size( 0 );
0321 }
0322
0323
0324 allocator_type get_allocator( void ) const
0325 {
0326 return *this;
0327 }
0328
0329
0330 void swap( pairing_heap& rhs )
0331 {
0332 super_t::swap( rhs );
0333 std::swap( root, rhs.root );
0334 }
0335
0336
0337
0338 const_reference top( void ) const
0339 {
0340 BOOST_ASSERT( !empty() );
0341
0342 return super_t::get_value( root->value );
0343 }
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355 handle_type push( value_type const& v )
0356 {
0357 size_holder::increment();
0358
0359 allocator_type& alloc = *this;
0360 node_pointer n = alloc.allocate( 1 );
0361 new ( n ) node( super_t::make_node( v ) );
0362 merge_node( n );
0363 return handle_type( n );
0364 }
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377 template < class... Args >
0378 handle_type emplace( Args&&... args )
0379 {
0380 size_holder::increment();
0381
0382 allocator_type& alloc = *this;
0383 node_pointer n = alloc.allocate( 1 );
0384 new ( n ) node( super_t::make_node( std::forward< Args >( args )... ) );
0385 merge_node( n );
0386 return handle_type( n );
0387 }
0388
0389
0390
0391
0392
0393
0394
0395 void pop( void )
0396 {
0397 BOOST_ASSERT( !empty() );
0398
0399 erase( handle_type( root ) );
0400 }
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 void update( handle_type handle, const_reference v )
0413 {
0414 handle.node_->value = super_t::make_node( v );
0415 update( handle );
0416 }
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429 void update( handle_type handle )
0430 {
0431 node_pointer n = handle.node_;
0432
0433 n->unlink();
0434 if ( !n->children.empty() )
0435 n = merge_nodes( n, merge_node_list( n->children ) );
0436
0437 if ( n != root )
0438 merge_node( n );
0439 }
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 void increase( handle_type handle, const_reference v )
0453 {
0454 update( handle, v );
0455 }
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468 void increase( handle_type handle )
0469 {
0470 update( handle );
0471 }
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484 void decrease( handle_type handle, const_reference v )
0485 {
0486 update( handle, v );
0487 }
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501 void decrease( handle_type handle )
0502 {
0503 update( handle );
0504 }
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515 void erase( handle_type handle )
0516 {
0517 node_pointer n = handle.node_;
0518 if ( n != root ) {
0519 n->unlink();
0520 if ( !n->children.empty() )
0521 merge_node( merge_node_list( n->children ) );
0522 } else {
0523 if ( !n->children.empty() )
0524 root = merge_node_list( n->children );
0525 else
0526 root = nullptr;
0527 }
0528
0529 size_holder::decrement();
0530 n->~node();
0531 allocator_type& alloc = *this;
0532 alloc.deallocate( n, 1 );
0533 }
0534
0535
0536 iterator begin( void ) const
0537 {
0538 return iterator( root, super_t::value_comp() );
0539 }
0540
0541
0542 iterator end( void ) const
0543 {
0544 return iterator( super_t::value_comp() );
0545 }
0546
0547
0548 ordered_iterator ordered_begin( void ) const
0549 {
0550 return ordered_iterator( root, super_t::value_comp() );
0551 }
0552
0553
0554 ordered_iterator ordered_end( void ) const
0555 {
0556 return ordered_iterator( nullptr, super_t::value_comp() );
0557 }
0558
0559
0560
0561 static handle_type s_handle_from_iterator( iterator const& it )
0562 {
0563 node* ptr = const_cast< node* >( it.get_node() );
0564 return handle_type( ptr );
0565 }
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577 void merge( pairing_heap& rhs )
0578 {
0579 if ( rhs.empty() )
0580 return;
0581
0582 merge_node( rhs.root );
0583
0584 size_holder::add( rhs.get_size() );
0585 rhs.set_size( 0 );
0586 rhs.root = nullptr;
0587
0588 super_t::set_stability_count( ( std::max )( super_t::get_stability_count(), rhs.get_stability_count() ) );
0589 rhs.set_stability_count( 0 );
0590 }
0591
0592
0593 value_compare const& value_comp( void ) const
0594 {
0595 return super_t::value_comp();
0596 }
0597
0598
0599 template < typename HeapType >
0600 bool operator<( HeapType const& rhs ) const
0601 {
0602 return detail::heap_compare( *this, rhs );
0603 }
0604
0605
0606 template < typename HeapType >
0607 bool operator>( HeapType const& rhs ) const
0608 {
0609 return detail::heap_compare( rhs, *this );
0610 }
0611
0612
0613 template < typename HeapType >
0614 bool operator>=( HeapType const& rhs ) const
0615 {
0616 return !operator<( rhs );
0617 }
0618
0619
0620 template < typename HeapType >
0621 bool operator<=( HeapType const& rhs ) const
0622 {
0623 return !operator>( rhs );
0624 }
0625
0626
0627 template < typename HeapType >
0628 bool operator==( HeapType const& rhs ) const
0629 {
0630 return detail::heap_equality( *this, rhs );
0631 }
0632
0633
0634 template < typename HeapType >
0635 bool operator!=( HeapType const& rhs ) const
0636 {
0637 return !( *this == rhs );
0638 }
0639
0640 private:
0641 #if !defined( BOOST_DOXYGEN_INVOKED )
0642 void clone_tree( pairing_heap const& rhs )
0643 {
0644 BOOST_HEAP_ASSERT( root == nullptr );
0645 if ( rhs.empty() )
0646 return;
0647
0648 root = allocator_type::allocate( 1 );
0649
0650 new ( root ) node( static_cast< node const& >( *rhs.root ), static_cast< allocator_type& >( *this ) );
0651 }
0652
0653 void merge_node( node_pointer other )
0654 {
0655 BOOST_HEAP_ASSERT( other );
0656 if ( root != nullptr )
0657 root = merge_nodes( root, other );
0658 else
0659 root = other;
0660 }
0661
0662 node_pointer merge_node_list( node_child_list& children )
0663 {
0664 BOOST_HEAP_ASSERT( !children.empty() );
0665 node_pointer merged = merge_first_pair( children );
0666 if ( children.empty() )
0667 return merged;
0668
0669 node_child_list node_list;
0670 node_list.push_back( *merged );
0671
0672 do {
0673 node_pointer next_merged = merge_first_pair( children );
0674 node_list.push_back( *next_merged );
0675 } while ( !children.empty() );
0676
0677 return merge_node_list( node_list );
0678 }
0679
0680 node_pointer merge_first_pair( node_child_list& children )
0681 {
0682 BOOST_HEAP_ASSERT( !children.empty() );
0683 node_pointer first_child = static_cast< node_pointer >( &children.front() );
0684 children.pop_front();
0685 if ( children.empty() )
0686 return first_child;
0687
0688 node_pointer second_child = static_cast< node_pointer >( &children.front() );
0689 children.pop_front();
0690
0691 return merge_nodes( first_child, second_child );
0692 }
0693
0694 node_pointer merge_nodes( node_pointer node1, node_pointer node2 )
0695 {
0696 if ( super_t::operator()( node1->value, node2->value ) )
0697 std::swap( node1, node2 );
0698
0699 node2->unlink();
0700 node1->children.push_front( *node2 );
0701 return node1;
0702 }
0703
0704 node_pointer root;
0705 #endif
0706 };
0707
0708
0709 }}
0710
0711 #undef BOOST_HEAP_ASSERT
0712 #endif