1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
26 /// Linear time sorting algorithms
35 namespace _radix_sort_bits {
37 template <typename Value>
39 const Value& operator()(const Value& val) {
45 template <typename Value, typename Iterator, typename Functor>
46 Iterator radixSortPartition(Iterator first, Iterator last,
47 Functor functor, Value mask) {
48 while (first != last && !(functor(*first) & mask)) {
55 while (first != last && (functor(*last) & mask)) {
61 std::iter_swap(first, last);
63 if (!(first < last)) {
67 while (!(functor(*first) & mask)) {
71 while (functor(*last) & mask) {
74 if (!(first < last)) {
77 std::iter_swap(first, last);
82 template <typename Iterator, typename Functor>
83 Iterator radixSortSignPartition(Iterator first, Iterator last,
85 while (first != last && functor(*first) < 0) {
92 while (first != last && functor(*last) >= 0) {
98 std::iter_swap(first, last);
100 if (!(first < last)) {
104 while (functor(*first) < 0) {
108 while (functor(*last) >= 0) {
111 if (!(first < last)) {
114 std::iter_swap(first, last);
119 template <typename Value, typename Iterator, typename Functor>
120 void radixIntroSort(Iterator first, Iterator last,
121 Functor functor, Value mask) {
122 while (mask != 0 && last - first > 1) {
123 Iterator cut = radixSortPartition(first, last, functor, mask);
125 radixIntroSort(first, cut, functor, mask);
130 template <typename Value, typename Iterator, typename Functor>
131 void radixSignedSort(Iterator first, Iterator last, Functor functor) {
133 Iterator cut = radixSortSignPartition(first, last, functor);
139 mask = ~0; max_digit = 0;
140 for (it = first; it != cut; ++it) {
141 while ((mask & functor(*it)) != mask) {
146 radixIntroSort(first, cut, functor, 1 << max_digit);
148 mask = 0; max_digit = 0;
149 for (it = cut; it != last; ++it) {
150 while ((mask | functor(*it)) != mask) {
152 mask <<= 1; mask |= 1;
155 radixIntroSort(cut, last, functor, 1 << max_digit);
158 template <typename Value, typename Iterator, typename Functor>
159 void radixUnsignedSort(Iterator first, Iterator last, Functor functor) {
165 for (it = first; it != last; ++it) {
166 while ((mask | functor(*it)) != mask) {
168 mask <<= 1; mask |= 1;
171 radixIntroSort(first, last, functor, 1 << max_digit);
175 template <typename Value,
176 bool sign = std::numeric_limits<Value>::is_signed >
177 struct RadixSortSelector {
178 template <typename Iterator, typename Functor>
179 static void sort(Iterator first, Iterator last, Functor functor) {
180 radixSignedSort<Value>(first, last, functor);
184 template <typename Value>
185 struct RadixSortSelector<Value, false> {
186 template <typename Iterator, typename Functor>
187 static void sort(Iterator first, Iterator last, Functor functor) {
188 radixUnsignedSort<Value>(first, last, functor);
196 /// \brief Sorts the STL compatible range into ascending order.
198 /// The \c radixSort sorts an STL compatible range into ascending
199 /// order. The radix sort algorithm can sort items which are mapped
200 /// to integers with an adaptable unary function \c functor and the
201 /// order will be ascending according to these mapped values.
203 /// It is also possible to use a normal function instead
204 /// of the functor object. If the functor is not given it will use
205 /// the identity function instead.
207 /// This is a special quick sort algorithm where the pivot
208 /// values to split the items are choosen to be 2<sup>k</sup>
210 /// Therefore, the time complexity of the algorithm is O(log(c)*n) and
211 /// it uses O(log(c)) additional space, where \c c is the maximal value
212 /// and \c n is the number of the items in the container.
214 /// \param first The begin of the given range.
215 /// \param last The end of the given range.
216 /// \param functor An adaptible unary function or a normal function
217 /// which maps the items to any integer type which can be either
218 /// signed or unsigned.
220 /// \sa stableRadixSort()
221 template <typename Iterator, typename Functor>
222 void radixSort(Iterator first, Iterator last, Functor functor) {
223 using namespace _radix_sort_bits;
224 typedef typename Functor::result_type Value;
225 RadixSortSelector<Value>::sort(first, last, functor);
228 template <typename Iterator, typename Value, typename Key>
229 void radixSort(Iterator first, Iterator last, Value (*functor)(Key)) {
230 using namespace _radix_sort_bits;
231 RadixSortSelector<Value>::sort(first, last, functor);
234 template <typename Iterator, typename Value, typename Key>
235 void radixSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
236 using namespace _radix_sort_bits;
237 RadixSortSelector<Value>::sort(first, last, functor);
240 template <typename Iterator, typename Value, typename Key>
241 void radixSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
242 using namespace _radix_sort_bits;
243 RadixSortSelector<Value>::sort(first, last, functor);
246 template <typename Iterator, typename Value, typename Key>
247 void radixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
248 using namespace _radix_sort_bits;
249 RadixSortSelector<Value>::sort(first, last, functor);
252 template <typename Iterator>
253 void radixSort(Iterator first, Iterator last) {
254 using namespace _radix_sort_bits;
255 typedef typename std::iterator_traits<Iterator>::value_type Value;
256 RadixSortSelector<Value>::sort(first, last, Identity<Value>());
259 namespace _radix_sort_bits {
261 template <typename Value>
262 unsigned char valueByte(Value value, int byte) {
263 return value >> (std::numeric_limits<unsigned char>::digits * byte);
266 template <typename Functor, typename Key>
267 void stableRadixIntroSort(Key *first, Key *last, Key *target,
268 int byte, Functor functor) {
270 unsigned(std::numeric_limits<unsigned char>::max()) + 1;
271 std::vector<int> counter(size);
272 for (int i = 0; i < size; ++i) {
276 while (first != last) {
277 ++counter[valueByte(functor(*first), byte)];
281 for (int i = 0; i < size; ++i) {
287 target[counter[valueByte(functor(*it), byte)]++] = *it;
292 template <typename Functor, typename Key>
293 void signedStableRadixIntroSort(Key *first, Key *last, Key *target,
294 int byte, Functor functor) {
296 unsigned(std::numeric_limits<unsigned char>::max()) + 1;
297 std::vector<int> counter(size);
298 for (int i = 0; i < size; ++i) {
302 while (first != last) {
303 counter[valueByte(functor(*first), byte)]++;
307 for (int i = size / 2; i < size; ++i) {
312 for (int i = 0; i < size / 2; ++i) {
318 target[counter[valueByte(functor(*it), byte)]++] = *it;
324 template <typename Value, typename Iterator, typename Functor>
325 void stableRadixSignedSort(Iterator first, Iterator last, Functor functor) {
326 if (first == last) return;
327 typedef typename std::iterator_traits<Iterator>::value_type Key;
328 typedef std::allocator<Key> Allocator;
331 int length = std::distance(first, last);
332 Key* buffer = allocator.allocate(2 * length);
335 std::copy(first, last, buffer);
336 for (int i = 0; i < int(sizeof(Value)) - 1; ++i) {
338 stableRadixIntroSort(buffer, buffer + length, buffer + length,
341 stableRadixIntroSort(buffer + length, buffer + 2 * length, buffer,
347 signedStableRadixIntroSort(buffer, buffer + length, buffer + length,
348 sizeof(Value) - 1, functor);
349 std::copy(buffer + length, buffer + 2 * length, first);
351 signedStableRadixIntroSort(buffer + length, buffer + 2 * length,
352 buffer, sizeof(Value) - 1, functor);
353 std::copy(buffer, buffer + length, first);
356 allocator.deallocate(buffer, 2 * length);
359 allocator.deallocate(buffer, 2 * length);
362 template <typename Value, typename Iterator, typename Functor>
363 void stableRadixUnsignedSort(Iterator first, Iterator last,
365 if (first == last) return;
366 typedef typename std::iterator_traits<Iterator>::value_type Key;
367 typedef std::allocator<Key> Allocator;
370 int length = std::distance(first, last);
371 Key *buffer = allocator.allocate(2 * length);
374 std::copy(first, last, buffer);
375 for (int i = 0; i < int(sizeof(Value)); ++i) {
377 stableRadixIntroSort(buffer, buffer + length,
378 buffer + length, i, functor);
380 stableRadixIntroSort(buffer + length, buffer + 2 * length,
386 std::copy(buffer, buffer + length, first);
388 std::copy(buffer + length, buffer + 2 * length, first);
391 allocator.deallocate(buffer, 2 * length);
394 allocator.deallocate(buffer, 2 * length);
399 template <typename Value,
400 bool sign = std::numeric_limits<Value>::is_signed >
401 struct StableRadixSortSelector {
402 template <typename Iterator, typename Functor>
403 static void sort(Iterator first, Iterator last, Functor functor) {
404 stableRadixSignedSort<Value>(first, last, functor);
408 template <typename Value>
409 struct StableRadixSortSelector<Value, false> {
410 template <typename Iterator, typename Functor>
411 static void sort(Iterator first, Iterator last, Functor functor) {
412 stableRadixUnsignedSort<Value>(first, last, functor);
420 /// \brief Sorts the STL compatible range into ascending order in a stable
423 /// This function sorts an STL compatible range into ascending
424 /// order according to an integer mapping in the same as radixSort() does.
426 /// This sorting algorithm is stable, i.e. the order of two equal
427 /// elements remains the same after the sorting.
429 /// This sort algorithm use a radix forward sort on the
430 /// bytes of the integer number. The algorithm sorts the items
431 /// byte-by-byte. First, it counts how many times a byte value occurs
432 /// in the container, then it copies the corresponding items to
433 /// another container in asceding order in O(n) time.
435 /// The time complexity of the algorithm is O(log(c)*n) and
436 /// it uses O(n) additional space, where \c c is the
437 /// maximal value and \c n is the number of the items in the
441 /// \param first The begin of the given range.
442 /// \param last The end of the given range.
443 /// \param functor An adaptible unary function or a normal function
444 /// which maps the items to any integer type which can be either
445 /// signed or unsigned.
447 template <typename Iterator, typename Functor>
448 void stableRadixSort(Iterator first, Iterator last, Functor functor) {
449 using namespace _radix_sort_bits;
450 typedef typename Functor::result_type Value;
451 StableRadixSortSelector<Value>::sort(first, last, functor);
454 template <typename Iterator, typename Value, typename Key>
455 void stableRadixSort(Iterator first, Iterator last, Value (*functor)(Key)) {
456 using namespace _radix_sort_bits;
457 StableRadixSortSelector<Value>::sort(first, last, functor);
460 template <typename Iterator, typename Value, typename Key>
461 void stableRadixSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
462 using namespace _radix_sort_bits;
463 StableRadixSortSelector<Value>::sort(first, last, functor);
466 template <typename Iterator, typename Value, typename Key>
467 void stableRadixSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
468 using namespace _radix_sort_bits;
469 StableRadixSortSelector<Value>::sort(first, last, functor);
472 template <typename Iterator, typename Value, typename Key>
473 void stableRadixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
474 using namespace _radix_sort_bits;
475 StableRadixSortSelector<Value>::sort(first, last, functor);
478 template <typename Iterator>
479 void stableRadixSort(Iterator first, Iterator last) {
480 using namespace _radix_sort_bits;
481 typedef typename std::iterator_traits<Iterator>::value_type Value;
482 StableRadixSortSelector<Value>::sort(first, last, Identity<Value>());