gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Update to 2009 plus whitespace unification
0 2 0
default
2 files changed with 4 insertions and 4 deletions:
↑ Collapse diff ↑
Ignore white space 256 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5
 * Copyright (C) 2003-2008
5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef RADIX_SORT_H
20 20
#define RADIX_SORT_H
21 21

	
22 22
/// \ingroup auxalg
23 23
/// \file
24 24
/// \brief Radix sort
25 25
///
26 26
/// Linear time sorting algorithms
27 27

	
28 28
#include <vector>
29 29
#include <limits>
30 30
#include <iterator>
31 31
#include <algorithm>
32 32

	
33 33
namespace lemon {
34 34

	
35 35
  namespace _radix_sort_bits {
36 36

	
37 37
    template <typename Value>
38 38
    struct Identity {
39 39
      const Value& operator()(const Value& val) {
40 40
        return val;
41 41
      }
42 42
    };
43 43

	
44 44

	
45 45
    template <typename Value, typename Iterator, typename Functor>
46 46
    Iterator radixSortPartition(Iterator first, Iterator last,
47 47
                                Functor functor, Value mask) {
48 48
      while (first != last && !(functor(*first) & mask)) {
49 49
        ++first;
50 50
      }
51 51
      if (first == last) {
52 52
        return first;
53 53
      }
54 54
      --last;
55 55
      while (first != last && (functor(*last) & mask)) {
56 56
        --last;
57 57
      }
58 58
      if (first == last) {
59 59
        return first;
60 60
      }
61 61
      std::iter_swap(first, last);
62 62
      ++first;
63 63
      if (!(first < last)) {
64 64
        return first;
65 65
      }
66 66
      while (true) {
67 67
        while (!(functor(*first) & mask)) {
68 68
          ++first;
69 69
        }
70 70
        --last;
71 71
        while (functor(*last) & mask) {
72 72
          --last;
73 73
        }
74 74
        if (!(first < last)) {
75 75
          return first;
76 76
        }
77 77
        std::iter_swap(first, last);
78 78
        ++first;
79 79
      }
80 80
    }
81 81

	
82 82
    template <typename Iterator, typename Functor>
83 83
    Iterator radixSortSignPartition(Iterator first, Iterator last,
84 84
                                    Functor functor) {
85 85
      while (first != last && functor(*first) < 0) {
86 86
        ++first;
87 87
      }
88 88
      if (first == last) {
89 89
        return first;
90 90
      }
91 91
      --last;
92 92
      while (first != last && functor(*last) >= 0) {
93 93
        --last;
94 94
      }
95 95
      if (first == last) {
96 96
        return first;
97 97
      }
98 98
      std::iter_swap(first, last);
99 99
      ++first;
100 100
      if (!(first < last)) {
101 101
        return first;
102 102
      }
103 103
      while (true) {
104 104
        while (functor(*first) < 0) {
105 105
          ++first;
106 106
        }
107 107
        --last;
108 108
        while (functor(*last) >= 0) {
109 109
          --last;
110 110
        }
111 111
        if (!(first < last)) {
112 112
          return first;
113 113
        }
114 114
        std::iter_swap(first, last);
115 115
        ++first;
116 116
      }
117 117
    }
118 118

	
119 119
    template <typename Value, typename Iterator, typename Functor>
120 120
    void radixIntroSort(Iterator first, Iterator last,
121 121
                        Functor functor, Value mask) {
122 122
      while (mask != 0 && last - first > 1) {
123 123
        Iterator cut = radixSortPartition(first, last, functor, mask);
124 124
        mask >>= 1;
125 125
        radixIntroSort(first, cut, functor, mask);
126 126
        first = cut;
127 127
      }
128 128
    }
129 129

	
130 130
    template <typename Value, typename Iterator, typename Functor>
131 131
    void radixSignedSort(Iterator first, Iterator last, Functor functor) {
132 132

	
133 133
      Iterator cut = radixSortSignPartition(first, last, functor);
... ...
@@ -223,265 +223,265 @@
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 267
    void stableRadixIntroSort(Key *first, Key *last, Key *target,
268 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 293
    void signedStableRadixIntroSort(Key *first, Key *last, Key *target,
294 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 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 338
            stableRadixIntroSort(buffer, buffer + length, buffer + length,
339 339
                                 i, functor);
340 340
          } else {
341 341
            stableRadixIntroSort(buffer + length, buffer + 2 * length, buffer,
342 342
                                 i, functor);
343 343
          }
344 344
          dir = !dir;
345 345
        }
346 346
        if (dir) {
347 347
          signedStableRadixIntroSort(buffer, buffer + length, buffer + length,
348 348
                                     sizeof(Value) - 1, functor);
349 349
          std::copy(buffer + length, buffer + 2 * length, first);
350 350
        }        else {
351
          signedStableRadixIntroSort(buffer + length, buffer + 2 * length, 
351
          signedStableRadixIntroSort(buffer + length, buffer + 2 * length,
352 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 stableRadixUnsignedSort(Iterator first, Iterator last, 
363
    void stableRadixUnsignedSort(Iterator first, Iterator last,
364 364
                                 Functor functor) {
365 365
      if (first == last) return;
366 366
      typedef typename std::iterator_traits<Iterator>::value_type Key;
367 367
      typedef std::allocator<Key> Allocator;
368 368
      Allocator allocator;
369 369

	
370 370
      int length = std::distance(first, last);
371 371
      Key *buffer = allocator.allocate(2 * length);
372 372
      try {
373 373
        bool dir = true;
374 374
        std::copy(first, last, buffer);
375 375
        for (int i = 0; i < int(sizeof(Value)); ++i) {
376 376
          if (dir) {
377 377
            stableRadixIntroSort(buffer, buffer + length,
378 378
                                 buffer + length, i, functor);
379 379
          } else {
380 380
            stableRadixIntroSort(buffer + length, buffer + 2 * length,
381 381
                                 buffer, i, functor);
382 382
          }
383 383
          dir = !dir;
384 384
        }
385 385
        if (dir) {
386 386
          std::copy(buffer, buffer + length, first);
387 387
        }        else {
388 388
          std::copy(buffer + length, buffer + 2 * length, first);
389 389
        }
390 390
      } catch (...) {
391 391
        allocator.deallocate(buffer, 2 * length);
392 392
        throw;
393 393
      }
394 394
      allocator.deallocate(buffer, 2 * length);
395 395
    }
396 396

	
397 397

	
398 398

	
399 399
    template <typename Value,
400 400
              bool sign = std::numeric_limits<Value>::is_signed >
401 401
    struct StableRadixSortSelector {
402 402
      template <typename Iterator, typename Functor>
403 403
      static void sort(Iterator first, Iterator last, Functor functor) {
404 404
        stableRadixSignedSort<Value>(first, last, functor);
405 405
      }
406 406
    };
407 407

	
408 408
    template <typename Value>
409 409
    struct StableRadixSortSelector<Value, false> {
410 410
      template <typename Iterator, typename Functor>
411 411
      static void sort(Iterator first, Iterator last, Functor functor) {
412 412
        stableRadixUnsignedSort<Value>(first, last, functor);
413 413
      }
414 414
    };
415 415

	
416 416
  }
417 417

	
418 418
  /// \ingroup auxalg
419 419
  ///
420 420
  /// \brief Sorts the STL compatible range into ascending order in a stable
421 421
  /// way.
422 422
  ///
423 423
  /// This function sorts an STL compatible range into ascending
424 424
  /// order according to an integer mapping in the same as radixSort() does.
425 425
  ///
426 426
  /// This sorting algorithm is stable, i.e. the order of two equal
427 427
  /// elements remains the same after the sorting.
428 428
  ///
429 429
  /// This sort algorithm  use a radix forward sort on the
430 430
  /// bytes of the integer number. The algorithm sorts the items
431 431
  /// byte-by-byte. First, it counts how many times a byte value occurs
432 432
  /// in the container, then it copies the corresponding items to
433 433
  /// another container in asceding order in \c O(n) time.
434 434
  ///
435 435
  /// The time complexity of the algorithm is \f$ O(\log(c)n) \f$ and
436 436
  /// it uses \f$ O(n) \f$, additional space, where \c c is the
437 437
  /// maximal value and \c n is the number of the items in the
438 438
  /// container.
439 439
  ///
440 440

	
441 441
  /// \param first The begin of the given range.
442 442
  /// \param last The end of the given range.
443 443
  /// \param functor An adaptible unary function or a normal function
444 444
  /// which maps the items to any integer type which can be either
445 445
  /// signed or unsigned.
446 446
  /// \sa radixSort()
447 447
  template <typename Iterator, typename Functor>
448 448
  void stableRadixSort(Iterator first, Iterator last, Functor functor) {
449 449
    using namespace _radix_sort_bits;
450 450
    typedef typename Functor::result_type Value;
451 451
    StableRadixSortSelector<Value>::sort(first, last, functor);
452 452
  }
453 453

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

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

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

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

	
478 478
  template <typename Iterator>
479 479
  void stableRadixSort(Iterator first, Iterator last) {
480 480
    using namespace _radix_sort_bits;
481 481
    typedef typename std::iterator_traits<Iterator>::value_type Value;
482 482
    StableRadixSortSelector<Value>::sort(first, last, Identity<Value>());
483 483
  }
484 484

	
485 485
}
486 486

	
487 487
#endif
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5
 * Copyright (C) 2003-2008
5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#include <lemon/time_measure.h>
20 20
#include <lemon/smart_graph.h>
21 21
#include <lemon/maps.h>
22 22
#include <lemon/radix_sort.h>
23 23
#include <lemon/math.h>
24 24

	
25 25
#include "test_tools.h"
26 26

	
27 27
#include <vector>
28 28
#include <algorithm>
29 29

	
30 30
using namespace lemon;
31 31

	
32 32
static const int n = 10000;
33 33

	
34 34
struct Negate {
35 35
  typedef int argument_type;
36 36
  typedef int result_type;
37 37
  int operator()(int a) { return - a; }
38 38
};
39 39

	
40 40
int negate(int a) { return - a; }
41 41

	
42 42

	
43 43
void generateIntSequence(int n, std::vector<int>& data) {
44 44
  int prime = 9973;
45 45
  int root = 136, value = 1;
46 46
  for (int i = 0; i < n; ++i) {
47 47
    data.push_back(value - prime / 2);
48 48
    value = (value * root) % prime;
49 49
  }
50 50
}
51 51

	
52 52
void generateCharSequence(int n, std::vector<unsigned char>& data) {
53 53
  int prime = 251;
54 54
  int root = 3, value = root;
55 55
  for (int i = 0; i < n; ++i) {
56 56
    data.push_back(static_cast<unsigned char>(value));
57 57
    value = (value * root) % prime;
58 58
  }
59 59
}
60 60

	
61 61
void checkRadixSort() {
62 62
  {
63 63
    std::vector<int> data1;
64 64
    generateIntSequence(n, data1);
65 65

	
66 66
    std::vector<int> data2(data1);
67 67
    std::sort(data1.begin(), data1.end());
68 68

	
69 69
    radixSort(data2.begin(), data2.end());
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 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());
0 comments (0 inline)