File indexing completed on 2025-12-16 09:53:05
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_HEAP_D_ARY_HEAP_HPP
0010 #define BOOST_HEAP_D_ARY_HEAP_HPP
0011
0012 #include <algorithm>
0013 #include <utility>
0014 #include <vector>
0015
0016 #include <boost/assert.hpp>
0017
0018 #include <boost/heap/detail/heap_comparison.hpp>
0019 #include <boost/heap/detail/mutable_heap.hpp>
0020 #include <boost/heap/detail/ordered_adaptor_iterator.hpp>
0021 #include <boost/heap/detail/stable_heap.hpp>
0022
0023 #ifdef BOOST_HAS_PRAGMA_ONCE
0024 # pragma once
0025 #endif
0026
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 struct nop_index_updater
0040 {
0041 template < typename T >
0042 static void run( T&, std::size_t )
0043 {}
0044 };
0045
0046 typedef parameter::parameters< boost::parameter::required< tag::arity >,
0047 boost::parameter::optional< tag::allocator >,
0048 boost::parameter::optional< tag::compare >,
0049 boost::parameter::optional< tag::stable >,
0050 boost::parameter::optional< tag::stability_counter_type >,
0051 boost::parameter::optional< tag::constant_time_size > >
0052 d_ary_heap_signature;
0053
0054
0055
0056 template < typename T, class BoundArgs, class IndexUpdater >
0057 class d_ary_heap : private make_heap_base< T, BoundArgs, false >::type
0058 {
0059 typedef make_heap_base< T, BoundArgs, false > heap_base_maker;
0060
0061 typedef typename heap_base_maker::type super_t;
0062 typedef typename super_t::internal_type internal_type;
0063
0064 typedef typename boost::allocator_rebind< typename heap_base_maker::allocator_argument, internal_type >::type
0065 internal_type_allocator;
0066 typedef std::vector< internal_type, internal_type_allocator > container_type;
0067 typedef typename container_type::const_iterator container_iterator;
0068
0069 typedef IndexUpdater index_updater;
0070
0071 container_type q_;
0072
0073 static const unsigned int D = parameter::binding< BoundArgs, tag::arity >::type::value;
0074
0075 template < typename Heap1, typename Heap2 >
0076 friend struct heap_merge_emulate;
0077
0078 struct implementation_defined : extract_allocator_types< typename heap_base_maker::allocator_argument >
0079 {
0080 typedef T value_type;
0081 typedef
0082 typename detail::extract_allocator_types< typename heap_base_maker::allocator_argument >::size_type size_type;
0083
0084 typedef typename heap_base_maker::compare_argument value_compare;
0085 typedef typename heap_base_maker::allocator_argument allocator_type;
0086
0087 struct ordered_iterator_dispatcher
0088 {
0089 static size_type max_index( const d_ary_heap* heap )
0090 {
0091 return heap->q_.size() - 1;
0092 }
0093
0094 static bool is_leaf( const d_ary_heap* heap, size_type index )
0095 {
0096 return !heap->not_leaf( index );
0097 }
0098
0099 static std::pair< size_type, size_type > get_child_nodes( const d_ary_heap* heap, size_type index )
0100 {
0101 BOOST_HEAP_ASSERT( !is_leaf( heap, index ) );
0102 return std::make_pair( d_ary_heap::first_child_index( index ), heap->last_child_index( index ) );
0103 }
0104
0105 static internal_type const& get_internal_value( const d_ary_heap* heap, size_type index )
0106 {
0107 return heap->q_[ index ];
0108 }
0109
0110 static value_type const& get_value( internal_type const& arg )
0111 {
0112 return super_t::get_value( arg );
0113 }
0114 };
0115
0116 typedef detail::ordered_adaptor_iterator< const value_type,
0117 internal_type,
0118 d_ary_heap,
0119 allocator_type,
0120 typename super_t::internal_compare,
0121 ordered_iterator_dispatcher >
0122 ordered_iterator;
0123
0124 typedef detail::stable_heap_iterator< const value_type, container_iterator, super_t > iterator;
0125 typedef iterator const_iterator;
0126 typedef void* handle_type;
0127 };
0128
0129 typedef typename implementation_defined::ordered_iterator_dispatcher ordered_iterator_dispatcher;
0130
0131 public:
0132 typedef T value_type;
0133
0134 typedef typename implementation_defined::size_type size_type;
0135 typedef typename implementation_defined::difference_type difference_type;
0136 typedef typename implementation_defined::value_compare value_compare;
0137 typedef typename implementation_defined::allocator_type allocator_type;
0138 typedef typename implementation_defined::reference reference;
0139 typedef typename implementation_defined::const_reference const_reference;
0140 typedef typename implementation_defined::pointer pointer;
0141 typedef typename implementation_defined::const_pointer const_pointer;
0142 typedef typename implementation_defined::iterator iterator;
0143 typedef typename implementation_defined::const_iterator const_iterator;
0144 typedef typename implementation_defined::ordered_iterator ordered_iterator;
0145 typedef typename implementation_defined::handle_type handle_type;
0146
0147 static const bool is_stable = extract_stable< BoundArgs >::value;
0148
0149 explicit d_ary_heap( value_compare const& cmp = value_compare() ) :
0150 super_t( cmp )
0151 {}
0152
0153 d_ary_heap( d_ary_heap const& rhs ) :
0154 super_t( rhs ),
0155 q_( rhs.q_ )
0156 {}
0157
0158 d_ary_heap( d_ary_heap&& rhs ) :
0159 super_t( std::move( rhs ) ),
0160 q_( std::move( rhs.q_ ) )
0161 {}
0162
0163 d_ary_heap& operator=( d_ary_heap&& rhs )
0164 {
0165 super_t::operator=( std::move( rhs ) );
0166 q_ = std::move( rhs.q_ );
0167 return *this;
0168 }
0169
0170 d_ary_heap& operator=( d_ary_heap const& rhs )
0171 {
0172 static_cast< super_t& >( *this ) = static_cast< super_t const& >( rhs );
0173 q_ = rhs.q_;
0174 return *this;
0175 }
0176
0177 bool empty( void ) const
0178 {
0179 return q_.empty();
0180 }
0181
0182 size_type size( void ) const
0183 {
0184 return q_.size();
0185 }
0186
0187 size_type max_size( void ) const
0188 {
0189 return q_.max_size();
0190 }
0191
0192 void clear( void )
0193 {
0194 q_.clear();
0195 }
0196
0197 allocator_type get_allocator( void ) const
0198 {
0199 return q_.get_allocator();
0200 }
0201
0202 value_type const& top( void ) const
0203 {
0204 BOOST_ASSERT( !empty() );
0205 return super_t::get_value( q_.front() );
0206 }
0207
0208 void push( value_type const& v )
0209 {
0210 q_.push_back( super_t::make_node( v ) );
0211 reset_index( size() - 1, size() - 1 );
0212 siftup( q_.size() - 1 );
0213 }
0214
0215 template < class... Args >
0216 void emplace( Args&&... args )
0217 {
0218 q_.emplace_back( super_t::make_node( std::forward< Args >( args )... ) );
0219 reset_index( size() - 1, size() - 1 );
0220 siftup( q_.size() - 1 );
0221 }
0222
0223 void pop( void )
0224 {
0225 BOOST_ASSERT( !empty() );
0226 std::swap( q_.front(), q_.back() );
0227 q_.pop_back();
0228
0229 if ( q_.empty() )
0230 return;
0231
0232 reset_index( 0, 0 );
0233 siftdown( 0 );
0234 }
0235
0236 void swap( d_ary_heap& rhs )
0237 {
0238 super_t::swap( rhs );
0239 q_.swap( rhs.q_ );
0240 }
0241
0242 iterator begin( void ) const
0243 {
0244 return iterator( q_.begin() );
0245 }
0246
0247 iterator end( void ) const
0248 {
0249 return iterator( q_.end() );
0250 }
0251
0252 ordered_iterator ordered_begin( void ) const
0253 {
0254 return ordered_iterator( 0, this, super_t::get_internal_cmp() );
0255 }
0256
0257 ordered_iterator ordered_end( void ) const
0258 {
0259 return ordered_iterator( size(), this, super_t::get_internal_cmp() );
0260 }
0261
0262 void reserve( size_type element_count )
0263 {
0264 q_.reserve( element_count );
0265 }
0266
0267 value_compare const& value_comp( void ) const
0268 {
0269 return super_t::value_comp();
0270 }
0271
0272 private:
0273 void reset_index( size_type index, size_type new_index )
0274 {
0275 BOOST_HEAP_ASSERT( index < q_.size() );
0276 index_updater::run( q_[ index ], new_index );
0277 }
0278
0279 void siftdown( size_type index )
0280 {
0281 while ( not_leaf( index ) ) {
0282 size_type max_child_index = top_child_index( index );
0283 if ( !super_t::operator()( q_[ max_child_index ], q_[ index ] ) ) {
0284 reset_index( index, max_child_index );
0285 reset_index( max_child_index, index );
0286 std::swap( q_[ max_child_index ], q_[ index ] );
0287 index = max_child_index;
0288 } else
0289 return;
0290 }
0291 }
0292
0293
0294 void siftup( size_type index )
0295 {
0296 while ( index != 0 ) {
0297 size_type parent = parent_index( index );
0298
0299 if ( super_t::operator()( q_[ parent ], q_[ index ] ) ) {
0300 reset_index( index, parent );
0301 reset_index( parent, index );
0302 std::swap( q_[ parent ], q_[ index ] );
0303 index = parent;
0304 } else
0305 return;
0306 }
0307 }
0308
0309 bool not_leaf( size_type index ) const
0310 {
0311 const size_t first_child = first_child_index( index );
0312 return first_child < q_.size();
0313 }
0314
0315 size_type top_child_index( size_type index ) const
0316 {
0317
0318
0319 const size_t first_index = first_child_index( index );
0320 typedef typename container_type::const_iterator container_iterator;
0321
0322 const container_iterator first_child = q_.begin() + first_index;
0323 const container_iterator end = q_.end();
0324
0325 const size_type max_elements = std::distance( first_child, end );
0326
0327 const container_iterator last_child = ( max_elements > D ) ? first_child + D : end;
0328
0329 const container_iterator min_element
0330 = std::max_element( first_child, last_child, static_cast< super_t const& >( *this ) );
0331
0332 return min_element - q_.begin();
0333 }
0334
0335 static size_type parent_index( size_type index )
0336 {
0337 return ( index - 1 ) / D;
0338 }
0339
0340 static size_type first_child_index( size_type index )
0341 {
0342 return index * D + 1;
0343 }
0344
0345 size_type last_child_index( size_type index ) const
0346 {
0347 const size_t first_index = first_child_index( index );
0348 const size_type last_index = ( std::min )( first_index + D - 1, size() - 1 );
0349
0350 return last_index;
0351 }
0352
0353 template < typename U, typename V, typename W, typename X >
0354 struct rebind
0355 {
0356 typedef d_ary_heap< U,
0357 typename d_ary_heap_signature::bind<
0358 boost::heap::stable< heap_base_maker::is_stable >,
0359 boost::heap::stability_counter_type< typename heap_base_maker::stability_counter_type >,
0360 boost::heap::arity< D >,
0361 boost::heap::compare< V >,
0362 boost::heap::allocator< W > >::type,
0363 X >
0364 other;
0365 };
0366
0367 template < class U >
0368 friend class priority_queue_mutable_wrapper;
0369
0370 void update( size_type index )
0371 {
0372 if ( index == 0 ) {
0373 siftdown( index );
0374 return;
0375 }
0376 size_type parent = parent_index( index );
0377
0378 if ( super_t::operator()( q_[ parent ], q_[ index ] ) )
0379 siftup( index );
0380 else
0381 siftdown( index );
0382 }
0383
0384 void erase( size_type index )
0385 {
0386 while ( index != 0 ) {
0387 size_type parent = parent_index( index );
0388
0389 reset_index( index, parent );
0390 reset_index( parent, index );
0391 std::swap( q_[ parent ], q_[ index ] );
0392 index = parent;
0393 }
0394 pop();
0395 }
0396
0397 void increase( size_type index )
0398 {
0399 siftup( index );
0400 }
0401
0402 void decrease( size_type index )
0403 {
0404 siftdown( index );
0405 }
0406 };
0407
0408
0409 template < typename T, typename BoundArgs >
0410 struct select_dary_heap
0411 {
0412 static const bool is_mutable = extract_mutable< BoundArgs >::value;
0413
0414 typedef typename std::conditional< is_mutable,
0415 priority_queue_mutable_wrapper< d_ary_heap< T, BoundArgs, nop_index_updater > >,
0416 d_ary_heap< T, BoundArgs, nop_index_updater > >::type type;
0417 };
0418
0419 }
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441 #ifdef BOOST_DOXYGEN_INVOKED
0442 template < class T, class... Options >
0443 #else
0444 template < typename T,
0445 class A0 = boost::parameter::void_,
0446 class A1 = boost::parameter::void_,
0447 class A2 = boost::parameter::void_,
0448 class A3 = boost::parameter::void_,
0449 class A4 = boost::parameter::void_,
0450 class A5 = boost::parameter::void_ >
0451 #endif
0452 class d_ary_heap :
0453 public detail::select_dary_heap< T, typename detail::d_ary_heap_signature::bind< A0, A1, A2, A3, A4, A5 >::type >::type
0454 {
0455 typedef typename detail::d_ary_heap_signature::bind< A0, A1, A2, A3, A4, A5 >::type bound_args;
0456 typedef typename detail::select_dary_heap< T, bound_args >::type super_t;
0457
0458 template < typename Heap1, typename Heap2 >
0459 friend struct heap_merge_emulate;
0460
0461 #ifndef BOOST_DOXYGEN_INVOKED
0462 static const bool is_mutable = detail::extract_mutable< bound_args >::value;
0463
0464 # define BOOST_HEAP_TYPEDEF_FROM_SUPER_T( NAME ) typedef typename super_t::NAME NAME;
0465
0466 struct implementation_defined
0467 {
0468 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( size_type )
0469 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( difference_type )
0470 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( value_compare )
0471 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( allocator_type )
0472 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( reference )
0473 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( const_reference )
0474 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( pointer )
0475 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( const_pointer )
0476 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( iterator )
0477 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( const_iterator )
0478 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( ordered_iterator )
0479 BOOST_HEAP_TYPEDEF_FROM_SUPER_T( handle_type )
0480 };
0481 # undef BOOST_HEAP_TYPEDEF_FROM_SUPER_T
0482
0483 #endif
0484 public:
0485 static const bool constant_time_size = true;
0486 static const bool has_ordered_iterators = true;
0487 static const bool is_mergable = false;
0488 static const bool has_reserve = true;
0489 static const bool is_stable = super_t::is_stable;
0490
0491 typedef T value_type;
0492 typedef typename implementation_defined::size_type size_type;
0493 typedef typename implementation_defined::difference_type difference_type;
0494 typedef typename implementation_defined::value_compare value_compare;
0495 typedef typename implementation_defined::allocator_type allocator_type;
0496 typedef typename implementation_defined::reference reference;
0497 typedef typename implementation_defined::const_reference const_reference;
0498 typedef typename implementation_defined::pointer pointer;
0499 typedef typename implementation_defined::const_pointer const_pointer;
0500
0501 typedef typename implementation_defined::iterator iterator;
0502 typedef typename implementation_defined::const_iterator const_iterator;
0503 typedef typename implementation_defined::ordered_iterator ordered_iterator;
0504 typedef typename implementation_defined::handle_type handle_type;
0505
0506
0507 explicit d_ary_heap( value_compare const& cmp = value_compare() ) :
0508 super_t( cmp )
0509 {}
0510
0511
0512 d_ary_heap( d_ary_heap const& rhs ) :
0513 super_t( rhs )
0514 {}
0515
0516
0517 d_ary_heap( d_ary_heap&& rhs ) :
0518 super_t( std::move( rhs ) )
0519 {}
0520
0521
0522 d_ary_heap& operator=( d_ary_heap&& rhs )
0523 {
0524 super_t::operator=( std::move( rhs ) );
0525 return *this;
0526 }
0527
0528
0529 d_ary_heap& operator=( d_ary_heap const& rhs )
0530 {
0531 super_t::operator=( rhs );
0532 return *this;
0533 }
0534
0535
0536 bool empty( void ) const
0537 {
0538 return super_t::empty();
0539 }
0540
0541
0542 size_type size( void ) const
0543 {
0544 return super_t::size();
0545 }
0546
0547
0548 size_type max_size( void ) const
0549 {
0550 return super_t::max_size();
0551 }
0552
0553
0554 void clear( void )
0555 {
0556 super_t::clear();
0557 }
0558
0559
0560 allocator_type get_allocator( void ) const
0561 {
0562 return super_t::get_allocator();
0563 }
0564
0565
0566 value_type const& top( void ) const
0567 {
0568 return super_t::top();
0569 }
0570
0571
0572 typename std::conditional< is_mutable, handle_type, void >::type push( value_type const& v )
0573 {
0574 return super_t::push( v );
0575 }
0576
0577
0578 template < class... Args >
0579 typename std::conditional< is_mutable, handle_type, void >::type emplace( Args&&... args )
0580 {
0581 return super_t::emplace( std::forward< Args >( args )... );
0582 }
0583
0584
0585 template < typename HeapType >
0586 bool operator<( HeapType const& rhs ) const
0587 {
0588 return detail::heap_compare( *this, rhs );
0589 }
0590
0591
0592 template < typename HeapType >
0593 bool operator>( HeapType const& rhs ) const
0594 {
0595 return detail::heap_compare( rhs, *this );
0596 }
0597
0598
0599 template < typename HeapType >
0600 bool operator>=( HeapType const& rhs ) const
0601 {
0602 return !operator<( rhs );
0603 }
0604
0605
0606 template < typename HeapType >
0607 bool operator<=( HeapType const& rhs ) const
0608 {
0609 return !operator>( rhs );
0610 }
0611
0612
0613 template < typename HeapType >
0614 bool operator==( HeapType const& rhs ) const
0615 {
0616 return detail::heap_equality( *this, rhs );
0617 }
0618
0619
0620 template < typename HeapType >
0621 bool operator!=( HeapType const& rhs ) const
0622 {
0623 return !( *this == rhs );
0624 }
0625
0626
0627
0628
0629
0630
0631
0632
0633 void update( handle_type handle, const_reference v )
0634 {
0635 BOOST_STATIC_ASSERT( is_mutable );
0636 super_t::update( handle, v );
0637 }
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648 void update( handle_type handle )
0649 {
0650 BOOST_STATIC_ASSERT( is_mutable );
0651 super_t::update( handle );
0652 }
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663 void increase( handle_type handle, const_reference v )
0664 {
0665 BOOST_STATIC_ASSERT( is_mutable );
0666 super_t::increase( handle, v );
0667 }
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679 void increase( handle_type handle )
0680 {
0681 BOOST_STATIC_ASSERT( is_mutable );
0682 super_t::increase( handle );
0683 }
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694 void decrease( handle_type handle, const_reference v )
0695 {
0696 BOOST_STATIC_ASSERT( is_mutable );
0697 super_t::decrease( handle, v );
0698 }
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710 void decrease( handle_type handle )
0711 {
0712 BOOST_STATIC_ASSERT( is_mutable );
0713 super_t::decrease( handle );
0714 }
0715
0716
0717
0718
0719
0720
0721
0722
0723 void erase( handle_type handle )
0724 {
0725 BOOST_STATIC_ASSERT( is_mutable );
0726 super_t::erase( handle );
0727 }
0728
0729
0730
0731
0732
0733
0734
0735
0736 static handle_type s_handle_from_iterator( iterator const& it )
0737 {
0738 BOOST_STATIC_ASSERT( is_mutable );
0739 return super_t::s_handle_from_iterator( it );
0740 }
0741
0742
0743 void pop( void )
0744 {
0745 super_t::pop();
0746 }
0747
0748
0749 void swap( d_ary_heap& rhs )
0750 {
0751 super_t::swap( rhs );
0752 }
0753
0754
0755 const_iterator begin( void ) const
0756 {
0757 return super_t::begin();
0758 }
0759
0760
0761 iterator begin( void )
0762 {
0763 return super_t::begin();
0764 }
0765
0766
0767 iterator end( void )
0768 {
0769 return super_t::end();
0770 }
0771
0772
0773 const_iterator end( void ) const
0774 {
0775 return super_t::end();
0776 }
0777
0778
0779 ordered_iterator ordered_begin( void ) const
0780 {
0781 return super_t::ordered_begin();
0782 }
0783
0784
0785 ordered_iterator ordered_end( void ) const
0786 {
0787 return super_t::ordered_end();
0788 }
0789
0790
0791 void reserve( size_type element_count )
0792 {
0793 super_t::reserve( element_count );
0794 }
0795
0796
0797 value_compare const& value_comp( void ) const
0798 {
0799 return super_t::value_comp();
0800 }
0801 };
0802
0803 }}
0804
0805 #undef BOOST_HEAP_ASSERT
0806
0807 #endif