gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Rename counterSort to stableRadixSort
0 2 0
default
2 files changed with 42 insertions and 41 deletions:
↑ Collapse diff ↑
Ignore white space 64 line context
... ...
@@ -188,299 +188,300 @@
188 188
        radixUnsignedSort<Value>(first, last, functor);
189 189
      }
190 190
    };
191 191

	
192 192
  }
193 193

	
194 194
  /// \ingroup auxalg
195 195
  ///
196 196
  /// \brief Sorts the STL compatible range into ascending order.
197 197
  ///
198 198
  /// The \c radixSort sorts an STL compatible range into ascending
199 199
  /// order.  The radix sort algorithm can sort items which are mapped
200 200
  /// to integers with an adaptable unary function \c functor and the
201 201
  /// order will be ascending according to these mapped values.
202 202
  ///
203 203
  /// It is also possible to use a normal function instead
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 counterSort()
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;
237 237
    RadixSortSelector<Value>::sort(first, last, functor);
238 238
  }
239 239

	
240 240
  template <typename Iterator, typename Value, typename Key>
241 241
  void radixSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
242 242
    using namespace _radix_sort_bits;
243 243
    RadixSortSelector<Value>::sort(first, last, functor);
244 244
  }
245 245

	
246 246
  template <typename Iterator, typename Value, typename Key>
247 247
  void radixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
248 248
    using namespace _radix_sort_bits;
249 249
    RadixSortSelector<Value>::sort(first, last, functor);
250 250
  }
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 counterSignedSort(Iterator first, Iterator last, Functor functor) {
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 counterUnsignedSort(Iterator first, Iterator last, Functor functor) {
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 CounterSortSelector {
401
    struct StableRadixSortSelector {
401 402
      template <typename Iterator, typename Functor>
402 403
      static void sort(Iterator first, Iterator last, Functor functor) {
403
        counterSignedSort<Value>(first, last, functor);
404
        stableRadixSignedSort<Value>(first, last, functor);
404 405
      }
405 406
    };
406 407

	
407 408
    template <typename Value>
408
    struct CounterSortSelector<Value, false> {
409
    struct StableRadixSortSelector<Value, false> {
409 410
      template <typename Iterator, typename Functor>
410 411
      static void sort(Iterator first, Iterator last, Functor functor) {
411
        counterUnsignedSort<Value>(first, last, functor);
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
  /// element remains the same after the sorting.
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 counterSort(Iterator first, Iterator last, Functor functor) {
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
    CounterSortSelector<Value>::sort(first, last, functor);
451
    StableRadixSortSelector<Value>::sort(first, last, functor);
451 452
  }
452 453

	
453 454
  template <typename Iterator, typename Value, typename Key>
454
  void counterSort(Iterator first, Iterator last, Value (*functor)(Key)) {
455
  void stableRadixSort(Iterator first, Iterator last, Value (*functor)(Key)) {
455 456
    using namespace _radix_sort_bits;
456
    CounterSortSelector<Value>::sort(first, last, functor);
457
    StableRadixSortSelector<Value>::sort(first, last, functor);
457 458
  }
458 459

	
459 460
  template <typename Iterator, typename Value, typename Key>
460
  void counterSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
461
  void stableRadixSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
461 462
    using namespace _radix_sort_bits;
462
    CounterSortSelector<Value>::sort(first, last, functor);
463
    StableRadixSortSelector<Value>::sort(first, last, functor);
463 464
  }
464 465

	
465 466
  template <typename Iterator, typename Value, typename Key>
466
  void counterSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
467
  void stableRadixSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
467 468
    using namespace _radix_sort_bits;
468
    CounterSortSelector<Value>::sort(first, last, functor);
469
    StableRadixSortSelector<Value>::sort(first, last, functor);
469 470
  }
470 471

	
471 472
  template <typename Iterator, typename Value, typename Key>
472
  void counterSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
473
  void stableRadixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
473 474
    using namespace _radix_sort_bits;
474
    CounterSortSelector<Value>::sort(first, last, functor);
475
    StableRadixSortSelector<Value>::sort(first, last, functor);
475 476
  }
476 477

	
477 478
  template <typename Iterator>
478
  void counterSort(Iterator first, Iterator last) {
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
    CounterSortSelector<Value>::sort(first, last, Identity<Value>());
482
    StableRadixSortSelector<Value>::sort(first, last, Identity<Value>());
482 483
  }
483 484

	
484 485
}
485 486

	
486 487
#endif
Ignore white space 6 line context
... ...
@@ -70,78 +70,78 @@
70 70
    for (int i = 0; i < n; ++i) {
71 71
      check(data1[i] == data2[i], "Test failed");
72 72
    }
73 73

	
74 74
    radixSort(data2.begin(), data2.end(), Negate());
75 75
    for (int i = 0; i < n; ++i) {
76 76
      check(data1[i] == data2[n - 1 - i], "Test failed");
77 77
    }
78 78

	
79 79
    radixSort(data2.begin(), data2.end(), negate);
80 80
    for (int i = 0; i < n; ++i) {
81 81
      check(data1[i] == data2[n - 1 - i], "Test failed");
82 82
    }
83 83

	
84 84
  }
85 85

	
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 checkCounterSort() {
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
    counterSort(data2.begin(), data2.end());
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
    counterSort(data2.begin(), data2.end(), Negate());
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
    counterSort(data2.begin(), data2.end(), negate);
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
  checkCounterSort();
144
  checkStableRadixSort();
145 145

	
146 146
  return 0;
147 147
}
0 comments (0 inline)