vigra - vigra/bucket_queue.hxx Source File

[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

bucket_queue.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 2010-2011 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35
36
37 #ifndef VIGRA_BUCKET_QUEUE_HXX
38 #define VIGRA_BUCKET_QUEUE_HXX
39
40 #include "config.hxx"
41 #include "error.hxx"
42 #include "array_vector.hxx"
43 #include <queue>
44
45 namespace vigra {
46
47 /** \brief Priority queue implemented using bucket sort.
48
49 This template implements functionality similar to <tt><a href="http://www.sgi.com/tech/stl/priority_queue.html">std::priority_queue</a></tt>,
50 but uses a more efficient algorithm based on bucket sort. It can be used
51 when all priorities are positive integers in a given range (typically, 0...255).
52 By default, <tt>BucketQueue<ValueType></tt> sorts the elements in descending order,
53 i.e. like in <tt>std::priority_queue</tt> the largest element has highest priority.
54 An ascending queue can be specified as <tt>BucketQueue<ValueType, true></tt>.
55 Elements with equal priorities are returned in a first-in first-out fashion.
56
57 The main difference to <tt>std::priority_queue</tt> is the function <tt>push</tt>
58 which explicitly takes the priority of the element to be added as a second argument.
59 This allows optimization of <tt>ValueType</tt>: since the bucket uniquely
60 determines an element's priority, there is no need for <tt>ValueType</tt> to
61 store redundant priority information. If compatibility to <tt>std::priority_queue</tt>
62 is more important, use \ref vigra::MappedBucketQueue.
63
64 <b>\#include</b> <vigra/bucket_queue.hxx><br>
65 Namespace: vigra
66 */
67 template <class ValueType,
68 bool Ascending = false> // std::priority_queue is descending
69 class BucketQueue
70 {
71 ArrayVector<std::queue<ValueType> > buckets_;
72 std::size_t size_;
73 std::ptrdiff_t top_;
74
75 public:
76
77 typedef ValueType value_type;
78 typedef ValueType & reference;
79 typedef ValueType const & const_reference;
80 typedef std::size_t size_type;
81 typedef std::ptrdiff_t priority_type;
82
83 /** \brief Create bucket queue with \arg bucket_count entries.
84 Priorities must be integers in the range <tt>[0, ..., bucket_count-1]</tt>.
85 */
86 BucketQueue(size_type bucket_count = 256)
87 : buckets_(bucket_count),
88 size_(0), top_(0)
89 {}
90
91 /** \brief Number of elements in this queue.
92 */
93 size_type size() const
94 {
95 return size_;
96 }
97
98 /** \brief Queue contains no elements.
99 Equivalent to <tt>size() == 0</tt>.
100 */
101 bool empty() const
102 {
103 return size() == 0;
104 }
105
106 /** \brief Maximum index (i.e. priority) allowed in this queue.
107 Equivalent to <tt>bucket_count - 1</tt>.
108 */
109 priority_type maxIndex() const
110 {
111 return (priority_type)buckets_.size() - 1;
112 }
113
114 /** \brief Priority of the current top element.
115 */
116 priority_type topPriority() const
117 {
118 return top_;
119 }
120
121 /** \brief The current top element.
122 */
123 const_reference top() const
124 {
125
126 return buckets_[top_].front();
127 }
128
129 /** \brief Remove the current top element.
130 */
131 void pop()
132 {
133 --size_;
134 buckets_[top_].pop();
135
136 while(top_ > 0 && buckets_[top_].size() == 0)
137 --top_;
138 }
139
140 /** \brief Insert new element \arg v with given \arg priority.
141 */
142 void push(value_type const & v, priority_type priority)
143 {
144 ++size_;
145 buckets_[priority].push(v);
146
147 if(priority > top_)
148 top_ = priority;
149 }
150 };
151
152 template <class ValueType>
153 class BucketQueue<ValueType, true> // ascending queue
154 {
155 ArrayVector<std::queue<ValueType> > buckets_;
156 std::size_t size_;
157 std::ptrdiff_t top_;
158
159 public:
160
161 typedef ValueType value_type;
162 typedef ValueType & reference;
163 typedef ValueType const & const_reference;
164 typedef std::size_t size_type;
165 typedef std::ptrdiff_t priority_type;
166
167 BucketQueue(size_type bucket_count = 256)
168 : buckets_(bucket_count),
169 size_(0), top_((priority_type)bucket_count)
170 {}
171
172 size_type size() const
173 {
174 return size_;
175 }
176
177 bool empty() const
178 {
179 return size() == 0;
180 }
181
182 priority_type maxIndex() const
183 {
184 return (priority_type)buckets_.size() - 1;
185 }
186
187 priority_type topPriority() const
188 {
189 return top_;
190 }
191
192 const_reference top() const
193 {
194
195 return buckets_[top_].front();
196 }
197
198 void pop()
199 {
200 --size_;
201 buckets_[top_].pop();
202
203 while(top_ < (priority_type)buckets_.size() && buckets_[top_].size() == 0)
204 ++top_;
205 }
206
207 void push(value_type const & v, priority_type priority)
208 {
209 ++size_;
210 buckets_[priority].push(v);
211
212 if(priority < top_)
213 top_ = priority;
214 }
215 };
216
217 /** \brief Priority queue implemented using bucket sort (STL compatible).
218
219 This template is compatible to <tt><a href="http://www.sgi.com/tech/stl/priority_queue.html">std::priority_queue</a></tt>,
220 but uses a more efficient algorithm based on bucket sort. It us used
221 like \ref vigra::BucketQueue, but has an additional <tt>PriorityFunctor</tt>
222 which extracts the priority value of an element of type <tt>ValueType</tt>.
223 Thus functor is called within <tt>push</tt> so that it does not need an
224 extra argument.
225
226 <b>\#include</b> <vigra/bucket_queue.hxx><br>
227 Namespace: vigra
228 */
229 template <class ValueType,
230 class PriorityFunctor,
231 bool Ascending = false>
232 class MappedBucketQueue
233 : public BucketQueue<ValueType, Ascending>
234 {
235 PriorityFunctor get_priority_;
236
237 public:
238
239 typedef BucketQueue<ValueType, Ascending> BaseType;
240 typedef typename BaseType::value_type value_type;
241 typedef typename BaseType::reference reference;
242 typedef typename BaseType::const_reference const_reference;
243 typedef typename BaseType::size_type size_type;
244 typedef typename BaseType::priority_type priority_type;
245
246 /** \brief Create a queue with \arg bucket_count entries.
247 Priorities will be computed by the <tt>PriorityFunctor</tt>
248 given in \arg priority (i.e. <tt>priority(v)</tt> must result in an integer,
249 where <tt>v</tt> is an instance of <tt>ValueType</tt>).
250 */
251 MappedBucketQueue(unsigned int bucket_count = 256,
252 PriorityFunctor const & priority = PriorityFunctor())
253 : BaseType(bucket_count),
254 get_priority_(priority)
255 {}
256
257 /** \brief Insert new element \arg v.
258 Its priority is calculated by <tt>priority(v)</tt>,
259 where <tt>priority</tt> is an instance of the
260 <tt>PriorityFunctor</tt> passed in the constructor.
261 If the priority is outside the range <tt>[0, ..., bucket_count-1]</tt>,
262 it is clamped to the range borders.
263 */
264 void push(value_type const & v)
265 {
266 priority_type index = get_priority_(v);
267
268 // clamp index to the allowed range
269 if(index > BaseType::maxIndex())
270 index = BaseType::maxIndex();
271 else if (index < 0)
272 index = 0;
273
274 BaseType::push(v, index);
275 }
276 };
277
278 /** \brief Heap-based priority queue compatible to BucketQueue.
279
280 This template is compatible to \ref vigra::BucketQueue, but accepts arbitrary priority
281 types. Internally, it uses a <tt>std::priority_queue</tt>, but implements an
282 API where priorities and payload data are separate, like in \ref vigra::BucketQueue.
283
284 <b>\#include</b> <vigra/bucket_queue.hxx><br>
285 Namespace: vigra
286 */
287 template <class ValueType,
288 class PriorityType,
289 bool Ascending = false> // std::priority_queue is descending
290 class PriorityQueue
291 {
292 typedef std::pair<ValueType, PriorityType> ElementType;
293
294 struct Compare
295 {
296 typename IfBool<Ascending, std::greater<PriorityType>,
297 std::less<PriorityType> >::type cmp;
298
299 bool operator()(ElementType const & l, ElementType const & r) const
300 {
301 return cmp(l.second, r.second);
302 }
303 };
304
305 typedef std::priority_queue<ElementType, std::vector<ElementType>, Compare> Heap;
306
307 Heap heap_;
308
309 public:
310
311 typedef ValueType value_type;
312 typedef ValueType & reference;
313 typedef ValueType const & const_reference;
314 typedef typename Heap::size_type size_type;
315 typedef PriorityType priority_type;
316
317 /** \brief Create empty priority queue.
318 */
319 PriorityQueue()
320 : heap_()
321 {}
322
323 /** \brief Number of elements in this queue.
324 */
325 size_type size() const
326 {
327 return heap_.size();
328 }
329
330 /** \brief Queue contains no elements.
331 Equivalent to <tt>size() == 0</tt>.
332 */
333 bool empty() const
334 {
335 return size() == 0;
336 }
337
338 /** \brief Maximum index (i.e. priority) allowed in this queue.
339 Equivalent to <tt>bucket_count - 1</tt>.
340 */
341 priority_type maxIndex() const
342 {
343 return NumericTraits<priority_type>::max();
344 }
345
346 /** \brief Priority of the current top element.
347 */
348 priority_type topPriority() const
349 {
350 return heap_.top().second;
351 }
352
353 /** \brief The current top element.
354 */
355 const_reference top() const
356 {
357
358 return heap_.top().first;
359 }
360
361 /** \brief Remove the current top element.
362 */
363 void pop()
364 {
365 heap_.pop();
366 }
367
368 /** \brief Insert new element \arg v with given \arg priority.
369 */
370 void push(value_type const & v, priority_type priority)
371 {
372 heap_.push(ElementType(v, priority));
373 }
374 };
375
376 template <class ValueType,
377 bool Ascending>
378 class PriorityQueue<ValueType, unsigned char, Ascending>
379 : public BucketQueue<ValueType, Ascending>
380 {
381 public:
382 typedef BucketQueue<ValueType, Ascending> BaseType;
383
384 PriorityQueue()
385 : BaseType(NumericTraits<unsigned char>::max()+1)
386 {}
387 };
388
389 template <class ValueType,
390 bool Ascending>
391 class PriorityQueue<ValueType, unsigned short, Ascending>
392 : public BucketQueue<ValueType, Ascending>
393 {
394 public:
395 typedef BucketQueue<ValueType, Ascending> BaseType;
396
397 PriorityQueue()
398 : BaseType(NumericTraits<unsigned short>::max()+1)
399 {}
400 };
401
402 } // namespace vigra
403
404 #endif // VIGRA_BUCKET_QUEUE_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.10.0 (Mon Nov 18 2013)