mutable_heap.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. // boost 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_DETAIL_MUTABLE_HEAP_HPP
  9. #define BOOST_HEAP_DETAIL_MUTABLE_HEAP_HPP
  10. /*! \file
  11. * INTERNAL ONLY
  12. */
  13. #include <list>
  14. #include <utility>
  15. #include <boost/heap/detail/ordered_adaptor_iterator.hpp>
  16. #include <boost/iterator/iterator_adaptor.hpp>
  17. namespace boost { namespace heap { namespace detail {
  18. /* wrapper for a mutable heap container adaptors
  19. *
  20. * this wrapper introduces an additional indirection. the heap is not constructed from objects,
  21. * but instead from std::list iterators. this way, the mutability is achieved
  22. *
  23. */
  24. template < typename PriorityQueueType >
  25. class priority_queue_mutable_wrapper
  26. {
  27. public:
  28. typedef typename PriorityQueueType::value_type value_type;
  29. typedef typename PriorityQueueType::size_type size_type;
  30. typedef typename PriorityQueueType::value_compare value_compare;
  31. typedef typename PriorityQueueType::allocator_type allocator_type;
  32. typedef typename PriorityQueueType::reference reference;
  33. typedef typename PriorityQueueType::const_reference const_reference;
  34. typedef typename PriorityQueueType::pointer pointer;
  35. typedef typename PriorityQueueType::const_pointer const_pointer;
  36. static const bool is_stable = PriorityQueueType::is_stable;
  37. private:
  38. typedef std::pair< value_type, size_type > node_type;
  39. typedef std::list< node_type, typename boost::allocator_rebind< allocator_type, node_type >::type > object_list;
  40. typedef typename object_list::iterator list_iterator;
  41. typedef typename object_list::const_iterator const_list_iterator;
  42. template < typename Heap1, typename Heap2 >
  43. friend struct heap_merge_emulate;
  44. typedef typename PriorityQueueType::super_t::stability_counter_type stability_counter_type;
  45. stability_counter_type get_stability_count( void ) const
  46. {
  47. return q_.get_stability_count();
  48. }
  49. void set_stability_count( stability_counter_type new_count )
  50. {
  51. q_.set_stability_count( new_count );
  52. }
  53. struct index_updater
  54. {
  55. template < typename It >
  56. static void run( It& it, size_type new_index )
  57. {
  58. q_type::get_value( it )->second = new_index;
  59. }
  60. };
  61. public:
  62. struct handle_type
  63. {
  64. value_type& operator*() const
  65. {
  66. return iterator->first;
  67. }
  68. handle_type( void )
  69. {}
  70. handle_type( handle_type const& rhs ) :
  71. iterator( rhs.iterator )
  72. {}
  73. handle_type& operator=( handle_type const& rhs )
  74. {
  75. iterator = rhs.iterator;
  76. return *this;
  77. }
  78. bool operator==( handle_type const& rhs ) const
  79. {
  80. return iterator == rhs.iterator;
  81. }
  82. bool operator!=( handle_type const& rhs ) const
  83. {
  84. return iterator != rhs.iterator;
  85. }
  86. private:
  87. explicit handle_type( list_iterator const& it ) :
  88. iterator( it )
  89. {}
  90. list_iterator iterator;
  91. friend class priority_queue_mutable_wrapper;
  92. };
  93. private:
  94. struct indirect_cmp : public value_compare
  95. {
  96. indirect_cmp( value_compare const& cmp = value_compare() ) :
  97. value_compare( cmp )
  98. {}
  99. bool operator()( const_list_iterator const& lhs, const_list_iterator const& rhs ) const
  100. {
  101. return value_compare::operator()( lhs->first, rhs->first );
  102. }
  103. };
  104. typedef
  105. typename PriorityQueueType::template rebind< list_iterator, indirect_cmp, allocator_type, index_updater >::other
  106. q_type;
  107. protected:
  108. q_type q_;
  109. object_list objects;
  110. protected:
  111. priority_queue_mutable_wrapper( value_compare const& cmp = value_compare() ) :
  112. q_( cmp )
  113. {}
  114. priority_queue_mutable_wrapper( priority_queue_mutable_wrapper const& rhs ) :
  115. q_( rhs.q_ ),
  116. objects( rhs.objects )
  117. {
  118. for ( typename object_list::iterator it = objects.begin(); it != objects.end(); ++it )
  119. q_.push( it );
  120. }
  121. priority_queue_mutable_wrapper& operator=( priority_queue_mutable_wrapper const& rhs )
  122. {
  123. q_ = rhs.q_;
  124. objects = rhs.objects;
  125. q_.clear();
  126. for ( typename object_list::iterator it = objects.begin(); it != objects.end(); ++it )
  127. q_.push( it );
  128. return *this;
  129. }
  130. priority_queue_mutable_wrapper( priority_queue_mutable_wrapper&& rhs ) :
  131. q_( std::move( rhs.q_ ) )
  132. {
  133. /// FIXME: msvc seems to invalidate iterators when moving std::list
  134. std::swap( objects, rhs.objects );
  135. }
  136. priority_queue_mutable_wrapper& operator=( priority_queue_mutable_wrapper&& rhs )
  137. {
  138. q_ = std::move( rhs.q_ );
  139. objects.clear();
  140. std::swap( objects, rhs.objects );
  141. return *this;
  142. }
  143. public:
  144. template < typename iterator_type >
  145. class iterator_base :
  146. public boost::iterator_adaptor< iterator_base< iterator_type >,
  147. iterator_type,
  148. value_type const,
  149. boost::bidirectional_traversal_tag >
  150. {
  151. typedef boost::iterator_adaptor< iterator_base< iterator_type >,
  152. iterator_type,
  153. value_type const,
  154. boost::bidirectional_traversal_tag >
  155. super_t;
  156. friend class boost::iterator_core_access;
  157. friend class priority_queue_mutable_wrapper;
  158. iterator_base( void ) :
  159. super_t( 0 )
  160. {}
  161. template < typename T >
  162. explicit iterator_base( T const& it ) :
  163. super_t( it )
  164. {}
  165. value_type const& dereference() const
  166. {
  167. return super_t::base()->first;
  168. }
  169. iterator_type get_list_iterator() const
  170. {
  171. return super_t::base_reference();
  172. }
  173. };
  174. typedef iterator_base< list_iterator > iterator;
  175. typedef iterator_base< const_list_iterator > const_iterator;
  176. typedef typename object_list::difference_type difference_type;
  177. class ordered_iterator :
  178. public boost::iterator_adaptor< ordered_iterator, const_list_iterator, value_type const, boost::forward_traversal_tag >,
  179. q_type::ordered_iterator_dispatcher
  180. {
  181. typedef boost::iterator_adaptor< ordered_iterator, const_list_iterator, value_type const, boost::forward_traversal_tag >
  182. adaptor_type;
  183. typedef const_list_iterator iterator;
  184. typedef typename q_type::ordered_iterator_dispatcher ordered_iterator_dispatcher;
  185. friend class boost::iterator_core_access;
  186. public:
  187. ordered_iterator( void ) :
  188. adaptor_type( 0 ),
  189. unvisited_nodes( indirect_cmp() ),
  190. q_( nullptr )
  191. {}
  192. ordered_iterator( const priority_queue_mutable_wrapper* q, indirect_cmp const& cmp ) :
  193. adaptor_type( 0 ),
  194. unvisited_nodes( cmp ),
  195. q_( q )
  196. {}
  197. ordered_iterator( const_list_iterator it, const priority_queue_mutable_wrapper* q, indirect_cmp const& cmp ) :
  198. adaptor_type( it ),
  199. unvisited_nodes( cmp ),
  200. q_( q )
  201. {
  202. if ( it != q->objects.end() )
  203. discover_nodes( it );
  204. }
  205. bool operator!=( ordered_iterator const& rhs ) const
  206. {
  207. return adaptor_type::base() != rhs.base();
  208. }
  209. bool operator==( ordered_iterator const& rhs ) const
  210. {
  211. return !operator!=( rhs );
  212. }
  213. private:
  214. void increment( void )
  215. {
  216. if ( unvisited_nodes.empty() )
  217. adaptor_type::base_reference() = q_->objects.end();
  218. else {
  219. iterator next = unvisited_nodes.top();
  220. unvisited_nodes.pop();
  221. discover_nodes( next );
  222. adaptor_type::base_reference() = next;
  223. }
  224. }
  225. value_type const& dereference() const
  226. {
  227. return adaptor_type::base()->first;
  228. }
  229. void discover_nodes( iterator current )
  230. {
  231. size_type current_index = current->second;
  232. const q_type* q = &( q_->q_ );
  233. if ( ordered_iterator_dispatcher::is_leaf( q, current_index ) )
  234. return;
  235. std::pair< size_type, size_type > child_range
  236. = ordered_iterator_dispatcher::get_child_nodes( q, current_index );
  237. for ( size_type i = child_range.first; i <= child_range.second; ++i ) {
  238. typename q_type::internal_type const& internal_value_at_index
  239. = ordered_iterator_dispatcher::get_internal_value( q, i );
  240. typename q_type::value_type const& value_at_index = q_->q_.get_value( internal_value_at_index );
  241. unvisited_nodes.push( value_at_index );
  242. }
  243. }
  244. std::priority_queue< iterator,
  245. std::vector< iterator, typename boost::allocator_rebind< allocator_type, iterator >::type >,
  246. indirect_cmp >
  247. unvisited_nodes;
  248. const priority_queue_mutable_wrapper* q_;
  249. };
  250. bool empty( void ) const
  251. {
  252. return q_.empty();
  253. }
  254. size_type size( void ) const
  255. {
  256. return q_.size();
  257. }
  258. size_type max_size( void ) const
  259. {
  260. return objects.max_size();
  261. }
  262. void clear( void )
  263. {
  264. q_.clear();
  265. objects.clear();
  266. }
  267. allocator_type get_allocator( void ) const
  268. {
  269. return q_.get_allocator();
  270. }
  271. void swap( priority_queue_mutable_wrapper& rhs )
  272. {
  273. objects.swap( rhs.objects );
  274. q_.swap( rhs.q_ );
  275. }
  276. const_reference top( void ) const
  277. {
  278. BOOST_ASSERT( !empty() );
  279. return q_.top()->first;
  280. }
  281. handle_type push( value_type const& v )
  282. {
  283. objects.push_front( std::make_pair( v, 0 ) );
  284. list_iterator ret = objects.begin();
  285. q_.push( ret );
  286. return handle_type( ret );
  287. }
  288. template < class... Args >
  289. handle_type emplace( Args&&... args )
  290. {
  291. objects.push_front( std::make_pair( std::forward< Args >( args )..., 0 ) );
  292. list_iterator ret = objects.begin();
  293. q_.push( ret );
  294. return handle_type( ret );
  295. }
  296. void pop( void )
  297. {
  298. BOOST_ASSERT( !empty() );
  299. list_iterator q_top = q_.top();
  300. q_.pop();
  301. objects.erase( q_top );
  302. }
  303. /**
  304. * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
  305. *
  306. * \b Complexity: Logarithmic.
  307. *
  308. * */
  309. void update( handle_type handle, const_reference v )
  310. {
  311. list_iterator it = handle.iterator;
  312. value_type const& current_value = it->first;
  313. value_compare const& cmp = q_.value_comp();
  314. if ( cmp( v, current_value ) )
  315. decrease( handle, v );
  316. else
  317. increase( handle, v );
  318. }
  319. /**
  320. * \b Effects: Updates the heap after the element handled by \c handle has been changed.
  321. *
  322. * \b Complexity: Logarithmic.
  323. *
  324. * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
  325. * */
  326. void update( handle_type handle )
  327. {
  328. list_iterator it = handle.iterator;
  329. size_type index = it->second;
  330. q_.update( index );
  331. }
  332. /**
  333. * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
  334. *
  335. * \b Complexity: Logarithmic.
  336. *
  337. * \b Note: The new value is expected to be greater than the current one
  338. * */
  339. void increase( handle_type handle, const_reference v )
  340. {
  341. BOOST_ASSERT( !value_comp()( v, handle.iterator->first ) );
  342. handle.iterator->first = v;
  343. increase( handle );
  344. }
  345. /**
  346. * \b Effects: Updates the heap after the element handled by \c handle has been changed.
  347. *
  348. * \b Complexity: Logarithmic.
  349. *
  350. * \b Note: The new value is expected to be greater than the current one. If this is not called, after a handle has
  351. * been updated, the behavior of the data structure is undefined!
  352. * */
  353. void increase( handle_type handle )
  354. {
  355. list_iterator it = handle.iterator;
  356. size_type index = it->second;
  357. q_.increase( index );
  358. }
  359. /**
  360. * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
  361. *
  362. * \b Complexity: Logarithmic.
  363. *
  364. * \b Note: The new value is expected to be less than the current one
  365. * */
  366. void decrease( handle_type handle, const_reference v )
  367. {
  368. BOOST_ASSERT( !value_comp()( handle.iterator->first, v ) );
  369. handle.iterator->first = v;
  370. decrease( handle );
  371. }
  372. /**
  373. * \b Effects: Updates the heap after the element handled by \c handle has been changed.
  374. *
  375. * \b Complexity: Logarithmic.
  376. *
  377. * \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has
  378. * been updated, the behavior of the data structure is undefined!
  379. * */
  380. void decrease( handle_type handle )
  381. {
  382. list_iterator it = handle.iterator;
  383. size_type index = it->second;
  384. q_.decrease( index );
  385. }
  386. /**
  387. * \b Effects: Removes the element handled by \c handle from the priority_queue.
  388. *
  389. * \b Complexity: Logarithmic.
  390. * */
  391. void erase( handle_type handle )
  392. {
  393. list_iterator it = handle.iterator;
  394. size_type index = it->second;
  395. q_.erase( index );
  396. objects.erase( it );
  397. }
  398. const_iterator begin( void ) const
  399. {
  400. return const_iterator( objects.begin() );
  401. }
  402. const_iterator end( void ) const
  403. {
  404. return const_iterator( objects.end() );
  405. }
  406. iterator begin( void )
  407. {
  408. return iterator( objects.begin() );
  409. }
  410. iterator end( void )
  411. {
  412. return iterator( objects.end() );
  413. }
  414. ordered_iterator ordered_begin( void ) const
  415. {
  416. if ( !empty() )
  417. return ordered_iterator( q_.top(), this, indirect_cmp( q_.value_comp() ) );
  418. else
  419. return ordered_end();
  420. }
  421. ordered_iterator ordered_end( void ) const
  422. {
  423. return ordered_iterator( objects.end(), this, indirect_cmp( q_.value_comp() ) );
  424. }
  425. static handle_type s_handle_from_iterator( iterator const& it )
  426. {
  427. return handle_type( it.get_list_iterator() );
  428. }
  429. value_compare const& value_comp( void ) const
  430. {
  431. return q_.value_comp();
  432. }
  433. void reserve( size_type element_count )
  434. {
  435. q_.reserve( element_count );
  436. }
  437. };
  438. }}} // namespace boost::heap::detail
  439. #endif /* BOOST_HEAP_DETAIL_MUTABLE_HEAP_HPP */