Chris@16
|
1 // // boost heap: d-ary heap as containter adaptor
|
Chris@16
|
2 //
|
Chris@16
|
3 // Copyright (C) 2010 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_D_ARY_HEAP_HPP
|
Chris@16
|
10 #define BOOST_HEAP_D_ARY_HEAP_HPP
|
Chris@16
|
11
|
Chris@16
|
12 #include <algorithm>
|
Chris@16
|
13 #include <utility>
|
Chris@16
|
14 #include <vector>
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/assert.hpp>
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/mem_fn.hpp>
|
Chris@16
|
19 #include <boost/heap/detail/heap_comparison.hpp>
|
Chris@16
|
20 #include <boost/heap/detail/ordered_adaptor_iterator.hpp>
|
Chris@16
|
21 #include <boost/heap/detail/stable_heap.hpp>
|
Chris@16
|
22 #include <boost/heap/detail/mutable_heap.hpp>
|
Chris@16
|
23
|
Chris@101
|
24 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@101
|
25 #pragma once
|
Chris@101
|
26 #endif
|
Chris@101
|
27
|
Chris@101
|
28
|
Chris@16
|
29 #ifndef BOOST_DOXYGEN_INVOKED
|
Chris@16
|
30 #ifdef BOOST_HEAP_SANITYCHECKS
|
Chris@16
|
31 #define BOOST_HEAP_ASSERT BOOST_ASSERT
|
Chris@16
|
32 #else
|
Chris@16
|
33 #define BOOST_HEAP_ASSERT(expression)
|
Chris@16
|
34 #endif
|
Chris@16
|
35 #endif
|
Chris@16
|
36
|
Chris@16
|
37 namespace boost {
|
Chris@16
|
38 namespace heap {
|
Chris@16
|
39 namespace detail {
|
Chris@16
|
40
|
Chris@16
|
41 struct nop_index_updater
|
Chris@16
|
42 {
|
Chris@16
|
43 template <typename T>
|
Chris@16
|
44 static void run(T &, std::size_t)
|
Chris@16
|
45 {}
|
Chris@16
|
46 };
|
Chris@16
|
47
|
Chris@16
|
48 typedef parameter::parameters<boost::parameter::required<tag::arity>,
|
Chris@16
|
49 boost::parameter::optional<tag::allocator>,
|
Chris@16
|
50 boost::parameter::optional<tag::compare>,
|
Chris@16
|
51 boost::parameter::optional<tag::stable>,
|
Chris@16
|
52 boost::parameter::optional<tag::stability_counter_type>,
|
Chris@16
|
53 boost::parameter::optional<tag::constant_time_size>
|
Chris@16
|
54 > d_ary_heap_signature;
|
Chris@16
|
55
|
Chris@16
|
56
|
Chris@16
|
57 /* base class for d-ary heap */
|
Chris@16
|
58 template <typename T,
|
Chris@16
|
59 class BoundArgs,
|
Chris@16
|
60 class IndexUpdater>
|
Chris@16
|
61 class d_ary_heap:
|
Chris@16
|
62 private make_heap_base<T, BoundArgs, false>::type
|
Chris@16
|
63 {
|
Chris@16
|
64 typedef make_heap_base<T, BoundArgs, false> heap_base_maker;
|
Chris@16
|
65
|
Chris@16
|
66 typedef typename heap_base_maker::type super_t;
|
Chris@16
|
67 typedef typename super_t::internal_type internal_type;
|
Chris@16
|
68
|
Chris@16
|
69 typedef typename heap_base_maker::allocator_argument::template rebind<internal_type>::other internal_type_allocator;
|
Chris@16
|
70 typedef std::vector<internal_type, internal_type_allocator> container_type;
|
Chris@16
|
71 typedef typename container_type::const_iterator container_iterator;
|
Chris@16
|
72
|
Chris@16
|
73 typedef IndexUpdater index_updater;
|
Chris@16
|
74
|
Chris@16
|
75 container_type q_;
|
Chris@16
|
76
|
Chris@16
|
77 static const unsigned int D = parameter::binding<BoundArgs, tag::arity>::type::value;
|
Chris@16
|
78
|
Chris@16
|
79 template <typename Heap1, typename Heap2>
|
Chris@16
|
80 friend struct heap_merge_emulate;
|
Chris@16
|
81
|
Chris@16
|
82 struct implementation_defined:
|
Chris@16
|
83 extract_allocator_types<typename heap_base_maker::allocator_argument>
|
Chris@16
|
84 {
|
Chris@16
|
85 typedef T value_type;
|
Chris@16
|
86 typedef typename detail::extract_allocator_types<typename heap_base_maker::allocator_argument>::size_type size_type;
|
Chris@16
|
87
|
Chris@16
|
88 typedef typename heap_base_maker::compare_argument value_compare;
|
Chris@16
|
89 typedef typename heap_base_maker::allocator_argument allocator_type;
|
Chris@16
|
90
|
Chris@16
|
91 struct ordered_iterator_dispatcher
|
Chris@16
|
92 {
|
Chris@16
|
93 static size_type max_index(const d_ary_heap * heap)
|
Chris@16
|
94 {
|
Chris@16
|
95 return heap->q_.size() - 1;
|
Chris@16
|
96 }
|
Chris@16
|
97
|
Chris@16
|
98 static bool is_leaf(const d_ary_heap * heap, size_type index)
|
Chris@16
|
99 {
|
Chris@16
|
100 return !heap->not_leaf(index);
|
Chris@16
|
101 }
|
Chris@16
|
102
|
Chris@16
|
103 static std::pair<size_type, size_type> get_child_nodes(const d_ary_heap * heap, size_type index)
|
Chris@16
|
104 {
|
Chris@16
|
105 BOOST_HEAP_ASSERT(!is_leaf(heap, index));
|
Chris@16
|
106 return std::make_pair(d_ary_heap::first_child_index(index),
|
Chris@16
|
107 heap->last_child_index(index));
|
Chris@16
|
108 }
|
Chris@16
|
109
|
Chris@16
|
110 static internal_type const & get_internal_value(const d_ary_heap * heap, size_type index)
|
Chris@16
|
111 {
|
Chris@16
|
112 return heap->q_[index];
|
Chris@16
|
113 }
|
Chris@16
|
114
|
Chris@16
|
115 static value_type const & get_value(internal_type const & arg)
|
Chris@16
|
116 {
|
Chris@16
|
117 return super_t::get_value(arg);
|
Chris@16
|
118 }
|
Chris@16
|
119 };
|
Chris@16
|
120
|
Chris@16
|
121 typedef detail::ordered_adaptor_iterator<const value_type,
|
Chris@16
|
122 internal_type,
|
Chris@16
|
123 d_ary_heap,
|
Chris@16
|
124 allocator_type,
|
Chris@16
|
125 typename super_t::internal_compare,
|
Chris@16
|
126 ordered_iterator_dispatcher
|
Chris@16
|
127 > ordered_iterator;
|
Chris@16
|
128
|
Chris@16
|
129 typedef detail::stable_heap_iterator<const value_type, container_iterator, super_t> iterator;
|
Chris@16
|
130 typedef iterator const_iterator;
|
Chris@16
|
131 typedef void * handle_type;
|
Chris@16
|
132
|
Chris@16
|
133 };
|
Chris@16
|
134
|
Chris@16
|
135 typedef typename implementation_defined::ordered_iterator_dispatcher ordered_iterator_dispatcher;
|
Chris@16
|
136
|
Chris@16
|
137 public:
|
Chris@16
|
138 typedef T value_type;
|
Chris@16
|
139
|
Chris@16
|
140 typedef typename implementation_defined::size_type size_type;
|
Chris@16
|
141 typedef typename implementation_defined::difference_type difference_type;
|
Chris@16
|
142 typedef typename implementation_defined::value_compare value_compare;
|
Chris@16
|
143 typedef typename implementation_defined::allocator_type allocator_type;
|
Chris@16
|
144 typedef typename implementation_defined::reference reference;
|
Chris@16
|
145 typedef typename implementation_defined::const_reference const_reference;
|
Chris@16
|
146 typedef typename implementation_defined::pointer pointer;
|
Chris@16
|
147 typedef typename implementation_defined::const_pointer const_pointer;
|
Chris@16
|
148 typedef typename implementation_defined::iterator iterator;
|
Chris@16
|
149 typedef typename implementation_defined::const_iterator const_iterator;
|
Chris@16
|
150 typedef typename implementation_defined::ordered_iterator ordered_iterator;
|
Chris@16
|
151 typedef typename implementation_defined::handle_type handle_type;
|
Chris@16
|
152
|
Chris@16
|
153 static const bool is_stable = extract_stable<BoundArgs>::value;
|
Chris@16
|
154
|
Chris@16
|
155 explicit d_ary_heap(value_compare const & cmp = value_compare()):
|
Chris@16
|
156 super_t(cmp)
|
Chris@16
|
157 {}
|
Chris@16
|
158
|
Chris@16
|
159 d_ary_heap(d_ary_heap const & rhs):
|
Chris@16
|
160 super_t(rhs), q_(rhs.q_)
|
Chris@16
|
161 {}
|
Chris@16
|
162
|
Chris@16
|
163 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
164 d_ary_heap(d_ary_heap && rhs):
|
Chris@16
|
165 super_t(std::move(rhs)), q_(std::move(rhs.q_))
|
Chris@16
|
166 {}
|
Chris@16
|
167
|
Chris@16
|
168 d_ary_heap & operator=(d_ary_heap && rhs)
|
Chris@16
|
169 {
|
Chris@16
|
170 super_t::operator=(std::move(rhs));
|
Chris@16
|
171 q_ = std::move(rhs.q_);
|
Chris@16
|
172 return *this;
|
Chris@16
|
173 }
|
Chris@16
|
174 #endif
|
Chris@16
|
175
|
Chris@16
|
176 d_ary_heap & operator=(d_ary_heap const & rhs)
|
Chris@16
|
177 {
|
Chris@16
|
178 static_cast<super_t&>(*this) = static_cast<super_t const &>(rhs);
|
Chris@16
|
179 q_ = rhs.q_;
|
Chris@16
|
180 return *this;
|
Chris@16
|
181 }
|
Chris@16
|
182
|
Chris@16
|
183 bool empty(void) const
|
Chris@16
|
184 {
|
Chris@16
|
185 return q_.empty();
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@16
|
188 size_type size(void) const
|
Chris@16
|
189 {
|
Chris@16
|
190 return q_.size();
|
Chris@16
|
191 }
|
Chris@16
|
192
|
Chris@16
|
193 size_type max_size(void) const
|
Chris@16
|
194 {
|
Chris@16
|
195 return q_.max_size();
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198 void clear(void)
|
Chris@16
|
199 {
|
Chris@16
|
200 q_.clear();
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 allocator_type get_allocator(void) const
|
Chris@16
|
204 {
|
Chris@16
|
205 return q_.get_allocator();
|
Chris@16
|
206 }
|
Chris@16
|
207
|
Chris@16
|
208 value_type const & top(void) const
|
Chris@16
|
209 {
|
Chris@16
|
210 BOOST_ASSERT(!empty());
|
Chris@16
|
211 return super_t::get_value(q_.front());
|
Chris@16
|
212 }
|
Chris@16
|
213
|
Chris@16
|
214 void push(value_type const & v)
|
Chris@16
|
215 {
|
Chris@16
|
216 q_.push_back(super_t::make_node(v));
|
Chris@16
|
217 reset_index(size() - 1, size() - 1);
|
Chris@16
|
218 siftup(q_.size() - 1);
|
Chris@16
|
219 }
|
Chris@16
|
220
|
Chris@16
|
221 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@16
|
222 template <class... Args>
|
Chris@16
|
223 void emplace(Args&&... args)
|
Chris@16
|
224 {
|
Chris@16
|
225 q_.emplace_back(super_t::make_node(std::forward<Args>(args)...));
|
Chris@16
|
226 reset_index(size() - 1, size() - 1);
|
Chris@16
|
227 siftup(q_.size() - 1);
|
Chris@16
|
228 }
|
Chris@16
|
229 #endif
|
Chris@16
|
230 void pop(void)
|
Chris@16
|
231 {
|
Chris@16
|
232 BOOST_ASSERT(!empty());
|
Chris@16
|
233 std::swap(q_.front(), q_.back());
|
Chris@16
|
234 q_.pop_back();
|
Chris@16
|
235
|
Chris@16
|
236 if (q_.empty())
|
Chris@16
|
237 return;
|
Chris@16
|
238
|
Chris@16
|
239 reset_index(0, 0);
|
Chris@16
|
240 siftdown(0);
|
Chris@16
|
241 }
|
Chris@16
|
242
|
Chris@16
|
243 void swap(d_ary_heap & rhs)
|
Chris@16
|
244 {
|
Chris@16
|
245 super_t::swap(rhs);
|
Chris@16
|
246 q_.swap(rhs.q_);
|
Chris@16
|
247 }
|
Chris@16
|
248
|
Chris@16
|
249 iterator begin(void) const
|
Chris@16
|
250 {
|
Chris@16
|
251 return iterator(q_.begin());
|
Chris@16
|
252 }
|
Chris@16
|
253
|
Chris@16
|
254 iterator end(void) const
|
Chris@16
|
255 {
|
Chris@16
|
256 return iterator(q_.end());
|
Chris@16
|
257 }
|
Chris@16
|
258
|
Chris@16
|
259 ordered_iterator ordered_begin(void) const
|
Chris@16
|
260 {
|
Chris@16
|
261 return ordered_iterator(0, this, super_t::get_internal_cmp());
|
Chris@16
|
262 }
|
Chris@16
|
263
|
Chris@16
|
264 ordered_iterator ordered_end(void) const
|
Chris@16
|
265 {
|
Chris@16
|
266 return ordered_iterator(size(), this, super_t::get_internal_cmp());
|
Chris@16
|
267 }
|
Chris@16
|
268
|
Chris@16
|
269 void reserve (size_type element_count)
|
Chris@16
|
270 {
|
Chris@16
|
271 q_.reserve(element_count);
|
Chris@16
|
272 }
|
Chris@16
|
273
|
Chris@16
|
274 value_compare const & value_comp(void) const
|
Chris@16
|
275 {
|
Chris@16
|
276 return super_t::value_comp();
|
Chris@16
|
277 }
|
Chris@16
|
278
|
Chris@16
|
279 private:
|
Chris@16
|
280 void reset_index(size_type index, size_type new_index)
|
Chris@16
|
281 {
|
Chris@16
|
282 BOOST_HEAP_ASSERT(index < q_.size());
|
Chris@16
|
283 index_updater::run(q_[index], new_index);
|
Chris@16
|
284 }
|
Chris@16
|
285
|
Chris@16
|
286 void siftdown(size_type index)
|
Chris@16
|
287 {
|
Chris@16
|
288 while (not_leaf(index)) {
|
Chris@16
|
289 size_type max_child_index = top_child_index(index);
|
Chris@16
|
290 if (!super_t::operator()(q_[max_child_index], q_[index])) {
|
Chris@16
|
291 reset_index(index, max_child_index);
|
Chris@16
|
292 reset_index(max_child_index, index);
|
Chris@16
|
293 std::swap(q_[max_child_index], q_[index]);
|
Chris@16
|
294 index = max_child_index;
|
Chris@16
|
295 }
|
Chris@16
|
296 else
|
Chris@16
|
297 return;
|
Chris@16
|
298 }
|
Chris@16
|
299 }
|
Chris@16
|
300
|
Chris@16
|
301 /* returns new index */
|
Chris@16
|
302 void siftup(size_type index)
|
Chris@16
|
303 {
|
Chris@16
|
304 while (index != 0) {
|
Chris@16
|
305 size_type parent = parent_index(index);
|
Chris@16
|
306
|
Chris@16
|
307 if (super_t::operator()(q_[parent], q_[index])) {
|
Chris@16
|
308 reset_index(index, parent);
|
Chris@16
|
309 reset_index(parent, index);
|
Chris@16
|
310 std::swap(q_[parent], q_[index]);
|
Chris@16
|
311 index = parent;
|
Chris@16
|
312 }
|
Chris@16
|
313 else
|
Chris@16
|
314 return;
|
Chris@16
|
315 }
|
Chris@16
|
316 }
|
Chris@16
|
317
|
Chris@16
|
318 bool not_leaf(size_type index) const
|
Chris@16
|
319 {
|
Chris@16
|
320 const size_t first_child = first_child_index(index);
|
Chris@16
|
321 return first_child < q_.size();
|
Chris@16
|
322 }
|
Chris@16
|
323
|
Chris@16
|
324 size_type top_child_index(size_type index) const
|
Chris@16
|
325 {
|
Chris@16
|
326 // invariant: index is not a leaf, so the iterator range is not empty
|
Chris@16
|
327
|
Chris@16
|
328 const size_t first_index = first_child_index(index);
|
Chris@16
|
329 typedef typename container_type::const_iterator container_iterator;
|
Chris@16
|
330
|
Chris@16
|
331 const container_iterator first_child = q_.begin() + first_index;
|
Chris@16
|
332 const container_iterator end = q_.end();
|
Chris@16
|
333
|
Chris@16
|
334 const size_type max_elements = std::distance(first_child, end);
|
Chris@16
|
335
|
Chris@16
|
336 const container_iterator last_child = (max_elements > D) ? first_child + D
|
Chris@16
|
337 : end;
|
Chris@16
|
338
|
Chris@16
|
339 const container_iterator min_element = std::max_element(first_child, last_child, static_cast<super_t const &>(*this));
|
Chris@16
|
340
|
Chris@16
|
341 return min_element - q_.begin();
|
Chris@16
|
342 }
|
Chris@16
|
343
|
Chris@16
|
344 static size_type parent_index(size_type index)
|
Chris@16
|
345 {
|
Chris@16
|
346 return (index - 1) / D;
|
Chris@16
|
347 }
|
Chris@16
|
348
|
Chris@16
|
349 static size_type first_child_index(size_type index)
|
Chris@16
|
350 {
|
Chris@16
|
351 return index * D + 1;
|
Chris@16
|
352 }
|
Chris@16
|
353
|
Chris@16
|
354 size_type last_child_index(size_type index) const
|
Chris@16
|
355 {
|
Chris@16
|
356 const size_t first_index = first_child_index(index);
|
Chris@16
|
357 const size_type last_index = (std::min)(first_index + D - 1, size() - 1);
|
Chris@16
|
358
|
Chris@16
|
359 return last_index;
|
Chris@16
|
360 }
|
Chris@16
|
361
|
Chris@16
|
362 template<typename U,
|
Chris@16
|
363 typename V,
|
Chris@16
|
364 typename W,
|
Chris@16
|
365 typename X>
|
Chris@16
|
366 struct rebind {
|
Chris@16
|
367 typedef d_ary_heap<U, typename d_ary_heap_signature::bind<boost::heap::stable<heap_base_maker::is_stable>,
|
Chris@16
|
368 boost::heap::stability_counter_type<typename heap_base_maker::stability_counter_type>,
|
Chris@16
|
369 boost::heap::arity<D>,
|
Chris@16
|
370 boost::heap::compare<V>,
|
Chris@16
|
371 boost::heap::allocator<W>
|
Chris@16
|
372 >::type,
|
Chris@16
|
373 X
|
Chris@16
|
374 > other;
|
Chris@16
|
375 };
|
Chris@16
|
376
|
Chris@16
|
377 template <class U> friend class priority_queue_mutable_wrapper;
|
Chris@16
|
378
|
Chris@16
|
379 void update(size_type index)
|
Chris@16
|
380 {
|
Chris@16
|
381 if (index == 0) {
|
Chris@16
|
382 siftdown(index);
|
Chris@16
|
383 return;
|
Chris@16
|
384 }
|
Chris@16
|
385 size_type parent = parent_index(index);
|
Chris@16
|
386
|
Chris@16
|
387 if (super_t::operator()(q_[parent], q_[index]))
|
Chris@16
|
388 siftup(index);
|
Chris@16
|
389 else
|
Chris@16
|
390 siftdown(index);
|
Chris@16
|
391 }
|
Chris@16
|
392
|
Chris@16
|
393 void erase(size_type index)
|
Chris@16
|
394 {
|
Chris@16
|
395 while (index != 0)
|
Chris@16
|
396 {
|
Chris@16
|
397 size_type parent = parent_index(index);
|
Chris@16
|
398
|
Chris@16
|
399 reset_index(index, parent);
|
Chris@16
|
400 reset_index(parent, index);
|
Chris@16
|
401 std::swap(q_[parent], q_[index]);
|
Chris@16
|
402 index = parent;
|
Chris@16
|
403 }
|
Chris@16
|
404 pop();
|
Chris@16
|
405 }
|
Chris@16
|
406
|
Chris@16
|
407 void increase(size_type index)
|
Chris@16
|
408 {
|
Chris@16
|
409 siftup(index);
|
Chris@16
|
410 }
|
Chris@16
|
411
|
Chris@16
|
412 void decrease(size_type index)
|
Chris@16
|
413 {
|
Chris@16
|
414 siftdown(index);
|
Chris@16
|
415 }
|
Chris@16
|
416 };
|
Chris@16
|
417
|
Chris@16
|
418
|
Chris@16
|
419 template <typename T, typename BoundArgs>
|
Chris@16
|
420 struct select_dary_heap
|
Chris@16
|
421 {
|
Chris@16
|
422 static const bool is_mutable = extract_mutable<BoundArgs>::value;
|
Chris@16
|
423
|
Chris@16
|
424 typedef typename mpl::if_c< is_mutable,
|
Chris@16
|
425 priority_queue_mutable_wrapper<d_ary_heap<T, BoundArgs, nop_index_updater > >,
|
Chris@16
|
426 d_ary_heap<T, BoundArgs, nop_index_updater >
|
Chris@16
|
427 >::type type;
|
Chris@16
|
428 };
|
Chris@16
|
429
|
Chris@16
|
430 } /* namespace detail */
|
Chris@16
|
431
|
Chris@16
|
432
|
Chris@16
|
433
|
Chris@16
|
434 /**
|
Chris@16
|
435 * \class d_ary_heap
|
Chris@16
|
436 * \brief d-ary heap class
|
Chris@16
|
437 *
|
Chris@16
|
438 * This class implements an immutable priority queue. Internally, the d-ary heap is represented
|
Chris@16
|
439 * as dynamically sized array (std::vector), that directly stores the values.
|
Chris@16
|
440 *
|
Chris@16
|
441 * The template parameter T is the type to be managed by the container.
|
Chris@16
|
442 * The user can specify additional options and if no options are provided default options are used.
|
Chris@16
|
443 *
|
Chris@16
|
444 * The container supports the following options:
|
Chris@16
|
445 * - \c boost::heap::arity<>, required
|
Chris@16
|
446 * - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
|
Chris@16
|
447 * - \c boost::heap::stable<>, defaults to \c stable<false>
|
Chris@16
|
448 * - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
|
Chris@16
|
449 * - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
|
Chris@16
|
450 * - \c boost::heap::mutable_<>, defaults to \c mutable_<false>
|
Chris@16
|
451 *
|
Chris@16
|
452 */
|
Chris@16
|
453 #ifdef BOOST_DOXYGEN_INVOKED
|
Chris@16
|
454 template<class T, class ...Options>
|
Chris@16
|
455 #else
|
Chris@16
|
456 template <typename T,
|
Chris@16
|
457 class A0 = boost::parameter::void_,
|
Chris@16
|
458 class A1 = boost::parameter::void_,
|
Chris@16
|
459 class A2 = boost::parameter::void_,
|
Chris@16
|
460 class A3 = boost::parameter::void_,
|
Chris@16
|
461 class A4 = boost::parameter::void_,
|
Chris@16
|
462 class A5 = boost::parameter::void_
|
Chris@16
|
463 >
|
Chris@16
|
464 #endif
|
Chris@16
|
465 class d_ary_heap:
|
Chris@16
|
466 public detail::select_dary_heap<T, typename detail::d_ary_heap_signature::bind<A0, A1, A2, A3, A4, A5>::type>::type
|
Chris@16
|
467 {
|
Chris@16
|
468 typedef typename detail::d_ary_heap_signature::bind<A0, A1, A2, A3, A4, A5>::type bound_args;
|
Chris@16
|
469 typedef typename detail::select_dary_heap<T, bound_args>::type super_t;
|
Chris@16
|
470
|
Chris@16
|
471 template <typename Heap1, typename Heap2>
|
Chris@16
|
472 friend struct heap_merge_emulate;
|
Chris@16
|
473
|
Chris@16
|
474 #ifndef BOOST_DOXYGEN_INVOKED
|
Chris@16
|
475 static const bool is_mutable = detail::extract_mutable<bound_args>::value;
|
Chris@16
|
476
|
Chris@16
|
477 #define BOOST_HEAP_TYPEDEF_FROM_SUPER_T(NAME) \
|
Chris@16
|
478 typedef typename super_t::NAME NAME;
|
Chris@16
|
479
|
Chris@16
|
480 struct implementation_defined
|
Chris@16
|
481 {
|
Chris@16
|
482 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(size_type)
|
Chris@16
|
483 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(difference_type)
|
Chris@16
|
484 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(value_compare)
|
Chris@16
|
485 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(allocator_type)
|
Chris@16
|
486 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(reference)
|
Chris@16
|
487 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(const_reference)
|
Chris@16
|
488 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(pointer)
|
Chris@16
|
489 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(const_pointer)
|
Chris@16
|
490 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(iterator)
|
Chris@16
|
491 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(const_iterator)
|
Chris@16
|
492 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(ordered_iterator)
|
Chris@16
|
493 BOOST_HEAP_TYPEDEF_FROM_SUPER_T(handle_type)
|
Chris@16
|
494 };
|
Chris@16
|
495 #undef BOOST_HEAP_TYPEDEF_FROM_SUPER_T
|
Chris@16
|
496
|
Chris@16
|
497 #endif
|
Chris@16
|
498 public:
|
Chris@16
|
499 static const bool constant_time_size = true;
|
Chris@16
|
500 static const bool has_ordered_iterators = true;
|
Chris@16
|
501 static const bool is_mergable = false;
|
Chris@16
|
502 static const bool has_reserve = true;
|
Chris@16
|
503 static const bool is_stable = super_t::is_stable;
|
Chris@16
|
504
|
Chris@16
|
505 typedef T value_type;
|
Chris@16
|
506 typedef typename implementation_defined::size_type size_type;
|
Chris@16
|
507 typedef typename implementation_defined::difference_type difference_type;
|
Chris@16
|
508 typedef typename implementation_defined::value_compare value_compare;
|
Chris@16
|
509 typedef typename implementation_defined::allocator_type allocator_type;
|
Chris@16
|
510 typedef typename implementation_defined::reference reference;
|
Chris@16
|
511 typedef typename implementation_defined::const_reference const_reference;
|
Chris@16
|
512 typedef typename implementation_defined::pointer pointer;
|
Chris@16
|
513 typedef typename implementation_defined::const_pointer const_pointer;
|
Chris@16
|
514 /// \copydoc boost::heap::priority_queue::iterator
|
Chris@16
|
515 typedef typename implementation_defined::iterator iterator;
|
Chris@16
|
516 typedef typename implementation_defined::const_iterator const_iterator;
|
Chris@16
|
517 typedef typename implementation_defined::ordered_iterator ordered_iterator;
|
Chris@16
|
518 typedef typename implementation_defined::handle_type handle_type;
|
Chris@16
|
519
|
Chris@16
|
520 /// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
|
Chris@16
|
521 explicit d_ary_heap(value_compare const & cmp = value_compare()):
|
Chris@16
|
522 super_t(cmp)
|
Chris@16
|
523 {}
|
Chris@16
|
524
|
Chris@16
|
525 /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
|
Chris@16
|
526 d_ary_heap(d_ary_heap const & rhs):
|
Chris@16
|
527 super_t(rhs)
|
Chris@16
|
528 {}
|
Chris@16
|
529
|
Chris@16
|
530 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
531 /// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
|
Chris@16
|
532 d_ary_heap(d_ary_heap && rhs):
|
Chris@16
|
533 super_t(std::move(rhs))
|
Chris@16
|
534 {}
|
Chris@16
|
535
|
Chris@16
|
536 /// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
|
Chris@16
|
537 d_ary_heap & operator=(d_ary_heap && rhs)
|
Chris@16
|
538 {
|
Chris@16
|
539 super_t::operator=(std::move(rhs));
|
Chris@16
|
540 return *this;
|
Chris@16
|
541 }
|
Chris@16
|
542 #endif
|
Chris@16
|
543
|
Chris@16
|
544 /// \copydoc boost::heap::priority_queue::operator=(priority_queue const &)
|
Chris@16
|
545 d_ary_heap & operator=(d_ary_heap const & rhs)
|
Chris@16
|
546 {
|
Chris@16
|
547 super_t::operator=(rhs);
|
Chris@16
|
548 return *this;
|
Chris@16
|
549 }
|
Chris@16
|
550
|
Chris@16
|
551 /// \copydoc boost::heap::priority_queue::empty
|
Chris@16
|
552 bool empty(void) const
|
Chris@16
|
553 {
|
Chris@16
|
554 return super_t::empty();
|
Chris@16
|
555 }
|
Chris@16
|
556
|
Chris@16
|
557 /// \copydoc boost::heap::priority_queue::size
|
Chris@16
|
558 size_type size(void) const
|
Chris@16
|
559 {
|
Chris@16
|
560 return super_t::size();
|
Chris@16
|
561 }
|
Chris@16
|
562
|
Chris@16
|
563 /// \copydoc boost::heap::priority_queue::max_size
|
Chris@16
|
564 size_type max_size(void) const
|
Chris@16
|
565 {
|
Chris@16
|
566 return super_t::max_size();
|
Chris@16
|
567 }
|
Chris@16
|
568
|
Chris@16
|
569 /// \copydoc boost::heap::priority_queue::clear
|
Chris@16
|
570 void clear(void)
|
Chris@16
|
571 {
|
Chris@16
|
572 super_t::clear();
|
Chris@16
|
573 }
|
Chris@16
|
574
|
Chris@16
|
575 /// \copydoc boost::heap::priority_queue::get_allocator
|
Chris@16
|
576 allocator_type get_allocator(void) const
|
Chris@16
|
577 {
|
Chris@16
|
578 return super_t::get_allocator();
|
Chris@16
|
579 }
|
Chris@16
|
580
|
Chris@16
|
581 /// \copydoc boost::heap::priority_queue::top
|
Chris@16
|
582 value_type const & top(void) const
|
Chris@16
|
583 {
|
Chris@16
|
584 return super_t::top();
|
Chris@16
|
585 }
|
Chris@16
|
586
|
Chris@16
|
587 /// \copydoc boost::heap::priority_queue::push
|
Chris@16
|
588 typename mpl::if_c<is_mutable, handle_type, void>::type push(value_type const & v)
|
Chris@16
|
589 {
|
Chris@16
|
590 return super_t::push(v);
|
Chris@16
|
591 }
|
Chris@16
|
592
|
Chris@16
|
593 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@16
|
594 /// \copydoc boost::heap::priority_queue::emplace
|
Chris@16
|
595 template <class... Args>
|
Chris@16
|
596 typename mpl::if_c<is_mutable, handle_type, void>::type emplace(Args&&... args)
|
Chris@16
|
597 {
|
Chris@16
|
598 return super_t::emplace(std::forward<Args>(args)...);
|
Chris@16
|
599 }
|
Chris@16
|
600 #endif
|
Chris@16
|
601
|
Chris@16
|
602 /// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
|
Chris@16
|
603 template <typename HeapType>
|
Chris@16
|
604 bool operator<(HeapType const & rhs) const
|
Chris@16
|
605 {
|
Chris@16
|
606 return detail::heap_compare(*this, rhs);
|
Chris@16
|
607 }
|
Chris@16
|
608
|
Chris@16
|
609 /// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
|
Chris@16
|
610 template <typename HeapType>
|
Chris@16
|
611 bool operator>(HeapType const & rhs) const
|
Chris@16
|
612 {
|
Chris@16
|
613 return detail::heap_compare(rhs, *this);
|
Chris@16
|
614 }
|
Chris@16
|
615
|
Chris@16
|
616 /// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
|
Chris@16
|
617 template <typename HeapType>
|
Chris@16
|
618 bool operator>=(HeapType const & rhs) const
|
Chris@16
|
619 {
|
Chris@16
|
620 return !operator<(rhs);
|
Chris@16
|
621 }
|
Chris@16
|
622
|
Chris@16
|
623 /// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
|
Chris@16
|
624 template <typename HeapType>
|
Chris@16
|
625 bool operator<=(HeapType const & rhs) const
|
Chris@16
|
626 {
|
Chris@16
|
627 return !operator>(rhs);
|
Chris@16
|
628 }
|
Chris@16
|
629
|
Chris@16
|
630 /// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
|
Chris@16
|
631 template <typename HeapType>
|
Chris@16
|
632 bool operator==(HeapType const & rhs) const
|
Chris@16
|
633 {
|
Chris@16
|
634 return detail::heap_equality(*this, rhs);
|
Chris@16
|
635 }
|
Chris@16
|
636
|
Chris@16
|
637 /// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
|
Chris@16
|
638 template <typename HeapType>
|
Chris@16
|
639 bool operator!=(HeapType const & rhs) const
|
Chris@16
|
640 {
|
Chris@16
|
641 return !(*this == rhs);
|
Chris@16
|
642 }
|
Chris@16
|
643
|
Chris@16
|
644 /**
|
Chris@16
|
645 * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
|
Chris@16
|
646 *
|
Chris@16
|
647 * \b Complexity: Logarithmic.
|
Chris@16
|
648 *
|
Chris@16
|
649 * \b Requirement: data structure must be configured as mutable
|
Chris@16
|
650 * */
|
Chris@16
|
651 void update(handle_type handle, const_reference v)
|
Chris@16
|
652 {
|
Chris@16
|
653 BOOST_STATIC_ASSERT(is_mutable);
|
Chris@16
|
654 super_t::update(handle, v);
|
Chris@16
|
655 }
|
Chris@16
|
656
|
Chris@16
|
657 /**
|
Chris@16
|
658 * \b Effects: Updates the heap after the element handled by \c handle has been changed.
|
Chris@16
|
659 *
|
Chris@16
|
660 * \b Complexity: Logarithmic.
|
Chris@16
|
661 *
|
Chris@16
|
662 * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
|
Chris@16
|
663 *
|
Chris@16
|
664 * \b Requirement: data structure must be configured as mutable
|
Chris@16
|
665 * */
|
Chris@16
|
666 void update(handle_type handle)
|
Chris@16
|
667 {
|
Chris@16
|
668 BOOST_STATIC_ASSERT(is_mutable);
|
Chris@16
|
669 super_t::update(handle);
|
Chris@16
|
670 }
|
Chris@16
|
671
|
Chris@16
|
672 /**
|
Chris@16
|
673 * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
|
Chris@16
|
674 *
|
Chris@16
|
675 * \b Complexity: Logarithmic.
|
Chris@16
|
676 *
|
Chris@16
|
677 * \b Note: The new value is expected to be greater than the current one
|
Chris@16
|
678 *
|
Chris@16
|
679 * \b Requirement: data structure must be configured as mutable
|
Chris@16
|
680 * */
|
Chris@16
|
681 void increase(handle_type handle, const_reference v)
|
Chris@16
|
682 {
|
Chris@16
|
683 BOOST_STATIC_ASSERT(is_mutable);
|
Chris@16
|
684 super_t::increase(handle, v);
|
Chris@16
|
685 }
|
Chris@16
|
686
|
Chris@16
|
687 /**
|
Chris@16
|
688 * \b Effects: Updates the heap after the element handled by \c handle has been changed.
|
Chris@16
|
689 *
|
Chris@16
|
690 * \b Complexity: Logarithmic.
|
Chris@16
|
691 *
|
Chris@16
|
692 * \b Note: The new value is expected to be greater than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
|
Chris@16
|
693 *
|
Chris@16
|
694 * \b Requirement: data structure must be configured as mutable
|
Chris@16
|
695 * */
|
Chris@16
|
696 void increase(handle_type handle)
|
Chris@16
|
697 {
|
Chris@16
|
698 BOOST_STATIC_ASSERT(is_mutable);
|
Chris@16
|
699 super_t::increase(handle);
|
Chris@16
|
700 }
|
Chris@16
|
701
|
Chris@16
|
702 /**
|
Chris@16
|
703 * \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
|
Chris@16
|
704 *
|
Chris@16
|
705 * \b Complexity: Logarithmic.
|
Chris@16
|
706 *
|
Chris@16
|
707 * \b Note: The new value is expected to be less than the current one
|
Chris@16
|
708 *
|
Chris@16
|
709 * \b Requirement: data structure must be configured as mutable
|
Chris@16
|
710 * */
|
Chris@16
|
711 void decrease(handle_type handle, const_reference v)
|
Chris@16
|
712 {
|
Chris@16
|
713 BOOST_STATIC_ASSERT(is_mutable);
|
Chris@16
|
714 super_t::decrease(handle, v);
|
Chris@16
|
715 }
|
Chris@16
|
716
|
Chris@16
|
717 /**
|
Chris@16
|
718 * \b Effects: Updates the heap after the element handled by \c handle has been changed.
|
Chris@16
|
719 *
|
Chris@16
|
720 * \b Complexity: Logarithmic.
|
Chris@16
|
721 *
|
Chris@16
|
722 * \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
|
Chris@16
|
723 *
|
Chris@16
|
724 * \b Requirement: data structure must be configured as mutable
|
Chris@16
|
725 * */
|
Chris@16
|
726 void decrease(handle_type handle)
|
Chris@16
|
727 {
|
Chris@16
|
728 BOOST_STATIC_ASSERT(is_mutable);
|
Chris@16
|
729 super_t::decrease(handle);
|
Chris@16
|
730 }
|
Chris@16
|
731
|
Chris@16
|
732 /**
|
Chris@16
|
733 * \b Effects: Removes the element handled by \c handle from the priority_queue.
|
Chris@16
|
734 *
|
Chris@16
|
735 * \b Complexity: Logarithmic.
|
Chris@16
|
736 *
|
Chris@16
|
737 * \b Requirement: data structure must be configured as mutable
|
Chris@16
|
738 * */
|
Chris@16
|
739 void erase(handle_type handle)
|
Chris@16
|
740 {
|
Chris@16
|
741 BOOST_STATIC_ASSERT(is_mutable);
|
Chris@16
|
742 super_t::erase(handle);
|
Chris@16
|
743 }
|
Chris@16
|
744
|
Chris@16
|
745 /**
|
Chris@16
|
746 * \b Effects: Casts an iterator to a node handle.
|
Chris@16
|
747 *
|
Chris@16
|
748 * \b Complexity: Constant.
|
Chris@16
|
749 *
|
Chris@16
|
750 * \b Requirement: data structure must be configured as mutable
|
Chris@16
|
751 * */
|
Chris@16
|
752 static handle_type s_handle_from_iterator(iterator const & it)
|
Chris@16
|
753 {
|
Chris@16
|
754 BOOST_STATIC_ASSERT(is_mutable);
|
Chris@16
|
755 return super_t::s_handle_from_iterator(it);
|
Chris@16
|
756 }
|
Chris@16
|
757
|
Chris@16
|
758 /// \copydoc boost::heap::priority_queue::pop
|
Chris@16
|
759 void pop(void)
|
Chris@16
|
760 {
|
Chris@16
|
761 super_t::pop();
|
Chris@16
|
762 }
|
Chris@16
|
763
|
Chris@16
|
764 /// \copydoc boost::heap::priority_queue::swap
|
Chris@16
|
765 void swap(d_ary_heap & rhs)
|
Chris@16
|
766 {
|
Chris@16
|
767 super_t::swap(rhs);
|
Chris@16
|
768 }
|
Chris@16
|
769
|
Chris@16
|
770 /// \copydoc boost::heap::priority_queue::begin
|
Chris@16
|
771 const_iterator begin(void) const
|
Chris@16
|
772 {
|
Chris@16
|
773 return super_t::begin();
|
Chris@16
|
774 }
|
Chris@16
|
775
|
Chris@16
|
776 /// \copydoc boost::heap::priority_queue::begin
|
Chris@16
|
777 iterator begin(void)
|
Chris@16
|
778 {
|
Chris@16
|
779 return super_t::begin();
|
Chris@16
|
780 }
|
Chris@16
|
781
|
Chris@16
|
782 /// \copydoc boost::heap::priority_queue::end
|
Chris@16
|
783 iterator end(void)
|
Chris@16
|
784 {
|
Chris@16
|
785 return super_t::end();
|
Chris@16
|
786 }
|
Chris@16
|
787
|
Chris@16
|
788 /// \copydoc boost::heap::priority_queue::end
|
Chris@16
|
789 const_iterator end(void) const
|
Chris@16
|
790 {
|
Chris@16
|
791 return super_t::end();
|
Chris@16
|
792 }
|
Chris@16
|
793
|
Chris@16
|
794 /// \copydoc boost::heap::fibonacci_heap::ordered_begin
|
Chris@16
|
795 ordered_iterator ordered_begin(void) const
|
Chris@16
|
796 {
|
Chris@16
|
797 return super_t::ordered_begin();
|
Chris@16
|
798 }
|
Chris@16
|
799
|
Chris@16
|
800 /// \copydoc boost::heap::fibonacci_heap::ordered_end
|
Chris@16
|
801 ordered_iterator ordered_end(void) const
|
Chris@16
|
802 {
|
Chris@16
|
803 return super_t::ordered_end();
|
Chris@16
|
804 }
|
Chris@16
|
805
|
Chris@16
|
806 /// \copydoc boost::heap::priority_queue::reserve
|
Chris@16
|
807 void reserve (size_type element_count)
|
Chris@16
|
808 {
|
Chris@16
|
809 super_t::reserve(element_count);
|
Chris@16
|
810 }
|
Chris@16
|
811
|
Chris@16
|
812 /// \copydoc boost::heap::priority_queue::value_comp
|
Chris@16
|
813 value_compare const & value_comp(void) const
|
Chris@16
|
814 {
|
Chris@16
|
815 return super_t::value_comp();
|
Chris@16
|
816 }
|
Chris@16
|
817 };
|
Chris@16
|
818
|
Chris@16
|
819 } /* namespace heap */
|
Chris@16
|
820 } /* namespace boost */
|
Chris@16
|
821
|
Chris@16
|
822 #undef BOOST_HEAP_ASSERT
|
Chris@16
|
823
|
Chris@16
|
824 #endif /* BOOST_HEAP_D_ARY_HEAP_HPP */
|