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