|
1 /* -*- C++ -*- |
|
2 * lemon/radix_sort.h - Part of LEMON, a generic C++ optimization library |
|
3 * |
|
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
|
5 * (Egervary Research Group on Combinatorial Optimization, EGRES). |
|
6 * |
|
7 * Permission to use, modify and distribute this software is granted |
|
8 * provided that this copyright notice appears in all copies. For |
|
9 * precise terms see the accompanying LICENSE file. |
|
10 * |
|
11 * This software is provided "AS IS" with no warranty of any kind, |
|
12 * express or implied, and with no claim as to its suitability for any |
|
13 * purpose. |
|
14 * |
|
15 */ |
|
16 |
|
17 #ifndef RADIX_SORT_H |
|
18 #define RADIX_SORT_H |
|
19 |
|
20 /// \ingroup auxdat |
|
21 /// \file |
|
22 /// \brief Radix sort |
|
23 /// |
|
24 |
|
25 #include <vector> |
|
26 #include <limits> |
|
27 #include <iterator> |
|
28 #include <algorithm> |
|
29 |
|
30 #include <lemon/error.h> |
|
31 |
|
32 namespace lemon { |
|
33 |
|
34 namespace _radix_sort_bits { |
|
35 |
|
36 template <typename Value> |
|
37 struct Identity { |
|
38 const Value& operator()(const Value& val) { |
|
39 return val; |
|
40 } |
|
41 }; |
|
42 |
|
43 } |
|
44 |
|
45 template <typename Value, typename Iterator, typename Functor> |
|
46 Iterator radixSortPartition(Iterator first, Iterator last, |
|
47 Functor functor, Value mask) { |
|
48 while (first != last && !(functor(*first) & mask)) { |
|
49 ++first; |
|
50 } |
|
51 if (first == last) { |
|
52 return first; |
|
53 } |
|
54 --last; |
|
55 while (first != last && (functor(*last) & mask)) { |
|
56 --last; |
|
57 } |
|
58 if (first == last) { |
|
59 return first; |
|
60 } |
|
61 std::iter_swap(first, last); |
|
62 ++first; |
|
63 if (!(first < last)) { |
|
64 return first; |
|
65 } |
|
66 while (true) { |
|
67 while (!(functor(*first) & mask)) { |
|
68 ++first; |
|
69 } |
|
70 --last; |
|
71 while (functor(*last) & mask) { |
|
72 --last; |
|
73 } |
|
74 if (!(first < last)) { |
|
75 return first; |
|
76 } |
|
77 std::iter_swap(first, last); |
|
78 ++first; |
|
79 } |
|
80 } |
|
81 |
|
82 template <typename Iterator, typename Functor> |
|
83 Iterator radixSortSignPartition(Iterator first, Iterator last, |
|
84 Functor functor) { |
|
85 while (first != last && functor(*first) < 0) { |
|
86 ++first; |
|
87 } |
|
88 if (first == last) { |
|
89 return first; |
|
90 } |
|
91 --last; |
|
92 while (first != last && functor(*last) >= 0) { |
|
93 --last; |
|
94 } |
|
95 if (first == last) { |
|
96 return first; |
|
97 } |
|
98 std::iter_swap(first, last); |
|
99 ++first; |
|
100 if (!(first < last)) { |
|
101 return first; |
|
102 } |
|
103 while (true) { |
|
104 while (functor(*first) < 0) { |
|
105 ++first; |
|
106 } |
|
107 --last; |
|
108 while (functor(*last) >= 0) { |
|
109 --last; |
|
110 } |
|
111 if (!(first < last)) { |
|
112 return first; |
|
113 } |
|
114 std::iter_swap(first, last); |
|
115 ++first; |
|
116 } |
|
117 } |
|
118 |
|
119 template <typename Value, typename Iterator, typename Functor> |
|
120 void radixIntroSort(Iterator first, Iterator last, |
|
121 Functor functor, Value mask) { |
|
122 while (mask != 0 && last - first > 1) { |
|
123 Iterator cut = radixSortPartition(first, last, functor, mask); |
|
124 mask >>= 1; |
|
125 radixIntroSort(first, cut, functor, mask); |
|
126 first = cut; |
|
127 } |
|
128 } |
|
129 |
|
130 template <typename Value, typename Iterator, typename Functor> |
|
131 void radixSignedSort(Iterator first, Iterator last, Functor functor) { |
|
132 Iterator cut = radixSortSignPartition(first, last, functor); |
|
133 |
|
134 Value mask; |
|
135 int max_digit; |
|
136 Iterator it; |
|
137 |
|
138 mask = 0; max_digit = 0; |
|
139 for (it = first; it != cut; ++it) { |
|
140 if ((mask | functor(*it)) != ~0) { |
|
141 ++max_digit; |
|
142 mask <<= 1; |
|
143 mask |= 1; |
|
144 } |
|
145 } |
|
146 radixIntroSort(first, cut, functor, 1 << max_digit); |
|
147 |
|
148 mask = ~0; max_digit = 0; |
|
149 for (it = cut; it != last; ++it) { |
|
150 if (mask & functor(*it)) { |
|
151 ++max_digit; |
|
152 mask <<= 1; |
|
153 } |
|
154 } |
|
155 radixIntroSort(cut, last, functor, 1 << max_digit); |
|
156 } |
|
157 |
|
158 template <typename Value, typename Iterator, typename Functor> |
|
159 void radixUnsignedSort(Iterator first, Iterator last, Functor functor) { |
|
160 |
|
161 Value mask = ~0; |
|
162 int max_digit = 0; |
|
163 |
|
164 Iterator it; |
|
165 for (it = first; it != last; ++it) { |
|
166 if (mask & functor(*it)) { |
|
167 ++max_digit; |
|
168 mask <<= 1; |
|
169 } |
|
170 } |
|
171 radixIntroSort(first, last, functor, 1 << max_digit); |
|
172 } |
|
173 |
|
174 namespace _radix_sort_bits { |
|
175 |
|
176 template <typename Value, |
|
177 bool sign = std::numeric_limits<Value>::is_signed > |
|
178 struct RadixSortSelector { |
|
179 template <typename Iterator, typename Functor> |
|
180 static void sort(Iterator first, Iterator last, Functor functor) { |
|
181 radixSignedSort<Value>(first, last, functor); |
|
182 } |
|
183 }; |
|
184 |
|
185 template <typename Value> |
|
186 struct RadixSortSelector<Value, false> { |
|
187 template <typename Iterator, typename Functor> |
|
188 static void sort(Iterator first, Iterator last, Functor functor) { |
|
189 radixUnsignedSort<Value>(first, last, functor); |
|
190 } |
|
191 }; |
|
192 |
|
193 } |
|
194 |
|
195 /// \ingroup auxdat |
|
196 /// |
|
197 /// \brief Sorts the stl compatible range into ascending order. |
|
198 /// |
|
199 /// The \c radixSort sorts the stl compatible range into ascending order. |
|
200 /// The radix sort algorithm can sort the items which mapped to an |
|
201 /// integer by the adaptable unary function \c functor and the order |
|
202 /// will be ascending by these mapped values. As function specialization |
|
203 /// there is possible to use a normal function as the functor object |
|
204 /// or if the functor is not given it will use an identity function instead. |
|
205 /// |
|
206 /// This implemented radix sort is a special quick sort which pivot value |
|
207 /// is choosen to partite the items on the next bit. This way, let be |
|
208 /// \c c the maximal capacity and \c n the number of the items in |
|
209 /// the container, the time complexity of the algorithm \c O(log(c)*n) |
|
210 /// and the additional space complexity is \c O(log(c)). |
|
211 /// |
|
212 /// \param first The begin of the given range. |
|
213 /// \param last The end of the given range. |
|
214 /// \param functor An adaptible unary function or a normal function which |
|
215 /// maps the items to any integer type which can be wheter signed or |
|
216 /// unsigned. |
|
217 template <typename Iterator, typename Functor> |
|
218 void radixSort(Iterator first, Iterator last, Functor functor) { |
|
219 using namespace _radix_sort_bits; |
|
220 typedef typename Functor::result_type Value; |
|
221 RadixSortSelector<Value>::sort(first, last, functor); |
|
222 } |
|
223 |
|
224 template <typename Iterator, typename Value, typename Key> |
|
225 void radixSort(Iterator first, Iterator last, Value (*functor)(Key)) { |
|
226 using namespace _radix_sort_bits; |
|
227 RadixSortSelector<Value>::sort(first, last, functor); |
|
228 } |
|
229 |
|
230 template <typename Iterator, typename Value, typename Key> |
|
231 void radixSort(Iterator first, Iterator last, Value& (*functor)(Key)) { |
|
232 using namespace _radix_sort_bits; |
|
233 RadixSortSelector<Value>::sort(first, last, functor); |
|
234 } |
|
235 |
|
236 template <typename Iterator, typename Value, typename Key> |
|
237 void radixSort(Iterator first, Iterator last, Value (*functor)(Key&)) { |
|
238 using namespace _radix_sort_bits; |
|
239 RadixSortSelector<Value>::sort(first, last, functor); |
|
240 } |
|
241 |
|
242 template <typename Iterator, typename Value, typename Key> |
|
243 void radixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) { |
|
244 using namespace _radix_sort_bits; |
|
245 RadixSortSelector<Value>::sort(first, last, functor); |
|
246 } |
|
247 |
|
248 template <typename Iterator> |
|
249 void radixSort(Iterator first, Iterator last) { |
|
250 using namespace _radix_sort_bits; |
|
251 typedef typename std::iterator_traits<Iterator>::value_type Value; |
|
252 RadixSortSelector<Value>::sort(first, last, Identity<Value>()); |
|
253 } |
|
254 |
|
255 template <typename Value> |
|
256 unsigned char valueByte(Value value, int byte) { |
|
257 return *((unsigned char *)(&value) + byte); |
|
258 } |
|
259 |
|
260 template <typename Functor, typename Key> |
|
261 void counterIntroSort(Key *first, Key *last, Key *target, |
|
262 int byte, Functor functor) { |
|
263 const int size = |
|
264 (unsigned int)std::numeric_limits<unsigned char>::max() + 1; |
|
265 int counter[size]; |
|
266 for (int i = 0; i < size; ++i) { |
|
267 counter[i] = 0; |
|
268 } |
|
269 Key *it = first; |
|
270 while (first != last) { |
|
271 ++counter[valueByte(functor(*first), byte)]; |
|
272 ++first; |
|
273 } |
|
274 int prev, num = 0; |
|
275 for (int i = 0; i < size; ++i) { |
|
276 prev = num; |
|
277 num += counter[i]; |
|
278 counter[i] = prev; |
|
279 } |
|
280 while (it != last) { |
|
281 target[counter[valueByte(functor(*it), byte)]++] = *it; |
|
282 ++it; |
|
283 } |
|
284 } |
|
285 |
|
286 template <typename Functor, typename Key> |
|
287 void signedCounterIntroSort(Key *first, Key *last, Key *target, |
|
288 int byte, Functor functor) { |
|
289 const int size = |
|
290 (unsigned int)std::numeric_limits<unsigned char>::max() + 1; |
|
291 int counter[size]; |
|
292 for (int i = 0; i < size; ++i) { |
|
293 counter[i] = 0; |
|
294 } |
|
295 Key *it = first; |
|
296 while (first != last) { |
|
297 counter[valueByte(functor(*first), byte)]++; |
|
298 ++first; |
|
299 } |
|
300 int prev, num = 0; |
|
301 for (int i = size / 2; i < size; ++i) { |
|
302 prev = num; |
|
303 num += counter[i]; |
|
304 counter[i] = prev; |
|
305 } |
|
306 for (int i = 0; i < size / 2; ++i) { |
|
307 prev = num; |
|
308 num += counter[i]; |
|
309 counter[i] = prev; |
|
310 } |
|
311 while (it != last) { |
|
312 target[counter[valueByte(functor(*it), byte)]++] = *it; |
|
313 ++it; |
|
314 } |
|
315 } |
|
316 |
|
317 |
|
318 template <typename Value, typename Iterator, typename Functor> |
|
319 void counterSignedSort(Iterator first, Iterator last, Functor functor) { |
|
320 typedef typename std::iterator_traits<Iterator>::value_type Key; |
|
321 typedef std::allocator<Key> Allocator; |
|
322 Allocator allocator; |
|
323 |
|
324 int length = std::distance(first, last); |
|
325 Key* buffer; |
|
326 buffer = allocator.allocate(2 * length); |
|
327 try { |
|
328 bool dir = true; |
|
329 std::copy(first, last, buffer); |
|
330 for (int i = 0; i < (int)sizeof(Value) - 1; ++i) { |
|
331 if (dir) { |
|
332 counterIntroSort(buffer, buffer + length, buffer + length, |
|
333 i, functor); |
|
334 } else { |
|
335 counterIntroSort(buffer + length, buffer + 2 * length, buffer, |
|
336 i, functor); |
|
337 } |
|
338 dir = !dir; |
|
339 } |
|
340 if (dir) { |
|
341 signedCounterIntroSort(buffer, buffer + length, buffer + length, |
|
342 sizeof(Value) - 1, functor); |
|
343 std::copy(buffer + length, buffer + 2 * length, first); |
|
344 } else { |
|
345 signedCounterIntroSort(buffer + length, buffer + 2 * length, buffer, |
|
346 sizeof(Value) - 1, functor); |
|
347 std::copy(buffer, buffer + length, first); |
|
348 } |
|
349 } catch (...) { |
|
350 allocator.deallocate(buffer, 2 * length); |
|
351 throw; |
|
352 } |
|
353 allocator.deallocate(buffer, 2 * length); |
|
354 } |
|
355 |
|
356 template <typename Value, typename Iterator, typename Functor> |
|
357 void counterUnsignedSort(Iterator first, Iterator last, Functor functor) { |
|
358 typedef typename std::iterator_traits<Iterator>::value_type Key; |
|
359 typedef std::allocator<Key> Allocator; |
|
360 Allocator allocator; |
|
361 |
|
362 int length = std::distance(first, last); |
|
363 Key *buffer; |
|
364 buffer = allocator.allocate(2 * length); |
|
365 try { |
|
366 bool dir = true; |
|
367 std::copy(first, last, buffer); |
|
368 for (int i = 0; i < sizeof(Value); ++i) { |
|
369 if (dir) { |
|
370 counterIntroSort(buffer, buffer + length, buffer + length, |
|
371 i, functor); |
|
372 } else { |
|
373 counterIntroSort(buffer + length, buffer + 2 * length, buffer, |
|
374 i, functor); |
|
375 } |
|
376 dir = !dir; |
|
377 } |
|
378 if (dir) { |
|
379 std::copy(buffer, buffer + length, first); |
|
380 } else { |
|
381 std::copy(buffer + length, buffer + 2 * length, first); |
|
382 } |
|
383 } catch (...) { |
|
384 allocator.deallocate(buffer, 2 * length); |
|
385 throw; |
|
386 } |
|
387 allocator.deallocate(buffer, 2 * length); |
|
388 } |
|
389 |
|
390 namespace _radix_sort_bits { |
|
391 |
|
392 template <typename Value, |
|
393 bool sign = std::numeric_limits<Value>::is_signed > |
|
394 struct CounterSortSelector { |
|
395 template <typename Iterator, typename Functor> |
|
396 static void sort(Iterator first, Iterator last, Functor functor) { |
|
397 counterSignedSort<Value>(first, last, functor); |
|
398 } |
|
399 }; |
|
400 |
|
401 template <typename Value> |
|
402 struct CounterSortSelector<Value, false> { |
|
403 template <typename Iterator, typename Functor> |
|
404 static void sort(Iterator first, Iterator last, Functor functor) { |
|
405 counterUnsignedSort<Value>(first, last, functor); |
|
406 } |
|
407 }; |
|
408 |
|
409 } |
|
410 |
|
411 /// \ingroup auxdat |
|
412 /// |
|
413 /// \brief Sorts stable the stl compatible range into ascending order. |
|
414 /// |
|
415 /// The \c counterSort sorts the stl compatible range into ascending order. |
|
416 /// The counter sort algorithm can sort the items which mapped to an |
|
417 /// integer by the adaptable unary function \c functor and the order |
|
418 /// will be ascending by these mapped values. As function specialization |
|
419 /// there is possible to use a normal function as the functor object |
|
420 /// or if the functor is not given it will use an identity function instead. |
|
421 /// |
|
422 /// This implemented counter sort use a radix forward sort on the bytes of |
|
423 /// the integer. The algorithm can sort the items on a given byte. |
|
424 /// First time it counts how many times occurs a byte value in the container. |
|
425 /// By the occurence number it is possible to copy the container |
|
426 /// in the right order in \c O(n) time. The algorithm sorts the container |
|
427 /// by each bytes in forward direction which sorts the container by the |
|
428 /// whole value. This way, let be |
|
429 /// \c c the maximal capacity and \c n the number of the items in |
|
430 /// the container, the time complexity of the algorithm \c O(log(c)*n) |
|
431 /// and the additional space complexity is \c O(n). |
|
432 /// |
|
433 /// This sorting algorithm is stable so the order of two equal element |
|
434 /// stay in the same order. |
|
435 /// |
|
436 /// \param first The begin of the given range. |
|
437 /// \param last The end of the given range. |
|
438 /// \param functor An adaptible unary function or a normal function which |
|
439 /// maps the items to any integer type which can be wheter signed or |
|
440 /// unsigned. |
|
441 template <typename Iterator, typename Functor> |
|
442 void counterSort(Iterator first, Iterator last, Functor functor) { |
|
443 using namespace _radix_sort_bits; |
|
444 typedef typename Functor::result_type Value; |
|
445 CounterSortSelector<Value>::sort(first, last, functor); |
|
446 } |
|
447 |
|
448 template <typename Iterator, typename Value, typename Key> |
|
449 void counterSort(Iterator first, Iterator last, Value (*functor)(Key)) { |
|
450 using namespace _radix_sort_bits; |
|
451 CounterSortSelector<Value>::sort(first, last, functor); |
|
452 } |
|
453 |
|
454 template <typename Iterator, typename Value, typename Key> |
|
455 void counterSort(Iterator first, Iterator last, Value& (*functor)(Key)) { |
|
456 using namespace _radix_sort_bits; |
|
457 CounterSortSelector<Value>::sort(first, last, functor); |
|
458 } |
|
459 |
|
460 template <typename Iterator, typename Value, typename Key> |
|
461 void counterSort(Iterator first, Iterator last, Value (*functor)(Key&)) { |
|
462 using namespace _radix_sort_bits; |
|
463 CounterSortSelector<Value>::sort(first, last, functor); |
|
464 } |
|
465 |
|
466 template <typename Iterator, typename Value, typename Key> |
|
467 void counterSort(Iterator first, Iterator last, Value& (*functor)(Key&)) { |
|
468 using namespace _radix_sort_bits; |
|
469 CounterSortSelector<Value>::sort(first, last, functor); |
|
470 } |
|
471 |
|
472 template <typename Iterator> |
|
473 void counterSort(Iterator first, Iterator last) { |
|
474 using namespace _radix_sort_bits; |
|
475 typedef typename std::iterator_traits<Iterator>::value_type Value; |
|
476 CounterSortSelector<Value>::sort(first, last, Identity<Value>()); |
|
477 } |
|
478 |
|
479 } |
|
480 |
|
481 |
|
482 |
|
483 #endif |