0
2
0
... | ... |
@@ -204,33 +204,33 @@ |
204 | 204 |
/// of the functor object. If the functor is not given it will use |
205 | 205 |
/// the identity function instead. |
206 | 206 |
/// |
207 | 207 |
/// This is a special quick sort algorithm where the pivot |
208 | 208 |
/// values to split the items are choosen to be \f$ 2^k \f$ for each \c k. |
209 | 209 |
/// Therefore, the time complexity of the |
210 | 210 |
/// algorithm is \f$ O(\log(c)n) \f$ and it uses \f$ O(\log(c)) \f$, |
211 | 211 |
/// additional space, where \c c is the maximal value and \c n is the |
212 | 212 |
/// number of the items in the container. |
213 | 213 |
/// |
214 | 214 |
/// \param first The begin of the given range. |
215 | 215 |
/// \param last The end of the given range. |
216 | 216 |
/// \param functor An adaptible unary function or a normal function |
217 | 217 |
/// which maps the items to any integer type which can be either |
218 | 218 |
/// signed or unsigned. |
219 | 219 |
/// |
220 |
/// \sa |
|
220 |
/// \sa stableRadixSort() |
|
221 | 221 |
template <typename Iterator, typename Functor> |
222 | 222 |
void radixSort(Iterator first, Iterator last, Functor functor) { |
223 | 223 |
using namespace _radix_sort_bits; |
224 | 224 |
typedef typename Functor::result_type Value; |
225 | 225 |
RadixSortSelector<Value>::sort(first, last, functor); |
226 | 226 |
} |
227 | 227 |
|
228 | 228 |
template <typename Iterator, typename Value, typename Key> |
229 | 229 |
void radixSort(Iterator first, Iterator last, Value (*functor)(Key)) { |
230 | 230 |
using namespace _radix_sort_bits; |
231 | 231 |
RadixSortSelector<Value>::sort(first, last, functor); |
232 | 232 |
} |
233 | 233 |
|
234 | 234 |
template <typename Iterator, typename Value, typename Key> |
235 | 235 |
void radixSort(Iterator first, Iterator last, Value& (*functor)(Key)) { |
236 | 236 |
using namespace _radix_sort_bits; |
... | ... |
@@ -251,236 +251,237 @@ |
251 | 251 |
|
252 | 252 |
template <typename Iterator> |
253 | 253 |
void radixSort(Iterator first, Iterator last) { |
254 | 254 |
using namespace _radix_sort_bits; |
255 | 255 |
typedef typename std::iterator_traits<Iterator>::value_type Value; |
256 | 256 |
RadixSortSelector<Value>::sort(first, last, Identity<Value>()); |
257 | 257 |
} |
258 | 258 |
|
259 | 259 |
namespace _radix_sort_bits { |
260 | 260 |
|
261 | 261 |
template <typename Value> |
262 | 262 |
unsigned char valueByte(Value value, int byte) { |
263 | 263 |
return value >> (std::numeric_limits<unsigned char>::digits * byte); |
264 | 264 |
} |
265 | 265 |
|
266 | 266 |
template <typename Functor, typename Key> |
267 |
void counterIntroSort(Key *first, Key *last, Key *target, |
|
268 |
int byte, Functor functor) { |
|
267 |
void stableRadixIntroSort(Key *first, Key *last, Key *target, |
|
268 |
int byte, Functor functor) { |
|
269 | 269 |
const int size = |
270 | 270 |
unsigned(std::numeric_limits<unsigned char>::max()) + 1; |
271 | 271 |
std::vector<int> counter(size); |
272 | 272 |
for (int i = 0; i < size; ++i) { |
273 | 273 |
counter[i] = 0; |
274 | 274 |
} |
275 | 275 |
Key *it = first; |
276 | 276 |
while (first != last) { |
277 | 277 |
++counter[valueByte(functor(*first), byte)]; |
278 | 278 |
++first; |
279 | 279 |
} |
280 | 280 |
int prev, num = 0; |
281 | 281 |
for (int i = 0; i < size; ++i) { |
282 | 282 |
prev = num; |
283 | 283 |
num += counter[i]; |
284 | 284 |
counter[i] = prev; |
285 | 285 |
} |
286 | 286 |
while (it != last) { |
287 | 287 |
target[counter[valueByte(functor(*it), byte)]++] = *it; |
288 | 288 |
++it; |
289 | 289 |
} |
290 | 290 |
} |
291 | 291 |
|
292 | 292 |
template <typename Functor, typename Key> |
293 |
void signedCounterIntroSort(Key *first, Key *last, Key *target, |
|
294 |
int byte, Functor functor) { |
|
293 |
void signedStableRadixIntroSort(Key *first, Key *last, Key *target, |
|
294 |
int byte, Functor functor) { |
|
295 | 295 |
const int size = |
296 | 296 |
unsigned(std::numeric_limits<unsigned char>::max()) + 1; |
297 | 297 |
std::vector<int> counter(size); |
298 | 298 |
for (int i = 0; i < size; ++i) { |
299 | 299 |
counter[i] = 0; |
300 | 300 |
} |
301 | 301 |
Key *it = first; |
302 | 302 |
while (first != last) { |
303 | 303 |
counter[valueByte(functor(*first), byte)]++; |
304 | 304 |
++first; |
305 | 305 |
} |
306 | 306 |
int prev, num = 0; |
307 | 307 |
for (int i = size / 2; i < size; ++i) { |
308 | 308 |
prev = num; |
309 | 309 |
num += counter[i]; |
310 | 310 |
counter[i] = prev; |
311 | 311 |
} |
312 | 312 |
for (int i = 0; i < size / 2; ++i) { |
313 | 313 |
prev = num; |
314 | 314 |
num += counter[i]; |
315 | 315 |
counter[i] = prev; |
316 | 316 |
} |
317 | 317 |
while (it != last) { |
318 | 318 |
target[counter[valueByte(functor(*it), byte)]++] = *it; |
319 | 319 |
++it; |
320 | 320 |
} |
321 | 321 |
} |
322 | 322 |
|
323 | 323 |
|
324 | 324 |
template <typename Value, typename Iterator, typename Functor> |
325 |
void |
|
325 |
void stableRadixSignedSort(Iterator first, Iterator last, Functor functor) { |
|
326 | 326 |
if (first == last) return; |
327 | 327 |
typedef typename std::iterator_traits<Iterator>::value_type Key; |
328 | 328 |
typedef std::allocator<Key> Allocator; |
329 | 329 |
Allocator allocator; |
330 | 330 |
|
331 | 331 |
int length = std::distance(first, last); |
332 | 332 |
Key* buffer = allocator.allocate(2 * length); |
333 | 333 |
try { |
334 | 334 |
bool dir = true; |
335 | 335 |
std::copy(first, last, buffer); |
336 | 336 |
for (int i = 0; i < int(sizeof(Value)) - 1; ++i) { |
337 | 337 |
if (dir) { |
338 |
counterIntroSort(buffer, buffer + length, buffer + length, |
|
339 |
i, functor); |
|
338 |
stableRadixIntroSort(buffer, buffer + length, buffer + length, |
|
339 |
i, functor); |
|
340 | 340 |
} else { |
341 |
counterIntroSort(buffer + length, buffer + 2 * length, buffer, |
|
342 |
i, functor); |
|
341 |
stableRadixIntroSort(buffer + length, buffer + 2 * length, buffer, |
|
342 |
i, functor); |
|
343 | 343 |
} |
344 | 344 |
dir = !dir; |
345 | 345 |
} |
346 | 346 |
if (dir) { |
347 |
signedCounterIntroSort(buffer, buffer + length, buffer + length, |
|
348 |
sizeof(Value) - 1, functor); |
|
347 |
signedStableRadixIntroSort(buffer, buffer + length, buffer + length, |
|
348 |
sizeof(Value) - 1, functor); |
|
349 | 349 |
std::copy(buffer + length, buffer + 2 * length, first); |
350 | 350 |
} else { |
351 |
signedCounterIntroSort(buffer + length, buffer + 2 * length, buffer, |
|
352 |
sizeof(Value) - 1, functor); |
|
351 |
signedStableRadixIntroSort(buffer + length, buffer + 2 * length, |
|
352 |
buffer, sizeof(Value) - 1, functor); |
|
353 | 353 |
std::copy(buffer, buffer + length, first); |
354 | 354 |
} |
355 | 355 |
} catch (...) { |
356 | 356 |
allocator.deallocate(buffer, 2 * length); |
357 | 357 |
throw; |
358 | 358 |
} |
359 | 359 |
allocator.deallocate(buffer, 2 * length); |
360 | 360 |
} |
361 | 361 |
|
362 | 362 |
template <typename Value, typename Iterator, typename Functor> |
363 |
void |
|
363 |
void stableRadixUnsignedSort(Iterator first, Iterator last, |
|
364 |
Functor functor) { |
|
364 | 365 |
if (first == last) return; |
365 | 366 |
typedef typename std::iterator_traits<Iterator>::value_type Key; |
366 | 367 |
typedef std::allocator<Key> Allocator; |
367 | 368 |
Allocator allocator; |
368 | 369 |
|
369 | 370 |
int length = std::distance(first, last); |
370 | 371 |
Key *buffer = allocator.allocate(2 * length); |
371 | 372 |
try { |
372 | 373 |
bool dir = true; |
373 | 374 |
std::copy(first, last, buffer); |
374 | 375 |
for (int i = 0; i < int(sizeof(Value)); ++i) { |
375 | 376 |
if (dir) { |
376 |
counterIntroSort(buffer, buffer + length, |
|
377 |
buffer + length, i, functor); |
|
377 |
stableRadixIntroSort(buffer, buffer + length, |
|
378 |
buffer + length, i, functor); |
|
378 | 379 |
} else { |
379 |
counterIntroSort(buffer + length, buffer + 2 * length, |
|
380 |
buffer, i, functor); |
|
380 |
stableRadixIntroSort(buffer + length, buffer + 2 * length, |
|
381 |
buffer, i, functor); |
|
381 | 382 |
} |
382 | 383 |
dir = !dir; |
383 | 384 |
} |
384 | 385 |
if (dir) { |
385 | 386 |
std::copy(buffer, buffer + length, first); |
386 | 387 |
} else { |
387 | 388 |
std::copy(buffer + length, buffer + 2 * length, first); |
388 | 389 |
} |
389 | 390 |
} catch (...) { |
390 | 391 |
allocator.deallocate(buffer, 2 * length); |
391 | 392 |
throw; |
392 | 393 |
} |
393 | 394 |
allocator.deallocate(buffer, 2 * length); |
394 | 395 |
} |
395 | 396 |
|
396 | 397 |
|
397 | 398 |
|
398 | 399 |
template <typename Value, |
399 | 400 |
bool sign = std::numeric_limits<Value>::is_signed > |
400 |
struct |
|
401 |
struct StableRadixSortSelector { |
|
401 | 402 |
template <typename Iterator, typename Functor> |
402 | 403 |
static void sort(Iterator first, Iterator last, Functor functor) { |
403 |
|
|
404 |
stableRadixSignedSort<Value>(first, last, functor); |
|
404 | 405 |
} |
405 | 406 |
}; |
406 | 407 |
|
407 | 408 |
template <typename Value> |
408 |
struct |
|
409 |
struct StableRadixSortSelector<Value, false> { |
|
409 | 410 |
template <typename Iterator, typename Functor> |
410 | 411 |
static void sort(Iterator first, Iterator last, Functor functor) { |
411 |
|
|
412 |
stableRadixUnsignedSort<Value>(first, last, functor); |
|
412 | 413 |
} |
413 | 414 |
}; |
414 | 415 |
|
415 | 416 |
} |
416 | 417 |
|
417 | 418 |
/// \ingroup auxalg |
418 | 419 |
/// |
419 | 420 |
/// \brief Sorts the STL compatible range into ascending order in a stable |
420 | 421 |
/// way. |
421 | 422 |
/// |
422 | 423 |
/// This function sorts an STL compatible range into ascending |
423 | 424 |
/// order according to an integer mapping in the same as radixSort() does. |
424 | 425 |
/// |
425 | 426 |
/// This sorting algorithm is stable, i.e. the order of two equal |
426 |
/// |
|
427 |
/// elements remains the same after the sorting. |
|
427 | 428 |
/// |
428 | 429 |
/// This sort algorithm use a radix forward sort on the |
429 | 430 |
/// bytes of the integer number. The algorithm sorts the items |
430 | 431 |
/// byte-by-byte. First, it counts how many times a byte value occurs |
431 | 432 |
/// in the container, then it copies the corresponding items to |
432 | 433 |
/// another container in asceding order in \c O(n) time. |
433 | 434 |
/// |
434 | 435 |
/// The time complexity of the algorithm is \f$ O(\log(c)n) \f$ and |
435 | 436 |
/// it uses \f$ O(n) \f$, additional space, where \c c is the |
436 | 437 |
/// maximal value and \c n is the number of the items in the |
437 | 438 |
/// container. |
438 | 439 |
/// |
439 | 440 |
|
440 | 441 |
/// \param first The begin of the given range. |
441 | 442 |
/// \param last The end of the given range. |
442 | 443 |
/// \param functor An adaptible unary function or a normal function |
443 | 444 |
/// which maps the items to any integer type which can be either |
444 | 445 |
/// signed or unsigned. |
445 | 446 |
/// \sa radixSort() |
446 | 447 |
template <typename Iterator, typename Functor> |
447 |
void |
|
448 |
void stableRadixSort(Iterator first, Iterator last, Functor functor) { |
|
448 | 449 |
using namespace _radix_sort_bits; |
449 | 450 |
typedef typename Functor::result_type Value; |
450 |
|
|
451 |
StableRadixSortSelector<Value>::sort(first, last, functor); |
|
451 | 452 |
} |
452 | 453 |
|
453 | 454 |
template <typename Iterator, typename Value, typename Key> |
454 |
void |
|
455 |
void stableRadixSort(Iterator first, Iterator last, Value (*functor)(Key)) { |
|
455 | 456 |
using namespace _radix_sort_bits; |
456 |
|
|
457 |
StableRadixSortSelector<Value>::sort(first, last, functor); |
|
457 | 458 |
} |
458 | 459 |
|
459 | 460 |
template <typename Iterator, typename Value, typename Key> |
460 |
void |
|
461 |
void stableRadixSort(Iterator first, Iterator last, Value& (*functor)(Key)) { |
|
461 | 462 |
using namespace _radix_sort_bits; |
462 |
|
|
463 |
StableRadixSortSelector<Value>::sort(first, last, functor); |
|
463 | 464 |
} |
464 | 465 |
|
465 | 466 |
template <typename Iterator, typename Value, typename Key> |
466 |
void |
|
467 |
void stableRadixSort(Iterator first, Iterator last, Value (*functor)(Key&)) { |
|
467 | 468 |
using namespace _radix_sort_bits; |
468 |
|
|
469 |
StableRadixSortSelector<Value>::sort(first, last, functor); |
|
469 | 470 |
} |
470 | 471 |
|
471 | 472 |
template <typename Iterator, typename Value, typename Key> |
472 |
void |
|
473 |
void stableRadixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) { |
|
473 | 474 |
using namespace _radix_sort_bits; |
474 |
|
|
475 |
StableRadixSortSelector<Value>::sort(first, last, functor); |
|
475 | 476 |
} |
476 | 477 |
|
477 | 478 |
template <typename Iterator> |
478 |
void |
|
479 |
void stableRadixSort(Iterator first, Iterator last) { |
|
479 | 480 |
using namespace _radix_sort_bits; |
480 | 481 |
typedef typename std::iterator_traits<Iterator>::value_type Value; |
481 |
|
|
482 |
StableRadixSortSelector<Value>::sort(first, last, Identity<Value>()); |
|
482 | 483 |
} |
483 | 484 |
|
484 | 485 |
} |
485 | 486 |
|
486 | 487 |
#endif |
... | ... |
@@ -86,62 +86,62 @@ |
86 | 86 |
{ |
87 | 87 |
std::vector<unsigned char> data1(n); |
88 | 88 |
generateCharSequence(n, data1); |
89 | 89 |
|
90 | 90 |
std::vector<unsigned char> data2(data1); |
91 | 91 |
std::sort(data1.begin(), data1.end()); |
92 | 92 |
|
93 | 93 |
radixSort(data2.begin(), data2.end()); |
94 | 94 |
for (int i = 0; i < n; ++i) { |
95 | 95 |
check(data1[i] == data2[i], "Test failed"); |
96 | 96 |
} |
97 | 97 |
|
98 | 98 |
} |
99 | 99 |
} |
100 | 100 |
|
101 | 101 |
|
102 |
void |
|
102 |
void checkStableRadixSort() { |
|
103 | 103 |
{ |
104 | 104 |
std::vector<int> data1; |
105 | 105 |
generateIntSequence(n, data1); |
106 | 106 |
|
107 | 107 |
std::vector<int> data2(data1); |
108 | 108 |
std::sort(data1.begin(), data1.end()); |
109 | 109 |
|
110 |
|
|
110 |
stableRadixSort(data2.begin(), data2.end()); |
|
111 | 111 |
for (int i = 0; i < n; ++i) { |
112 | 112 |
check(data1[i] == data2[i], "Test failed"); |
113 | 113 |
} |
114 | 114 |
|
115 |
|
|
115 |
stableRadixSort(data2.begin(), data2.end(), Negate()); |
|
116 | 116 |
for (int i = 0; i < n; ++i) { |
117 | 117 |
check(data1[i] == data2[n - 1 - i], "Test failed"); |
118 | 118 |
} |
119 | 119 |
|
120 |
|
|
120 |
stableRadixSort(data2.begin(), data2.end(), negate); |
|
121 | 121 |
for (int i = 0; i < n; ++i) { |
122 | 122 |
check(data1[i] == data2[n - 1 - i], "Test failed"); |
123 | 123 |
} |
124 | 124 |
} |
125 | 125 |
|
126 | 126 |
{ |
127 | 127 |
std::vector<unsigned char> data1(n); |
128 | 128 |
generateCharSequence(n, data1); |
129 | 129 |
|
130 | 130 |
std::vector<unsigned char> data2(data1); |
131 | 131 |
std::sort(data1.begin(), data1.end()); |
132 | 132 |
|
133 | 133 |
radixSort(data2.begin(), data2.end()); |
134 | 134 |
for (int i = 0; i < n; ++i) { |
135 | 135 |
check(data1[i] == data2[i], "Test failed"); |
136 | 136 |
} |
137 | 137 |
|
138 | 138 |
} |
139 | 139 |
} |
140 | 140 |
|
141 | 141 |
int main() { |
142 | 142 |
|
143 | 143 |
checkRadixSort(); |
144 |
|
|
144 |
checkStableRadixSort(); |
|
145 | 145 |
|
146 | 146 |
return 0; |
147 | 147 |
} |
0 comments (0 inline)