0
2
0
| ... | ... |
@@ -214,13 +214,13 @@ |
| 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 |
} |
| ... | ... |
@@ -261,14 +261,14 @@ |
| 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 |
} |
| ... | ... |
@@ -287,14 +287,14 @@ |
| 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 |
} |
| ... | ... |
@@ -319,68 +319,69 @@ |
| 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 {
|
| ... | ... |
@@ -394,24 +395,24 @@ |
| 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 |
| ... | ... |
@@ -420,13 +421,13 @@ |
| 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. |
| ... | ... |
@@ -441,46 +442,46 @@ |
| 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 |
| ... | ... |
@@ -96,31 +96,31 @@ |
| 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 |
{
|
| ... | ... |
@@ -138,10 +138,10 @@ |
| 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)