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