| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- // boost heap: heap merge algorithms
- //
- // Copyright (C) 2011 Tim Blechmann
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_HEAP_MERGE_HPP
- #define BOOST_HEAP_MERGE_HPP
- #include <algorithm>
- #include <type_traits>
- #include <boost/concept/assert.hpp>
- #include <boost/heap/heap_concepts.hpp>
- #ifdef BOOST_HAS_PRAGMA_ONCE
- # pragma once
- #endif
- namespace boost { namespace heap {
- namespace detail {
- template < typename Heap1, typename Heap2 >
- struct heap_merge_emulate
- {
- struct dummy_reserver
- {
- static void reserve( Heap1& /*lhs*/, std::size_t /*required_size*/ )
- {}
- };
- struct reserver
- {
- static void reserve( Heap1& lhs, std::size_t required_size )
- {
- lhs.reserve( required_size );
- }
- };
- typedef typename std::conditional< Heap1::has_reserve, reserver, dummy_reserver >::type space_reserver;
- static void merge( Heap1& lhs, Heap2& rhs )
- {
- if ( Heap1::constant_time_size && Heap2::constant_time_size ) {
- if ( Heap1::has_reserve ) {
- std::size_t required_size = lhs.size() + rhs.size();
- space_reserver::reserve( lhs, required_size );
- }
- }
- // FIXME: container adaptors could benefit from first appending all elements and then restoring the heap order
- // FIXME: optimize: if we have ordered iterators and we can efficiently insert keys with a below the lowest key
- // in the heap
- // d-ary, b and fibonacci heaps fall into this category
- while ( !rhs.empty() ) {
- lhs.push( rhs.top() );
- rhs.pop();
- }
- lhs.set_stability_count( ( std::max )( lhs.get_stability_count(), rhs.get_stability_count() ) );
- rhs.set_stability_count( 0 );
- }
- };
- template < typename Heap >
- struct heap_merge_same_mergable
- {
- static void merge( Heap& lhs, Heap& rhs )
- {
- lhs.merge( rhs );
- }
- };
- template < typename Heap >
- struct heap_merge_same
- {
- static const bool is_mergable = Heap::is_mergable;
- typedef
- typename std::conditional< is_mergable, heap_merge_same_mergable< Heap >, heap_merge_emulate< Heap, Heap > >::type
- heap_merger;
- static void merge( Heap& lhs, Heap& rhs )
- {
- heap_merger::merge( lhs, rhs );
- }
- };
- } /* namespace detail */
- /** merge rhs into lhs
- *
- * \b Effect: lhs contains all elements that have been part of rhs, rhs is empty.
- *
- * */
- template < typename Heap1, typename Heap2 >
- void heap_merge( Heap1& lhs, Heap2& rhs )
- {
- BOOST_CONCEPT_ASSERT( (boost::heap::PriorityQueue< Heap1 >));
- BOOST_CONCEPT_ASSERT( (boost::heap::PriorityQueue< Heap2 >));
- // if this assertion is triggered, the value_compare types are incompatible
- BOOST_STATIC_ASSERT( ( std::is_same< typename Heap1::value_compare, typename Heap2::value_compare >::value ) );
- const bool same_heaps = std::is_same< Heap1, Heap2 >::value;
- typedef typename std::conditional< same_heaps,
- detail::heap_merge_same< Heap1 >,
- detail::heap_merge_emulate< Heap1, Heap2 > >::type heap_merger;
- heap_merger::merge( lhs, rhs );
- }
- }} // namespace boost::heap
- #endif /* BOOST_HEAP_MERGE_HPP */
|