• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // boost heap: wrapper for stl 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 
9 #ifndef BOOST_HEAP_PRIORITY_QUEUE_HPP
10 #define BOOST_HEAP_PRIORITY_QUEUE_HPP
11 
12 #include <algorithm>
13 #include <queue>
14 #include <utility>
15 #include <vector>
16 
17 #include <boost/assert.hpp>
18 
19 #include <boost/heap/detail/heap_comparison.hpp>
20 #include <boost/heap/detail/stable_heap.hpp>
21 
22 #ifdef BOOST_HAS_PRAGMA_ONCE
23 #pragma once
24 #endif
25 
26 
27 namespace boost  {
28 namespace heap   {
29 namespace detail {
30 
31 typedef parameter::parameters<boost::parameter::optional<tag::allocator>,
32                               boost::parameter::optional<tag::compare>,
33                               boost::parameter::optional<tag::stable>,
34                               boost::parameter::optional<tag::stability_counter_type>
35                              > priority_queue_signature;
36 }
37 
38 /**
39  * \class priority_queue
40  * \brief priority queue, based on stl heap functions
41  *
42  * The priority_queue class is a wrapper for the stl heap functions.<br>
43  * The template parameter T is the type to be managed by the container.
44  * The user can specify additional options and if no options are provided default options are used.
45  *
46  * The container supports the following options:
47  * - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
48  * - \c boost::heap::stable<>, defaults to \c stable<false>
49  * - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
50  * - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
51  *
52  */
53 #ifdef BOOST_DOXYGEN_INVOKED
54 template<class T, class ...Options>
55 #else
56 template <typename T,
57           class A0 = boost::parameter::void_,
58           class A1 = boost::parameter::void_,
59           class A2 = boost::parameter::void_,
60           class A3 = boost::parameter::void_
61          >
62 #endif
63 class priority_queue:
64     private detail::make_heap_base<T, typename detail::priority_queue_signature::bind<A0, A1, A2, A3>::type, false>::type
65 {
66     typedef detail::make_heap_base<T, typename detail::priority_queue_signature::bind<A0, A1, A2, A3>::type, false> heap_base_maker;
67 
68     typedef typename heap_base_maker::type super_t;
69     typedef typename super_t::internal_type internal_type;
70     typedef typename boost::allocator_rebind<typename heap_base_maker::allocator_argument, internal_type>::type internal_type_allocator;
71     typedef std::vector<internal_type, internal_type_allocator> container_type;
72 
73     template <typename Heap1, typename Heap2>
74     friend struct detail::heap_merge_emulate;
75 
76     container_type q_;
77 
78 #ifndef BOOST_DOXYGEN_INVOKED
79     struct implementation_defined:
80         detail::extract_allocator_types<typename heap_base_maker::allocator_argument>
81     {
82         typedef typename heap_base_maker::compare_argument value_compare;
83         typedef detail::stable_heap_iterator<T, typename container_type::const_iterator, super_t> iterator;
84         typedef iterator const_iterator;
85         typedef typename container_type::allocator_type allocator_type;
86     };
87 #endif
88 
89 public:
90     typedef T value_type;
91     typedef typename implementation_defined::size_type size_type;
92     typedef typename implementation_defined::difference_type difference_type;
93     typedef typename implementation_defined::value_compare value_compare;
94     typedef typename implementation_defined::allocator_type allocator_type;
95     typedef typename implementation_defined::reference reference;
96     typedef typename implementation_defined::const_reference const_reference;
97     typedef typename implementation_defined::pointer pointer;
98     typedef typename implementation_defined::const_pointer const_pointer;
99     /**
100      * \b Note: The iterator does not traverse the priority queue in order of the priorities.
101      * */
102     typedef typename implementation_defined::iterator iterator;
103     typedef typename implementation_defined::const_iterator const_iterator;
104 
105     static const bool constant_time_size = true;
106     static const bool has_ordered_iterators = false;
107     static const bool is_mergable = false;
108     static const bool is_stable = heap_base_maker::is_stable;
109     static const bool has_reserve = true;
110 
111     /**
112      * \b Effects: constructs an empty priority queue.
113      *
114      * \b Complexity: Constant.
115      *
116      * */
priority_queue(value_compare const & cmp=value_compare ())117     explicit priority_queue(value_compare const & cmp = value_compare()):
118         super_t(cmp)
119     {}
120 
121     /**
122      * \b Effects: copy-constructs priority queue from rhs.
123      *
124      * \b Complexity: Linear.
125      *
126      * */
priority_queue(priority_queue const & rhs)127     priority_queue (priority_queue const & rhs):
128         super_t(rhs), q_(rhs.q_)
129     {}
130 
131 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
132     /**
133      * \b Effects: C++11-style move constructor.
134      *
135      * \b Complexity: Constant.
136      *
137      * \b Note: Only available, if BOOST_NO_CXX11_RVALUE_REFERENCES is not defined
138      * */
BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<super_t>::value)139     priority_queue(priority_queue && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<super_t>::value):
140         super_t(std::move(rhs)), q_(std::move(rhs.q_))
141     {}
142 
143     /**
144      * \b Effects: C++11-style move assignment.
145      *
146      * \b Complexity: Constant.
147      *
148      * \b Note: Only available, if BOOST_NO_CXX11_RVALUE_REFERENCES is not defined
149      * */
operator =(priority_queue && rhs)150     priority_queue & operator=(priority_queue && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<super_t>::value)
151     {
152         super_t::operator=(std::move(rhs));
153         q_ = std::move(rhs.q_);
154         return *this;
155     }
156 #endif
157 
158     /**
159      * \b Effects: Assigns priority queue from rhs.
160      *
161      * \b Complexity: Linear.
162      *
163      * */
operator =(priority_queue const & rhs)164     priority_queue & operator=(priority_queue const & rhs)
165     {
166         static_cast<super_t&>(*this) = static_cast<super_t const &>(rhs);
167         q_ = rhs.q_;
168         return *this;
169     }
170 
171     /**
172      * \b Effects: Returns true, if the priority queue contains no elements.
173      *
174      * \b Complexity: Constant.
175      *
176      * */
empty(void) const177     bool empty(void) const BOOST_NOEXCEPT
178     {
179         return q_.empty();
180     }
181 
182     /**
183      * \b Effects: Returns the number of elements contained in the priority queue.
184      *
185      * \b Complexity: Constant.
186      *
187      * */
size(void) const188     size_type size(void) const BOOST_NOEXCEPT
189     {
190         return q_.size();
191     }
192 
193     /**
194      * \b Effects: Returns the maximum number of elements the priority queue can contain.
195      *
196      * \b Complexity: Constant.
197      *
198      * */
max_size(void) const199     size_type max_size(void) const BOOST_NOEXCEPT
200     {
201         return q_.max_size();
202     }
203 
204     /**
205      * \b Effects: Removes all elements from the priority queue.
206      *
207      * \b Complexity: Linear.
208      *
209      * */
clear(void)210     void clear(void) BOOST_NOEXCEPT
211     {
212         q_.clear();
213     }
214 
215     /**
216      * \b Effects: Returns allocator.
217      *
218      * \b Complexity: Constant.
219      *
220      * */
get_allocator(void) const221     allocator_type get_allocator(void) const
222     {
223         return q_.get_allocator();
224     }
225 
226     /**
227      * \b Effects: Returns a const_reference to the maximum element.
228      *
229      * \b Complexity: Constant.
230      *
231      * */
top(void) const232     const_reference top(void) const
233     {
234         BOOST_ASSERT(!empty());
235         return super_t::get_value(q_.front());
236     }
237 
238     /**
239      * \b Effects: Adds a new element to the priority queue.
240      *
241      * \b Complexity: Logarithmic (amortized). Linear (worst case).
242      *
243      * */
push(value_type const & v)244     void push(value_type const & v)
245     {
246         q_.push_back(super_t::make_node(v));
247         std::push_heap(q_.begin(), q_.end(), static_cast<super_t const &>(*this));
248     }
249 
250 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
251     /**
252      * \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place.
253      *
254      * \b Complexity: Logarithmic (amortized). Linear (worst case).
255      *
256      * */
257     template <class... Args>
emplace(Args &&...args)258     void emplace(Args&&... args)
259     {
260         q_.emplace_back(super_t::make_node(std::forward<Args>(args)...));
261         std::push_heap(q_.begin(), q_.end(), static_cast<super_t const &>(*this));
262     }
263 #endif
264 
265     /**
266      * \b Effects: Removes the top element from the priority queue.
267      *
268      * \b Complexity: Logarithmic (amortized). Linear (worst case).
269      *
270      * */
pop(void)271     void pop(void)
272     {
273         BOOST_ASSERT(!empty());
274         std::pop_heap(q_.begin(), q_.end(), static_cast<super_t const &>(*this));
275         q_.pop_back();
276     }
277 
278     /**
279      * \b Effects: Swaps two priority queues.
280      *
281      * \b Complexity: Constant.
282      *
283      * */
swap(priority_queue & rhs)284     void swap(priority_queue & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<super_t>::value && boost::is_nothrow_move_assignable<super_t>::value)
285     {
286         super_t::swap(rhs);
287         q_.swap(rhs.q_);
288     }
289 
290     /**
291      * \b Effects: Returns an iterator to the first element contained in the priority queue.
292      *
293      * \b Complexity: Constant.
294      *
295      * */
begin(void) const296     iterator begin(void) const BOOST_NOEXCEPT
297     {
298         return iterator(q_.begin());
299     }
300 
301     /**
302      * \b Effects: Returns an iterator to the end of the priority queue.
303      *
304      * \b Complexity: Constant.
305      *
306      * */
end(void) const307     iterator end(void) const BOOST_NOEXCEPT
308     {
309         return iterator(q_.end());
310     }
311 
312     /**
313      * \b Effects: Reserves memory for element_count elements
314      *
315      * \b Complexity: Linear.
316      *
317      * \b Node: Invalidates iterators
318      *
319      * */
reserve(size_type element_count)320     void reserve(size_type element_count)
321     {
322         q_.reserve(element_count);
323     }
324 
325     /**
326      * \b Effect: Returns the value_compare object used by the priority queue
327      *
328      * */
value_comp(void) const329     value_compare const & value_comp(void) const
330     {
331         return super_t::value_comp();
332     }
333 
334     /**
335      * \b Returns: Element-wise comparison of heap data structures
336      *
337      * \b Requirement: the \c value_compare object of both heaps must match.
338      *
339      * */
340     template <typename HeapType>
operator <(HeapType const & rhs) const341     bool operator<(HeapType const & rhs) const
342     {
343         return detail::heap_compare(*this, rhs);
344     }
345 
346     /**
347      * \b Returns: Element-wise comparison of heap data structures
348      *
349      * \b Requirement: the \c value_compare object of both heaps must match.
350      *
351      * */
352     template <typename HeapType>
operator >(HeapType const & rhs) const353     bool operator>(HeapType const & rhs) const
354     {
355         return detail::heap_compare(rhs, *this);
356     }
357 
358     /**
359      * \b Returns: Element-wise comparison of heap data structures
360      *
361      * \b Requirement: the \c value_compare object of both heaps must match.
362      *
363      * */
364     template <typename HeapType>
operator >=(HeapType const & rhs) const365     bool operator>=(HeapType const & rhs) const
366     {
367         return !operator<(rhs);
368     }
369 
370     /**
371      * \b Returns: Element-wise comparison of heap data structures
372      *
373      * \b Requirement: the \c value_compare object of both heaps must match.
374      *
375      * */
376     template <typename HeapType>
operator <=(HeapType const & rhs) const377     bool operator<=(HeapType const & rhs) const
378     {
379         return !operator>(rhs);
380     }
381 
382     /** \brief Equivalent comparison
383      * \b Returns: True, if both heap data structures are equivalent.
384      *
385      * \b Requirement: the \c value_compare object of both heaps must match.
386      *
387      * */
388     template <typename HeapType>
operator ==(HeapType const & rhs) const389     bool operator==(HeapType const & rhs) const
390     {
391         return detail::heap_equality(*this, rhs);
392     }
393 
394     /** \brief Equivalent comparison
395      * \b Returns: True, if both heap data structures are not equivalent.
396      *
397      * \b Requirement: the \c value_compare object of both heaps must match.
398      *
399      * */
400     template <typename HeapType>
operator !=(HeapType const & rhs) const401     bool operator!=(HeapType const & rhs) const
402     {
403         return !(*this == rhs);
404     }
405 };
406 
407 } /* namespace heap */
408 } /* namespace boost */
409 
410 #endif /* BOOST_HEAP_PRIORITY_QUEUE_HPP */
411