Chris@16
|
1 // boost heap: heap merge algorithms
|
Chris@16
|
2 //
|
Chris@16
|
3 // Copyright (C) 2011 Tim Blechmann
|
Chris@16
|
4 //
|
Chris@16
|
5 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
6 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8
|
Chris@16
|
9 #ifndef BOOST_HEAP_MERGE_HPP
|
Chris@16
|
10 #define BOOST_HEAP_MERGE_HPP
|
Chris@16
|
11
|
Chris@16
|
12 #include <boost/concept/assert.hpp>
|
Chris@16
|
13 #include <boost/heap/heap_concepts.hpp>
|
Chris@16
|
14 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
15
|
Chris@101
|
16 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@101
|
17 #pragma once
|
Chris@101
|
18 #endif
|
Chris@101
|
19
|
Chris@101
|
20
|
Chris@16
|
21 namespace boost {
|
Chris@16
|
22 namespace heap {
|
Chris@16
|
23 namespace detail {
|
Chris@16
|
24
|
Chris@16
|
25 template <typename Heap1, typename Heap2>
|
Chris@16
|
26 struct heap_merge_emulate
|
Chris@16
|
27 {
|
Chris@16
|
28 struct dummy_reserver
|
Chris@16
|
29 {
|
Chris@16
|
30 static void reserve (Heap1 & lhs, std::size_t required_size)
|
Chris@16
|
31 {}
|
Chris@16
|
32 };
|
Chris@16
|
33
|
Chris@16
|
34 struct reserver
|
Chris@16
|
35 {
|
Chris@16
|
36 static void reserve (Heap1 & lhs, std::size_t required_size)
|
Chris@16
|
37 {
|
Chris@16
|
38 lhs.reserve(required_size);
|
Chris@16
|
39 }
|
Chris@16
|
40 };
|
Chris@16
|
41
|
Chris@16
|
42 typedef typename boost::mpl::if_c<Heap1::has_reserve,
|
Chris@16
|
43 reserver,
|
Chris@16
|
44 dummy_reserver>::type space_reserver;
|
Chris@16
|
45
|
Chris@16
|
46 static void merge(Heap1 & lhs, Heap2 & rhs)
|
Chris@16
|
47 {
|
Chris@16
|
48 if (Heap1::constant_time_size && Heap2::constant_time_size) {
|
Chris@16
|
49 if (Heap1::has_reserve) {
|
Chris@16
|
50 std::size_t required_size = lhs.size() + rhs.size();
|
Chris@16
|
51 space_reserver::reserve(lhs, required_size);
|
Chris@16
|
52 }
|
Chris@16
|
53 }
|
Chris@16
|
54
|
Chris@16
|
55 // FIXME: container adaptors could benefit from first appending all elements and then restoring the heap order
|
Chris@16
|
56 // FIXME: optimize: if we have ordered iterators and we can efficiently insert keys with a below the lowest key in the heap
|
Chris@16
|
57 // d-ary, b and fibonacci heaps fall into this category
|
Chris@16
|
58
|
Chris@16
|
59 while (!rhs.empty()) {
|
Chris@16
|
60 lhs.push(rhs.top());
|
Chris@16
|
61 rhs.pop();
|
Chris@16
|
62 }
|
Chris@16
|
63
|
Chris@16
|
64 lhs.set_stability_count((std::max)(lhs.get_stability_count(),
|
Chris@16
|
65 rhs.get_stability_count()));
|
Chris@16
|
66 rhs.set_stability_count(0);
|
Chris@16
|
67 }
|
Chris@16
|
68
|
Chris@16
|
69 };
|
Chris@16
|
70
|
Chris@16
|
71
|
Chris@16
|
72 template <typename Heap>
|
Chris@16
|
73 struct heap_merge_same_mergable
|
Chris@16
|
74 {
|
Chris@16
|
75 static void merge(Heap & lhs, Heap & rhs)
|
Chris@16
|
76 {
|
Chris@16
|
77 lhs.merge(rhs);
|
Chris@16
|
78 }
|
Chris@16
|
79 };
|
Chris@16
|
80
|
Chris@16
|
81
|
Chris@16
|
82 template <typename Heap>
|
Chris@16
|
83 struct heap_merge_same
|
Chris@16
|
84 {
|
Chris@16
|
85 static const bool is_mergable = Heap::is_mergable;
|
Chris@16
|
86 typedef typename boost::mpl::if_c<is_mergable,
|
Chris@16
|
87 heap_merge_same_mergable<Heap>,
|
Chris@16
|
88 heap_merge_emulate<Heap, Heap>
|
Chris@16
|
89 >::type heap_merger;
|
Chris@16
|
90
|
Chris@16
|
91 static void merge(Heap & lhs, Heap & rhs)
|
Chris@16
|
92 {
|
Chris@16
|
93 heap_merger::merge(lhs, rhs);
|
Chris@16
|
94 }
|
Chris@16
|
95 };
|
Chris@16
|
96
|
Chris@16
|
97 } /* namespace detail */
|
Chris@16
|
98
|
Chris@16
|
99
|
Chris@16
|
100 /** merge rhs into lhs
|
Chris@16
|
101 *
|
Chris@16
|
102 * \b Effect: lhs contains all elements that have been part of rhs, rhs is empty.
|
Chris@16
|
103 *
|
Chris@16
|
104 * */
|
Chris@16
|
105 template <typename Heap1,
|
Chris@16
|
106 typename Heap2
|
Chris@16
|
107 >
|
Chris@16
|
108 void heap_merge(Heap1 & lhs, Heap2 & rhs)
|
Chris@16
|
109 {
|
Chris@16
|
110 BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap1>));
|
Chris@16
|
111 BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap2>));
|
Chris@16
|
112
|
Chris@16
|
113 // if this assertion is triggered, the value_compare types are incompatible
|
Chris@16
|
114 BOOST_STATIC_ASSERT((boost::is_same<typename Heap1::value_compare, typename Heap2::value_compare>::value));
|
Chris@16
|
115
|
Chris@16
|
116 const bool same_heaps = boost::is_same<Heap1, Heap2>::value;
|
Chris@16
|
117
|
Chris@16
|
118 typedef typename boost::mpl::if_c<same_heaps,
|
Chris@16
|
119 detail::heap_merge_same<Heap1>,
|
Chris@16
|
120 detail::heap_merge_emulate<Heap1, Heap2>
|
Chris@16
|
121 >::type heap_merger;
|
Chris@16
|
122
|
Chris@16
|
123 heap_merger::merge(lhs, rhs);
|
Chris@16
|
124 }
|
Chris@16
|
125
|
Chris@16
|
126
|
Chris@16
|
127 } /* namespace heap */
|
Chris@16
|
128 } /* namespace boost */
|
Chris@16
|
129
|
Chris@16
|
130 #endif /* BOOST_HEAP_MERGE_HPP */
|