1 /******************************************************************************
2 * src/SortAlgo.cpp
3 *
4 * Implementations is many sorting algorithms.
5 *
6 * Note that these implementations may not be as good/fast as possible. Some
7 * are modified so that the visualization is more instructive.
8 *
9 * Futhermore, some algorithms are annotated using the mark() and watch()
10 * functions from SortArray. These functions add colors to the illustratation
11 * and thereby makes the algorithm's visualization easier to explain.
12 *
13 ******************************************************************************
14 * The algorithms in this file are copyrighted by the original authors. All
15 * code is freely available.
16 *
17 * The source code added by myself (Timo Bingmann) and all modifications are
18 * copyright (C) 2013-2014 Timo Bingmann <tb@panthema.net>
19 *
20 * This program is free software: you can redistribute it and/or modify it
21 * under the terms of the GNU General Public License as published by the Free
22 * Software Foundation, either version 3 of the License, or (at your option)
23 * any later version.
24 *
25 * This program is distributed in the hope that it will be useful, but WITHOUT
26 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
27 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
28 * more details.
29 *
30 * You should have received a copy of the GNU General Public License along with
31 * this program. If not, see <http://www.gnu.org/licenses/>.
32 *****************************************************************************/
33
34 #include "SortAlgo.h"
35
36 #include <algorithm>
37 #include <numeric>
38 #include <limits>
39 #include <inttypes.h>
40
41 typedef ArrayItem value_type;
42
43 // inversion count limit for iterator instrumented algorithms
44 const unsigned int inversion_count_instrumented = 512;
45
46 const struct AlgoEntry g_algolist[] =
47 {
48 { _("Selection Sort"), &SelectionSort, UINT_MAX, UINT_MAX,
49 wxEmptyString },
50 { _("Insertion Sort"), &InsertionSort, UINT_MAX, UINT_MAX,
51 wxEmptyString },
52 { _("Binary Insertion Sort"), &BinaryInsertionSort, UINT_MAX, UINT_MAX,
53 wxEmptyString },
54 { _("Merge Sort"), &MergeSort, UINT_MAX, 512,
55 _("Merge sort which merges two sorted sequences into a shadow array,"
56 "and then copies it back to the shown array.") },
57 { _("Merge Sort (iterative)"), &MergeSortIterative, UINT_MAX, 512,
58 _("Merge sort variant which iteratively merges "
59 "subarrays of sizes of powers of two.") },
60 { _("Quick Sort (LR ptrs)"), &QuickSortLR, UINT_MAX, UINT_MAX,
61 _("Quick sort variant with left and right pointers.") },
62 { _("Quick Sort (LL ptrs)"), &QuickSortLL, UINT_MAX, UINT_MAX,
63 _("Quick sort variant from 3rd edition of CLRS: two pointers on left.") },
64 { _("Quick Sort (ternary, LR ptrs)"), &QuickSortTernaryLR, UINT_MAX, UINT_MAX,
65 _("Ternary-split quick sort variant, adapted from multikey quicksort by "
66 "Bentley & Sedgewick: partitions \"=<?>=\" using two pairs of pointers "
67 "at left and right, then copied to middle.") },
68 { _("Quick Sort (ternary, LL ptrs)"), &QuickSortTernaryLL, UINT_MAX, UINT_MAX,
69 _("Ternary-split quick sort variant: partitions \"<>?=\" using two "
70 "pointers at left and one at right. Afterwards copies the \"=\" to middle.") },
71 { _("Quick Sort (dual pivot)"), &QuickSortDualPivot, UINT_MAX, UINT_MAX,
72 _("Dual pivot quick sort variant: partitions \"<1<2?>\" using three pointers, "
73 "two at left and one at right.") },
74 { _("Bubble Sort"), &BubbleSort, UINT_MAX, UINT_MAX,
75 wxEmptyString },
76 { _("Cocktail Shaker Sort"), &CocktailShakerSort, UINT_MAX, UINT_MAX,
77 wxEmptyString },
78 { _("Gnome Sort"), &GnomeSort, UINT_MAX, UINT_MAX,
79 wxEmptyString },
80 { _("Comb Sort"), &CombSort, UINT_MAX, UINT_MAX,
81 wxEmptyString },
82 { _("Shell Sort"), &ShellSort, UINT_MAX, 1024,
83 wxEmptyString },
84 { _("Heap Sort"), &HeapSort, UINT_MAX, UINT_MAX,
85 wxEmptyString },
86 { _("Smooth Sort"), &SmoothSort, UINT_MAX, 1024,
87 wxEmptyString },
88 { _("Odd-Even Sort"), &OddEvenSort, UINT_MAX, 1024,
89 wxEmptyString },
90 // older sequential implementation, which really makes little sense to do
91 //{ _("Bitonic Sort"), &BitonicSort, UINT_MAX, UINT_MAX, wxEmptyString },
92 { _("Batcher's Bitonic Sort"), &BitonicSortNetwork, UINT_MAX, UINT_MAX,
93 wxEmptyString },
94 { _("Batcher's Odd-Even Merge Sort"), &BatcherSortNetwork, UINT_MAX, UINT_MAX,
95 wxEmptyString },
96 { _("Cycle Sort"), &CycleSort, 512, UINT_MAX,
97 wxEmptyString },
98 { _("Radix Sort (LSD)"), &RadixSortLSD, UINT_MAX, 512,
99 _("Least significant digit radix sort, which copies item into a shadow "
100 "array during counting.") },
101 { _("Radix Sort (MSD)"), &RadixSortMSD, UINT_MAX, UINT_MAX,
102 _("Most significant digit radix sort, which permutes items in-place by walking cycles.") },
103 { _("std::sort (gcc)"), &StlSort, UINT_MAX, inversion_count_instrumented,
104 wxEmptyString },
105 { _("std::stable_sort (gcc)"), &StlStableSort, UINT_MAX, inversion_count_instrumented,
106 wxEmptyString },
107 { _("std::sort_heap (gcc)"), &StlHeapSort, UINT_MAX, inversion_count_instrumented,
108 wxEmptyString },
109 { _("Tim Sort"), &TimSort, UINT_MAX, inversion_count_instrumented,
110 wxEmptyString },
111 { _("Block Merge Sort (WikiSort)"), &WikiSort, UINT_MAX, inversion_count_instrumented,
112 _("An O(1) place O(n log n) time stable merge sort.") },
113 { _("Bogo Sort"), &BogoSort, 10, UINT_MAX,
114 wxEmptyString },
115 { _("Bozo Sort"), &BozoSort, 10, UINT_MAX,
116 wxEmptyString },
117 { _("Stooge Sort"), &StoogeSort, 256, inversion_count_instrumented,
118 wxEmptyString },
119 { _("Slow Sort"), &SlowSort, 128, inversion_count_instrumented,
120 wxEmptyString }
121 };
122
123 const size_t g_algolist_size = sizeof(g_algolist) / sizeof(g_algolist[0]);
124
125 const struct AlgoEntry* g_algolist_end = g_algolist + g_algolist_size;
126
127 // ****************************************************************************
128 // *** Selection Sort
129
SelectionSort(SortArray & A)130 void SelectionSort(SortArray& A)
131 {
132 volatile ssize_t jMin = 0;
133 A.watch(&jMin, 3);
134
135 for (size_t i = 0; i < A.size()-1; ++i)
136 {
137 jMin = i;
138
139 for (size_t j = i+1; j < A.size(); ++j)
140 {
141 if (A[j] < A[jMin]) {
142 A.mark_swap(j, jMin);
143 jMin = j;
144 }
145 }
146
147 A.swap(i, jMin);
148
149 // mark the last good element
150 if (i > 0) A.unmark(i-1);
151 A.mark(i);
152 }
153 A.unwatch_all();
154 }
155
156 // ****************************************************************************
157 // *** Insertion Sort
158
159 // swaps every time (keeps all values visible)
InsertionSort(SortArray & A)160 void InsertionSort(SortArray& A)
161 {
162 for (size_t i = 1; i < A.size(); ++i)
163 {
164 value_type key = A[i];
165 A.mark(i);
166
167 ssize_t j = i - 1;
168 while (j >= 0 && A[j] > key)
169 {
170 A.swap(j, j+1);
171 j--;
172 }
173
174 A.unmark(i);
175 }
176 }
177
178 // with extra item on stack
InsertionSort2(SortArray & A)179 void InsertionSort2(SortArray& A)
180 {
181 for (size_t i = 1; i < A.size(); ++i)
182 {
183 value_type tmp, key = A[i];
184 A.mark(i);
185
186 ssize_t j = i - 1;
187 while (j >= 0 && (tmp = A[j]) > key)
188 {
189 A.set(j + 1, tmp);
190 j--;
191 }
192 A.set(j + 1, key);
193
194 A.unmark(i);
195 }
196 }
197
198 // swaps every time (keeps all values visible)
BinaryInsertionSort(SortArray & A)199 void BinaryInsertionSort(SortArray& A)
200 {
201 for (size_t i = 1; i < A.size(); ++i)
202 {
203 value_type key = A[i];
204 A.mark(i);
205
206 int lo = 0, hi = i;
207 while (lo < hi) {
208 int mid = (lo + hi) / 2;
209 if (key <= A[mid])
210 hi = mid;
211 else
212 lo = mid + 1;
213 }
214
215 // item has to go into position lo
216
217 ssize_t j = i - 1;
218 while (j >= lo)
219 {
220 A.swap(j, j+1);
221 j--;
222 }
223
224 A.unmark(i);
225 }
226 }
227
228 // ****************************************************************************
229 // *** Merge Sort (out-of-place with sentinels)
230
231 // by myself (Timo Bingmann)
232
Merge(SortArray & A,size_t lo,size_t mid,size_t hi)233 void Merge(SortArray& A, size_t lo, size_t mid, size_t hi)
234 {
235 // mark merge boundaries
236 A.mark(lo);
237 A.mark(mid,3);
238 A.mark(hi-1);
239
240 // allocate output
241 std::vector<value_type> out(hi-lo);
242
243 // merge
244 size_t i = lo, j = mid, o = 0; // first and second halves
245 while (i < mid && j < hi)
246 {
247 // copy out for fewer time steps
248 value_type ai = A[i], aj = A[j];
249
250 out[o++] = (ai < aj ? (++i, ai) : (++j, aj));
251 }
252
253 // copy rest
254 while (i < mid) out[o++] = A[i++];
255 while (j < hi) out[o++] = A[j++];
256
257 ASSERT(o == hi-lo);
258
259 A.unmark(mid);
260
261 // copy back
262 for (i = 0; i < hi-lo; ++i)
263 A.set(lo + i, out[i]);
264
265 A.unmark(lo);
266 A.unmark(hi-1);
267 }
268
MergeSort(SortArray & A,size_t lo,size_t hi)269 void MergeSort(SortArray& A, size_t lo, size_t hi)
270 {
271 if (lo + 1 < hi)
272 {
273 size_t mid = (lo + hi) / 2;
274
275 MergeSort(A, lo, mid);
276 MergeSort(A, mid, hi);
277
278 Merge(A, lo, mid, hi);
279 }
280 }
281
MergeSort(SortArray & A)282 void MergeSort(SortArray& A)
283 {
284 return MergeSort(A, 0, A.size());
285 }
286
MergeSortIterative(SortArray & A)287 void MergeSortIterative(SortArray& A)
288 {
289 for (size_t s = 1; s < A.size(); s *= 2)
290 {
291 for (size_t i = 0; i + s < A.size(); i += 2 * s)
292 {
293 Merge(A, i, i + s,
294 std::min(i + 2 * s, A.size()));
295 }
296 }
297 }
298
299 // ****************************************************************************
300 // *** Quick Sort Pivot Selection
301
302 QuickSortPivotType g_quicksort_pivot = PIVOT_FIRST;
303
304 // some quicksort variants use hi inclusive and some exclusive, we require it
305 // to be _exclusive_. hi == array.end()!
QuickSortSelectPivot(SortArray & A,ssize_t lo,ssize_t hi)306 ssize_t QuickSortSelectPivot(SortArray& A, ssize_t lo, ssize_t hi)
307 {
308 if (g_quicksort_pivot == PIVOT_FIRST)
309 return lo;
310
311 if (g_quicksort_pivot == PIVOT_LAST)
312 return hi-1;
313
314 if (g_quicksort_pivot == PIVOT_MID)
315 return (lo + hi) / 2;
316
317 if (g_quicksort_pivot == PIVOT_RANDOM)
318 return lo + (rand() % (hi - lo));
319
320 if (g_quicksort_pivot == PIVOT_MEDIAN3)
321 {
322 ssize_t mid = (lo + hi) / 2;
323
324 // cases if two are equal
325 if (A[lo] == A[mid]) return lo;
326 if (A[lo] == A[hi-1] || A[mid] == A[hi-1]) return hi-1;
327
328 // cases if three are different
329 return A[lo] < A[mid]
330 ? (A[mid] < A[hi-1] ? mid : (A[lo] < A[hi-1] ? hi-1 : lo))
331 : (A[mid] > A[hi-1] ? mid : (A[lo] < A[hi-1] ? lo : hi-1));
332 }
333
334 return lo;
335 }
336
QuickSortPivotText()337 wxArrayString QuickSortPivotText()
338 {
339 wxArrayString sl;
340
341 sl.Add( _("First Item") );
342 sl.Add( _("Last Item") );
343 sl.Add( _("Middle Item") );
344 sl.Add( _("Random Item") );
345 sl.Add( _("Median of Three") );
346
347 return sl;
348 }
349
350 // ****************************************************************************
351 // *** Quick Sort LR (in-place, pointers at left and right, pivot is middle element)
352
353 // by myself (Timo Bingmann), based on Hoare's original code
354
QuickSortLR(SortArray & A,ssize_t lo,ssize_t hi)355 void QuickSortLR(SortArray& A, ssize_t lo, ssize_t hi)
356 {
357 // pick pivot and watch
358 volatile ssize_t p = QuickSortSelectPivot(A, lo, hi+1);
359
360 value_type pivot = A[p];
361 A.watch(&p, 2);
362
363 volatile ssize_t i = lo, j = hi;
364 A.watch(&i, 3);
365 A.watch(&j, 3);
366
367 while (i <= j)
368 {
369 while (A[i] < pivot)
370 i++;
371
372 while (A[j] > pivot)
373 j--;
374
375 if (i <= j)
376 {
377 A.swap(i,j);
378
379 // follow pivot if it is swapped
380 if (p == i) p = j;
381 else if (p == j) p = i;
382
383 i++, j--;
384 }
385 }
386
387 A.unwatch_all();
388
389 if (lo < j)
390 QuickSortLR(A, lo, j);
391
392 if (i < hi)
393 QuickSortLR(A, i, hi);
394 }
395
QuickSortLR(SortArray & A)396 void QuickSortLR(SortArray& A)
397 {
398 return QuickSortLR(A, 0, A.size()-1);
399 }
400
401 // ****************************************************************************
402 // *** Quick Sort LL (in-place, two pointers at left, pivot is first element and moved to right)
403
404 // by myself (Timo Bingmann), based on CLRS' 3rd edition
405
PartitionLL(SortArray & A,size_t lo,size_t hi)406 size_t PartitionLL(SortArray& A, size_t lo, size_t hi)
407 {
408 // pick pivot and move to back
409 size_t p = QuickSortSelectPivot(A, lo, hi);
410
411 value_type pivot = A[p];
412 A.swap(p, hi-1);
413 A.mark(hi-1);
414
415 volatile ssize_t i = lo;
416 A.watch(&i, 3);
417
418 for (size_t j = lo; j < hi-1; ++j)
419 {
420 if (A[j] <= pivot) {
421 A.swap(i, j);
422 ++i;
423 }
424 }
425
426 A.swap(i, hi-1);
427 A.unmark(hi-1);
428 A.unwatch_all();
429
430 return i;
431 }
432
QuickSortLL(SortArray & A,size_t lo,size_t hi)433 void QuickSortLL(SortArray& A, size_t lo, size_t hi)
434 {
435 if (lo + 1 < hi)
436 {
437 size_t mid = PartitionLL(A, lo, hi);
438
439 QuickSortLL(A, lo, mid);
440 QuickSortLL(A, mid+1, hi);
441 }
442 }
443
QuickSortLL(SortArray & A)444 void QuickSortLL(SortArray& A)
445 {
446 return QuickSortLL(A, 0, A.size());
447 }
448
449 // ****************************************************************************
450 // *** Quick Sort Ternary (in-place, two pointers at left, pivot is first element and moved to right)
451
452 // by myself (Timo Bingmann), loosely based on multikey quicksort by B&S
453
QuickSortTernaryLR(SortArray & A,ssize_t lo,ssize_t hi)454 void QuickSortTernaryLR(SortArray& A, ssize_t lo, ssize_t hi)
455 {
456 if (hi <= lo) return;
457
458 int cmp;
459
460 // pick pivot and swap to back
461 ssize_t piv = QuickSortSelectPivot(A, lo, hi+1);
462 A.swap(piv, hi);
463 A.mark(hi);
464
465 const value_type& pivot = A[hi];
466
467 // schema: |p === |i <<< | ??? |j >>> |q === |piv
468 volatile ssize_t i = lo, j = hi-1;
469 volatile ssize_t p = lo, q = hi-1;
470
471 A.watch(&i, 3);
472 A.watch(&j, 3);
473
474 for (;;)
475 {
476 // partition on left
477 while (i <= j && (cmp = A[i].cmp(pivot)) <= 0)
478 {
479 if (cmp == 0) {
480 A.mark(p,4);
481 A.swap(i, p++);
482 }
483 ++i;
484 }
485
486 // partition on right
487 while (i <= j && (cmp = A[j].cmp(pivot)) >= 0)
488 {
489 if (cmp == 0) {
490 A.mark(q,4);
491 A.swap(j, q--);
492 }
493 --j;
494 }
495
496 if (i > j) break;
497
498 // swap item between < > regions
499 A.swap(i++, j--);
500 }
501
502 // swap pivot to right place
503 A.swap(i,hi);
504 A.mark_swap(i,hi);
505
506 ssize_t num_less = i - p;
507 ssize_t num_greater = q - j;
508
509 // swap equal ranges into center, but avoid swapping equal elements
510 j = i-1; i = i+1;
511
512 ssize_t pe = lo + std::min(p-lo, num_less);
513 for (ssize_t k = lo; k < pe; k++, j--) {
514 A.swap(k,j);
515 A.mark_swap(k,j);
516 }
517
518 ssize_t qe = hi-1 - std::min(hi-1-q, num_greater-1); // one already greater at end
519 for (ssize_t k = hi-1; k > qe; k--, i++) {
520 A.swap(i,k);
521 A.mark_swap(i,k);
522 }
523
524 A.unwatch_all();
525 A.unmark_all();
526
527 QuickSortTernaryLR(A, lo, lo + num_less - 1);
528 QuickSortTernaryLR(A, hi - num_greater + 1, hi);
529 }
530
QuickSortTernaryLR(SortArray & A)531 void QuickSortTernaryLR(SortArray& A)
532 {
533 return QuickSortTernaryLR(A, 0, A.size()-1);
534 }
535
536 // ****************************************************************************
537 // *** Quick Sort LL (in-place, two pointers at left, pivot is first element and moved to right)
538
539 // by myself (Timo Bingmann)
540
PartitionTernaryLL(SortArray & A,ssize_t lo,ssize_t hi)541 std::pair<ssize_t,ssize_t> PartitionTernaryLL(SortArray& A, ssize_t lo, ssize_t hi)
542 {
543 // pick pivot and swap to back
544 ssize_t p = QuickSortSelectPivot(A, lo, hi);
545
546 value_type pivot = A[p];
547 A.swap(p, hi-1);
548 A.mark(hi-1);
549
550 volatile ssize_t i = lo, k = hi-1;
551 A.watch(&i, 3);
552
553 for (ssize_t j = lo; j < k; ++j)
554 {
555 int cmp = A[j].cmp(pivot); // ternary comparison
556 if (cmp == 0) {
557 A.swap(--k, j);
558 --j; // reclassify A[j]
559 A.mark(k,4);
560 }
561 else if (cmp < 0) {
562 A.swap(i++, j);
563 }
564 }
565
566 // unwatch i, because the pivot is swapped there
567 // in the first step of the following swap loop.
568 A.unwatch_all();
569
570 ssize_t j = i + (hi-k);
571
572 for (ssize_t s = 0; s < hi-k; ++s) {
573 A.swap(i+s, hi-1-s);
574 A.mark_swap(i+s, hi-1-s);
575 }
576 A.unmark_all();
577
578 return std::make_pair(i,j);
579 }
580
QuickSortTernaryLL(SortArray & A,size_t lo,size_t hi)581 void QuickSortTernaryLL(SortArray& A, size_t lo, size_t hi)
582 {
583 if (lo + 1 < hi)
584 {
585 std::pair<ssize_t,ssize_t> mid = PartitionTernaryLL(A, lo, hi);
586
587 QuickSortTernaryLL(A, lo, mid.first);
588 QuickSortTernaryLL(A, mid.second, hi);
589 }
590 }
591
QuickSortTernaryLL(SortArray & A)592 void QuickSortTernaryLL(SortArray& A)
593 {
594 return QuickSortTernaryLL(A, 0, A.size());
595 }
596
597 // ****************************************************************************
598 // *** Dual-Pivot Quick Sort
599
600 // by Sebastian Wild
601
dualPivotYaroslavskiy(class SortArray & a,int left,int right)602 void dualPivotYaroslavskiy(class SortArray& a, int left, int right)
603 {
604 if (right > left)
605 {
606 if (a[left] > a[right]) {
607 a.swap(left, right);
608 }
609
610 const value_type p = a[left];
611 const value_type q = a[right];
612
613 a.mark(left);
614 a.mark(right);
615
616 volatile ssize_t l = left + 1;
617 volatile ssize_t g = right - 1;
618 volatile ssize_t k = l;
619
620 a.watch(&l, 3);
621 a.watch(&g, 3);
622 a.watch(&k, 3);
623
624 while (k <= g)
625 {
626 if (a[k] < p) {
627 a.swap(k, l);
628 ++l;
629 }
630 else if (a[k] >= q) {
631 while (a[g] > q && k < g) --g;
632 a.swap(k, g);
633 --g;
634
635 if (a[k] < p) {
636 a.swap(k, l);
637 ++l;
638 }
639 }
640 ++k;
641 }
642 --l;
643 ++g;
644 a.swap(left, l);
645 a.swap(right, g);
646
647 a.unmark_all();
648 a.unwatch_all();
649
650 dualPivotYaroslavskiy(a, left, l - 1);
651 dualPivotYaroslavskiy(a, l + 1, g - 1);
652 dualPivotYaroslavskiy(a, g + 1, right);
653 }
654 }
655
QuickSortDualPivot(class SortArray & a)656 void QuickSortDualPivot(class SortArray& a)
657 {
658 return dualPivotYaroslavskiy(a, 0, a.size()-1);
659 }
660
661 // ****************************************************************************
662 // *** Bubble Sort
663
BubbleSort(SortArray & A)664 void BubbleSort(SortArray& A)
665 {
666 for (size_t i = 0; i < A.size()-1; ++i)
667 {
668 for (size_t j = 0; j < A.size()-1 - i; ++j)
669 {
670 if (A[j] > A[j + 1])
671 {
672 A.swap(j, j+1);
673 }
674 }
675 }
676 }
677
678 // ****************************************************************************
679 // *** Cocktail Shaker Sort
680
681 // from http://de.wikibooks.org/wiki/Algorithmen_und_Datenstrukturen_in_C/_Shakersort
682
CocktailShakerSort(SortArray & A)683 void CocktailShakerSort(SortArray& A)
684 {
685 size_t lo = 0, hi = A.size()-1, mov = lo;
686
687 while (lo < hi)
688 {
689 for (size_t i = hi; i > lo; --i)
690 {
691 if (A[i-1] > A[i])
692 {
693 A.swap(i-1, i);
694 mov = i;
695 }
696 }
697
698 lo = mov;
699
700 for (size_t i = lo; i < hi; ++i)
701 {
702 if (A[i] > A[i+1])
703 {
704 A.swap(i, i+1);
705 mov = i;
706 }
707 }
708
709 hi = mov;
710 }
711 }
712
713 // ****************************************************************************
714 // *** Gnome Sort
715
716 // from http://en.wikipediA.org/wiki/Gnome_sort
717
GnomeSort(SortArray & A)718 void GnomeSort(SortArray& A)
719 {
720 for (size_t i = 1; i < A.size(); )
721 {
722 if (A[i] >= A[i-1])
723 {
724 ++i;
725 }
726 else
727 {
728 A.swap(i, i-1);
729 if (i > 1) --i;
730 }
731 }
732 }
733
734 // ****************************************************************************
735 // *** Comb Sort
736
737 // from http://en.wikipediA.org/wiki/Comb_sort
738
CombSort(SortArray & A)739 void CombSort(SortArray& A)
740 {
741 const double shrink = 1.3;
742
743 bool swapped = false;
744 size_t gap = A.size();
745
746 while ((gap > 1) || swapped)
747 {
748 if (gap > 1) {
749 gap = (size_t)((float)gap / shrink);
750 }
751
752 swapped = false;
753
754 for (size_t i = 0; gap + i < A.size(); ++i)
755 {
756 if (A[i] > A[i + gap])
757 {
758 A.swap(i, i+gap);
759 swapped = true;
760 }
761 }
762 }
763 }
764
765 // ****************************************************************************
766 // *** Odd-Even Sort
767
768 // from http://en.wikipediA.org/wiki/Odd%E2%80%93even_sort
769
OddEvenSort(SortArray & A)770 void OddEvenSort(SortArray& A)
771 {
772 bool sorted = false;
773
774 while (!sorted)
775 {
776 sorted = true;
777
778 for (size_t i = 1; i < A.size()-1; i += 2)
779 {
780 if(A[i] > A[i+1])
781 {
782 A.swap(i, i+1);
783 sorted = false;
784 }
785 }
786
787 for (size_t i = 0; i < A.size()-1; i += 2)
788 {
789 if(A[i] > A[i+1])
790 {
791 A.swap(i, i+1);
792 sorted = false;
793 }
794 }
795 }
796 }
797
798 // ****************************************************************************
799 // *** Shell Sort
800
801 // with gaps by Robert Sedgewick from http://www.cs.princeton.edu/~rs/shell/shell.c
802
ShellSort(SortArray & A)803 void ShellSort(SortArray& A)
804 {
805 size_t incs[16] = { 1391376, 463792, 198768, 86961, 33936,
806 13776, 4592, 1968, 861, 336,
807 112, 48, 21, 7, 3, 1 };
808
809 for (size_t k = 0; k < 16; k++)
810 {
811 for (size_t h = incs[k], i = h; i < A.size(); i++)
812 {
813 value_type v = A[i];
814 size_t j = i;
815
816 while (j >= h && A[j-h] > v)
817 {
818 A.set(j, A[j-h]);
819 j -= h;
820 }
821
822 A.set(j, v);
823 }
824 }
825 }
826
827 // ****************************************************************************
828 // *** Heap Sort
829
830 // heavily adapted from http://www.codecodex.com/wiki/Heapsort
831
isPowerOfTwo(size_t x)832 bool isPowerOfTwo(size_t x)
833 {
834 return ((x != 0) && !(x & (x - 1)));
835 }
836
prevPowerOfTwo(uint32_t x)837 uint32_t prevPowerOfTwo(uint32_t x)
838 {
839 x |= x >> 1; x |= x >> 2; x |= x >> 4;
840 x |= x >> 8; x |= x >> 16;
841 return x - (x >> 1);
842 }
843
largestPowerOfTwoLessThan(int n)844 int largestPowerOfTwoLessThan(int n)
845 {
846 int k = 1;
847 while (k < n) k = k << 1;
848 return k >> 1;
849 }
850
HeapSort(SortArray & A)851 void HeapSort(SortArray& A)
852 {
853 size_t n = A.size(), i = n / 2;
854
855 // mark heap levels with different colors
856 for (size_t j = i; j < n; ++j)
857 A.mark(j, log(prevPowerOfTwo(j+1)) / log(2) + 4);
858
859 while (1)
860 {
861 if (i > 0) {
862 // build heap, sift A[i] down the heap
863 i--;
864 }
865 else {
866 // pop largest element from heap: swap front to back, and sift
867 // front A[0] down the heap
868 n--;
869 if (n == 0) return;
870 A.swap(0,n);
871
872 A.mark(n);
873 if (n+1 < A.size()) A.unmark(n+1);
874 }
875
876 size_t parent = i;
877 size_t child = i*2 + 1;
878
879 // sift operation - push the value of A[i] down the heap
880 while (child < n)
881 {
882 if (child + 1 < n && A[child + 1] > A[child]) {
883 child++;
884 }
885 if (A[child] > A[parent]) {
886 A.swap(parent, child);
887 parent = child;
888 child = parent*2+1;
889 }
890 else {
891 break;
892 }
893 }
894
895 // mark heap levels with different colors
896 A.mark(i, log(prevPowerOfTwo(i+1)) / log(2) + 4);
897 }
898
899 }
900
901 // ****************************************************************************
902 // *** Radix Sort (counting sort, most significant digit (MSD) first, in-place redistribute)
903
904 // by myself (Timo Bingmann)
905
RadixSortMSD(SortArray & A,size_t lo,size_t hi,size_t depth)906 void RadixSortMSD(SortArray& A, size_t lo, size_t hi, size_t depth)
907 {
908 A.mark(lo); A.mark(hi-1);
909
910 // radix and base calculations
911 const unsigned int RADIX = 4;
912
913 unsigned int pmax = floor( log(A.array_max()+1) / log(RADIX) );
914 ASSERT(depth <= pmax);
915
916 size_t base = pow(RADIX, pmax - depth);
917
918 // count digits
919 std::vector<size_t> count(RADIX, 0);
920
921 for (size_t i = lo; i < hi; ++i)
922 {
923 size_t r = A[i].get() / base % RADIX;
924 ASSERT(r < RADIX);
925 count[r]++;
926 }
927
928 // inclusive prefix sum
929 std::vector<size_t> bkt(RADIX, 0);
930 std::partial_sum(count.begin(), count.end(), bkt.begin());
931
932 // mark bucket boundaries
933 for (size_t i = 0; i < bkt.size(); ++i) {
934 if (bkt[i] == 0) continue;
935 A.mark(lo + bkt[i]-1, 3);
936 }
937
938 // reorder items in-place by walking cycles
939 for (size_t i=0, j; i < (hi-lo); )
940 {
941 while ( (j = --bkt[ (A[lo+i].get() / base % RADIX) ]) > i )
942 {
943 A.swap(lo + i, lo + j);
944 }
945 i += count[ (A[lo+i].get() / base % RADIX) ];
946 }
947
948 A.unmark_all();
949
950 // no more depth to sort?
951 if (depth+1 > pmax) return;
952
953 // recurse on buckets
954 size_t sum = lo;
955 for (size_t i = 0; i < RADIX; ++i)
956 {
957 if (count[i] > 1)
958 RadixSortMSD(A, sum, sum+count[i], depth+1);
959 sum += count[i];
960 }
961 }
962
RadixSortMSD(SortArray & A)963 void RadixSortMSD(SortArray& A)
964 {
965 return RadixSortMSD(A, 0, A.size(), 0);
966 }
967
968 // ****************************************************************************
969 // *** Radix Sort (counting sort, least significant digit (LSD) first, out-of-place redistribute)
970
971 // by myself (Timo Bingmann)
972
RadixSortLSD(SortArray & A)973 void RadixSortLSD(SortArray& A)
974 {
975 // radix and base calculations
976 const unsigned int RADIX = 4;
977
978 unsigned int pmax = ceil( log(A.array_max()+1) / log(RADIX) );
979
980 for (unsigned int p = 0; p < pmax; ++p)
981 {
982 size_t base = pow(RADIX, p);
983
984 // count digits and copy data
985 std::vector<size_t> count(RADIX, 0);
986 std::vector<value_type> copy(A.size());
987
988 for (size_t i = 0; i < A.size(); ++i)
989 {
990 size_t r = (copy[i] = A[i]).get() / base % RADIX;
991 ASSERT(r < RADIX);
992 count[r]++;
993 }
994
995 // exclusive prefix sum
996 std::vector<size_t> bkt(RADIX+1, 0);
997 std::partial_sum(count.begin(), count.end(), bkt.begin()+1);
998
999 // mark bucket boundaries
1000 for (size_t i = 0; i < bkt.size()-1; ++i) {
1001 if (bkt[i] >= A.size()) continue;
1002 A.mark(bkt[i], 3);
1003 }
1004
1005 // redistribute items back into array (stable)
1006 for (size_t i=0; i < A.size(); ++i)
1007 {
1008 size_t r = copy[i].get() / base % RADIX;
1009 A.set( bkt[r]++, copy[i] );
1010 }
1011
1012 A.unmark_all();
1013 }
1014 }
1015
1016 // ****************************************************************************
1017 // *** Use STL Sorts via Iterator Adapters
1018
StlSort(SortArray & A)1019 void StlSort(SortArray& A)
1020 {
1021 std::sort(MyIterator(&A,0), MyIterator(&A,A.size()));
1022 }
1023
StlStableSort(SortArray & A)1024 void StlStableSort(SortArray& A)
1025 {
1026 std::stable_sort(MyIterator(&A,0), MyIterator(&A,A.size()));
1027 }
1028
StlHeapSort(SortArray & A)1029 void StlHeapSort(SortArray& A)
1030 {
1031 std::make_heap(MyIterator(&A,0), MyIterator(&A,A.size()));
1032 std::sort_heap(MyIterator(&A,0), MyIterator(&A,A.size()));
1033 }
1034
1035 // ****************************************************************************
1036 // *** BogoSort and more slow sorts
1037
1038 // by myself (Timo Bingmann)
1039
BogoCheckSorted(SortArray & A)1040 bool BogoCheckSorted(SortArray& A)
1041 {
1042 size_t i;
1043 value_type prev = A[0];
1044 A.mark(0);
1045 for (i = 1; i < A.size(); ++i)
1046 {
1047 value_type val = A[i];
1048 if (prev > val) break;
1049 prev = val;
1050 A.mark(i);
1051 }
1052
1053 if (i == A.size()) {
1054 // this is amazing.
1055 return true;
1056 }
1057
1058 // unmark
1059 while (i > 0) A.unmark(i--);
1060 A.unmark(0);
1061
1062 return false;
1063 }
1064
BogoSort(SortArray & A)1065 void BogoSort(SortArray& A)
1066 {
1067 // keep a permutation of [0,size)
1068 std::vector<size_t> perm(A.size());
1069
1070 for (size_t i = 0; i < A.size(); ++i)
1071 perm[i] = i;
1072
1073 while (1)
1074 {
1075 // check if array is sorted
1076 if (BogoCheckSorted(A)) break;
1077
1078 // pick a random permutation of indexes
1079 std::random_shuffle(perm.begin(), perm.end());
1080
1081 // permute array in-place
1082 std::vector<char> pmark(A.size(), 0);
1083
1084 for (size_t i = 0; i < A.size(); ++i)
1085 {
1086 if (pmark[i]) continue;
1087
1088 // walk a cycle
1089 size_t j = i;
1090
1091 //std::cout << "cycle start " << j << " -> " << perm[j] << "\n";
1092
1093 while ( perm[j] != i )
1094 {
1095 ASSERT(!pmark[j]);
1096 A.swap(j, perm[j]);
1097 pmark[j] = 1;
1098
1099 j = perm[j];
1100 //std::cout << "cycle step " << j << " -> " << perm[j] << "\n";
1101 }
1102 //std::cout << "cycle end\n";
1103
1104 ASSERT(!pmark[j]);
1105 pmark[j] = 1;
1106 }
1107
1108 //std::cout << "permute end\n";
1109
1110 for (size_t i = 0; i < A.size(); ++i)
1111 ASSERT(pmark[i]);
1112 }
1113 }
1114
BozoSort(SortArray & A)1115 void BozoSort(SortArray& A)
1116 {
1117 srand(time(NULL));
1118
1119 while (1)
1120 {
1121 // check if array is sorted
1122 if (BogoCheckSorted(A)) break;
1123
1124 // swap two random items
1125 A.swap(rand() % A.size(), rand() % A.size());
1126 }
1127 }
1128
1129 // ****************************************************************************
1130 // *** Bitonic Sort
1131
1132 // from http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/bitonic/oddn.htm
1133
1134 namespace BitonicSortNS {
1135
1136 static const bool ASCENDING = true; // sorting direction
1137
compare(SortArray & A,int i,int j,bool dir)1138 static void compare(SortArray& A, int i, int j, bool dir)
1139 {
1140 if (dir == (A[i] > A[j]))
1141 A.swap(i, j);
1142 }
1143
bitonicMerge(SortArray & A,int lo,int n,bool dir)1144 static void bitonicMerge(SortArray& A, int lo, int n, bool dir)
1145 {
1146 if (n > 1)
1147 {
1148 int m = largestPowerOfTwoLessThan(n);
1149
1150 for (int i = lo; i < lo + n - m; i++)
1151 compare(A, i, i+m, dir);
1152
1153 bitonicMerge(A, lo, m, dir);
1154 bitonicMerge(A, lo + m, n - m, dir);
1155 }
1156 }
1157
bitonicSort(SortArray & A,int lo,int n,bool dir)1158 static void bitonicSort(SortArray& A, int lo, int n, bool dir)
1159 {
1160 if (n > 1)
1161 {
1162 int m = n / 2;
1163 bitonicSort(A, lo, m, !dir);
1164 bitonicSort(A, lo + m, n - m, dir);
1165 bitonicMerge(A, lo, n, dir);
1166 }
1167 }
1168
1169 } // namespace BitonicSortNS
1170
BitonicSort(SortArray & A)1171 void BitonicSort(SortArray& A)
1172 {
1173 BitonicSortNS::bitonicSort(A, 0, A.size(), BitonicSortNS::ASCENDING);
1174 }
1175
1176 // ****************************************************************************
1177 // *** Bitonic Sort as "Parallel" Sorting Network
1178
1179 // from http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/bitonic/oddn.htm
1180
1181 // modified to first record the recursively generated swap sequence, and then
1182 // sort it back into the order a parallel sorting network would perform the
1183 // swaps in
1184
1185 namespace BitonicSortNetworkNS {
1186
1187 struct swappair_type
1188 {
1189 // swapped positions
1190 unsigned int i,j;
1191
1192 // depth of recursions: sort / merge
1193 unsigned int sort_depth, merge_depth;
1194
swappair_typeBitonicSortNetworkNS::swappair_type1195 swappair_type(unsigned int _i, unsigned int _j,
1196 unsigned int _sort_depth, unsigned int _merge_depth)
1197 : i(_i), j(_j),
1198 sort_depth(_sort_depth), merge_depth(_merge_depth)
1199 { }
1200
1201 // order relation for sorting swaps
operator <BitonicSortNetworkNS::swappair_type1202 bool operator < (const swappair_type& b) const
1203 {
1204 if (sort_depth != b.sort_depth)
1205 return sort_depth > b.sort_depth;
1206
1207 if (merge_depth != b.merge_depth)
1208 return merge_depth < b.merge_depth;
1209
1210 return i < b.i;
1211 }
1212 };
1213
1214 typedef std::vector<swappair_type> sequence_type;
1215 std::vector<swappair_type> sequence;
1216
replay(SortArray & A)1217 void replay(SortArray& A)
1218 {
1219 for (sequence_type::const_iterator si = sequence.begin();
1220 si != sequence.end(); ++si)
1221 {
1222 if (A[si->i] > A[si->j])
1223 A.swap(si->i, si->j);
1224 }
1225 }
1226
1227 static const bool ASCENDING = true; // sorting direction
1228
compare(SortArray &,unsigned int i,unsigned int j,bool dir,unsigned int sort_depth,unsigned int merge_depth)1229 static void compare(SortArray& /* A */, unsigned int i, unsigned int j, bool dir,
1230 unsigned int sort_depth, unsigned int merge_depth)
1231 {
1232 // if (dir == (A[i] > A[j])) A.swap(i, j);
1233
1234 if (dir)
1235 sequence.push_back( swappair_type(i,j, sort_depth, merge_depth) );
1236 else
1237 sequence.push_back( swappair_type(j,i, sort_depth, merge_depth) );
1238 }
1239
bitonicMerge(SortArray & A,unsigned int lo,unsigned int n,bool dir,unsigned int sort_depth,unsigned int merge_depth)1240 static void bitonicMerge(SortArray& A, unsigned int lo, unsigned int n, bool dir,
1241 unsigned int sort_depth, unsigned int merge_depth)
1242 {
1243 if (n > 1)
1244 {
1245 unsigned int m = largestPowerOfTwoLessThan(n);
1246
1247 for (unsigned int i = lo; i < lo + n - m; i++)
1248 compare(A, i, i + m, dir, sort_depth, merge_depth);
1249
1250 bitonicMerge(A, lo, m, dir, sort_depth, merge_depth+1);
1251 bitonicMerge(A, lo + m, n - m, dir, sort_depth, merge_depth+1);
1252 }
1253 }
1254
bitonicSort(SortArray & A,unsigned int lo,unsigned int n,bool dir,unsigned int sort_depth)1255 static void bitonicSort(SortArray& A, unsigned int lo, unsigned int n, bool dir,
1256 unsigned int sort_depth)
1257 {
1258 if (n > 1)
1259 {
1260 unsigned int m = n / 2;
1261 bitonicSort(A, lo, m, !dir, sort_depth+1);
1262 bitonicSort(A, lo + m, n - m, dir, sort_depth+1);
1263 bitonicMerge(A, lo, n, dir, sort_depth, 0);
1264 }
1265 }
1266
sort(SortArray & A)1267 void sort(SortArray& A)
1268 {
1269 sequence.clear();
1270 bitonicSort(A, 0, A.size(), BitonicSortNS::ASCENDING, 0);
1271 std::sort(sequence.begin(), sequence.end());
1272 replay(A);
1273 sequence.clear();
1274 }
1275
1276 } // namespace BitonicSortNS
1277
BitonicSortNetwork(SortArray & A)1278 void BitonicSortNetwork(SortArray& A)
1279 {
1280 BitonicSortNetworkNS::sort(A);
1281 }
1282
1283 // ****************************************************************************
1284 // *** Batcher's Odd-Even Merge Sort as "Parallel" Sorting Network
1285
1286 // from http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/networks/oemen.htm
1287
1288 // modified to first record the recursively generated swap sequence, and then
1289 // sort it back into the order a parallel sorting network would perform the
1290 // swaps in
1291
1292 namespace BatcherSortNetworkNS {
1293
1294 struct swappair_type
1295 {
1296 // swapped positions
1297 unsigned int i,j;
1298
1299 // depth of recursions: sort / merge
1300 unsigned int sort_depth, merge_depth;
1301
swappair_typeBatcherSortNetworkNS::swappair_type1302 swappair_type(unsigned int _i, unsigned int _j,
1303 unsigned int _sort_depth, unsigned int _merge_depth)
1304 : i(_i), j(_j),
1305 sort_depth(_sort_depth), merge_depth(_merge_depth)
1306 { }
1307
1308 // order relation for sorting swaps
operator <BatcherSortNetworkNS::swappair_type1309 bool operator < (const swappair_type& b) const
1310 {
1311 if (sort_depth != b.sort_depth)
1312 return sort_depth > b.sort_depth;
1313
1314 if (merge_depth != b.merge_depth)
1315 return merge_depth > b.merge_depth;
1316
1317 return i < b.i;
1318 }
1319 };
1320
1321 typedef std::vector<swappair_type> sequence_type;
1322 std::vector<swappair_type> sequence;
1323
replay(SortArray & A)1324 void replay(SortArray& A)
1325 {
1326 for (sequence_type::const_iterator si = sequence.begin();
1327 si != sequence.end(); ++si)
1328 {
1329 if (A[si->i] > A[si->j])
1330 A.swap(si->i, si->j);
1331 }
1332 }
1333
compare(SortArray & A,unsigned int i,unsigned int j,unsigned int sort_depth,unsigned int merge_depth)1334 static void compare(SortArray& A, unsigned int i, unsigned int j,
1335 unsigned int sort_depth, unsigned int merge_depth)
1336 {
1337 // skip all swaps beyond end of array
1338 ASSERT(i < j);
1339 if (j >= A.size()) return;
1340
1341 sequence.push_back( swappair_type(i,j, sort_depth, merge_depth) );
1342
1343 //if (A[i] > A[j]) A.swap(i, j);
1344 }
1345
1346 // lo is the starting position and n is the length of the piece to be merged, r
1347 // is the distance of the elements to be compared
oddEvenMerge(SortArray & A,unsigned int lo,unsigned int n,unsigned int r,unsigned int sort_depth,unsigned int merge_depth)1348 static void oddEvenMerge(SortArray& A, unsigned int lo, unsigned int n, unsigned int r,
1349 unsigned int sort_depth, unsigned int merge_depth)
1350 {
1351 unsigned int m = r * 2;
1352 if (m < n)
1353 {
1354 // even subsequence
1355 oddEvenMerge(A, lo, n, m, sort_depth, merge_depth+1);
1356 // odd subsequence
1357 oddEvenMerge(A, lo + r, n, m, sort_depth, merge_depth+1);
1358
1359 for (unsigned int i = lo + r; i + r < lo + n; i += m)
1360 compare(A, i, i + r, sort_depth, merge_depth);
1361 }
1362 else {
1363 compare(A, lo, lo + r, sort_depth, merge_depth);
1364 }
1365 }
1366
1367 // sorts a piece of length n of the array starting at position lo
oddEvenMergeSort(SortArray & A,unsigned int lo,unsigned int n,unsigned int sort_depth)1368 static void oddEvenMergeSort(SortArray& A, unsigned int lo, unsigned int n,
1369 unsigned int sort_depth)
1370 {
1371 if (n > 1)
1372 {
1373 unsigned int m = n / 2;
1374 oddEvenMergeSort(A, lo, m, sort_depth+1);
1375 oddEvenMergeSort(A, lo + m, m, sort_depth+1);
1376 oddEvenMerge(A, lo, n, 1, sort_depth, 0);
1377 }
1378 }
1379
sort(SortArray & A)1380 void sort(SortArray& A)
1381 {
1382 sequence.clear();
1383
1384 unsigned int n = largestPowerOfTwoLessThan(A.size());
1385 if (n != A.size()) n *= 2;
1386
1387 oddEvenMergeSort(A, 0, n, 0);
1388 std::sort(sequence.begin(), sequence.end());
1389 replay(A);
1390 sequence.clear();
1391 }
1392
1393 } // namespace BatcherSortNetworkNS
1394
BatcherSortNetwork(SortArray & A)1395 void BatcherSortNetwork(SortArray& A)
1396 {
1397 BatcherSortNetworkNS::sort(A);
1398 }
1399
1400 // ****************************************************************************
1401 // *** Smooth Sort
1402
1403 // from http://en.wikipediA.org/wiki/Smoothsort
1404
1405 namespace SmoothSortNS {
1406
1407 static const int LP[] = {
1408 1, 1, 3, 5, 9, 15, 25, 41, 67, 109,
1409 177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891,
1410 35421, 57313, 92735, 150049, 242785, 392835, 635621, 1028457,
1411 1664079, 2692537, 4356617, 7049155, 11405773, 18454929, 29860703,
1412 48315633, 78176337, 126491971, 204668309, 331160281, 535828591,
1413 866988873 // the next number is > 31 bits.
1414 };
1415
sift(SortArray & A,int pshift,int head)1416 static void sift(SortArray& A, int pshift, int head)
1417 {
1418 // we do not use Floyd's improvements to the heapsort sift, because we
1419 // are not doing what heapsort does - always moving nodes from near
1420 // the bottom of the tree to the root.
1421
1422 value_type val = A[head];
1423
1424 while (pshift > 1)
1425 {
1426 int rt = head - 1;
1427 int lf = head - 1 - LP[pshift - 2];
1428
1429 if (val.cmp(A[lf]) >= 0 && val.cmp(A[rt]) >= 0)
1430 break;
1431
1432 if (A[lf].cmp(A[rt]) >= 0) {
1433 A.set(head, A[lf]);
1434 head = lf;
1435 pshift -= 1;
1436 }
1437 else {
1438 A.set(head, A[rt]);
1439 head = rt;
1440 pshift -= 2;
1441 }
1442 }
1443
1444 A.set(head, val);
1445 }
1446
trinkle(SortArray & A,int p,int pshift,int head,bool isTrusty)1447 static void trinkle(SortArray& A, int p, int pshift, int head, bool isTrusty)
1448 {
1449 value_type val = A[head];
1450
1451 while (p != 1)
1452 {
1453 int stepson = head - LP[pshift];
1454
1455 if (A[stepson].cmp(val) <= 0)
1456 break; // current node is greater than head. sift.
1457
1458 // no need to check this if we know the current node is trusty,
1459 // because we just checked the head (which is val, in the first
1460 // iteration)
1461 if (!isTrusty && pshift > 1) {
1462 int rt = head - 1;
1463 int lf = head - 1 - LP[pshift - 2];
1464 if (A[rt].cmp(A[stepson]) >= 0 ||
1465 A[lf].cmp(A[stepson]) >= 0)
1466 break;
1467 }
1468
1469 A.set(head, A[stepson]);
1470
1471 head = stepson;
1472 //int trail = Integer.numberOfTrailingZeros(p & ~1);
1473 int trail = __builtin_ctz(p & ~1);
1474 p >>= trail;
1475 pshift += trail;
1476 isTrusty = false;
1477 }
1478
1479 if (!isTrusty) {
1480 A.set(head, val);
1481 sift(A, pshift, head);
1482 }
1483 }
1484
sort(SortArray & A,int lo,int hi)1485 void sort(SortArray& A, int lo, int hi)
1486 {
1487 int head = lo; // the offset of the first element of the prefix into m
1488
1489 // These variables need a little explaining. If our string of heaps
1490 // is of length 38, then the heaps will be of size 25+9+3+1, which are
1491 // Leonardo numbers 6, 4, 2, 1.
1492 // Turning this into a binary number, we get b01010110 = 0x56. We represent
1493 // this number as a pair of numbers by right-shifting all the zeros and
1494 // storing the mantissa and exponent as "p" and "pshift".
1495 // This is handy, because the exponent is the index into L[] giving the
1496 // size of the rightmost heap, and because we can instantly find out if
1497 // the rightmost two heaps are consecutive Leonardo numbers by checking
1498 // (p&3)==3
1499
1500 int p = 1; // the bitmap of the current standard concatenation >> pshift
1501 int pshift = 1;
1502
1503 while (head < hi)
1504 {
1505 if ((p & 3) == 3) {
1506 // Add 1 by merging the first two blocks into a larger one.
1507 // The next Leonardo number is one bigger.
1508 sift(A, pshift, head);
1509 p >>= 2;
1510 pshift += 2;
1511 }
1512 else {
1513 // adding a new block of length 1
1514 if (LP[pshift - 1] >= hi - head) {
1515 // this block is its final size.
1516 trinkle(A, p, pshift, head, false);
1517 } else {
1518 // this block will get merged. Just make it trusty.
1519 sift(A, pshift, head);
1520 }
1521
1522 if (pshift == 1) {
1523 // LP[1] is being used, so we add use LP[0]
1524 p <<= 1;
1525 pshift--;
1526 } else {
1527 // shift out to position 1, add LP[1]
1528 p <<= (pshift - 1);
1529 pshift = 1;
1530 }
1531 }
1532 p |= 1;
1533 head++;
1534 }
1535
1536 trinkle(A, p, pshift, head, false);
1537
1538 while (pshift != 1 || p != 1)
1539 {
1540 if (pshift <= 1) {
1541 // block of length 1. No fiddling needed
1542 //int trail = Integer.numberOfTrailingZeros(p & ~1);
1543 int trail = __builtin_ctz(p & ~1);
1544 p >>= trail;
1545 pshift += trail;
1546 }
1547 else {
1548 p <<= 2;
1549 p ^= 7;
1550 pshift -= 2;
1551
1552 // This block gets broken into three bits. The rightmost bit is a
1553 // block of length 1. The left hand part is split into two, a block
1554 // of length LP[pshift+1] and one of LP[pshift]. Both these two
1555 // are appropriately heapified, but the root nodes are not
1556 // necessarily in order. We therefore semitrinkle both of them
1557
1558 trinkle(A, p >> 1, pshift + 1, head - LP[pshift] - 1, true);
1559 trinkle(A, p, pshift, head - 1, true);
1560 }
1561
1562 head--;
1563 }
1564 }
1565
1566 } // namespace SmoothSortNS
1567
SmoothSort(SortArray & A)1568 void SmoothSort(SortArray& A)
1569 {
1570 return SmoothSortNS::sort(A, 0, A.size()-1);
1571 }
1572
1573 // ****************************************************************************
1574 // *** Stooge Sort
1575
StoogeSort(SortArray & A,int i,int j)1576 void StoogeSort(SortArray& A, int i, int j)
1577 {
1578 if (A[i] > A[j])
1579 {
1580 A.swap(i, j);
1581 }
1582
1583 if (j - i + 1 >= 3)
1584 {
1585 int t = (j - i + 1) / 3;
1586
1587 A.mark(i, 3);
1588 A.mark(j, 3);
1589
1590 StoogeSort(A, i, j-t);
1591 StoogeSort(A, i+t, j);
1592 StoogeSort(A, i, j-t);
1593
1594 A.unmark(i);
1595 A.unmark(j);
1596 }
1597 }
1598
StoogeSort(SortArray & A)1599 void StoogeSort(SortArray& A)
1600 {
1601 StoogeSort(A, 0, A.size()-1);
1602 }
1603
1604 // ****************************************************************************
1605 // *** Slow Sort
1606
SlowSort(SortArray & A,int i,int j)1607 void SlowSort(SortArray& A, int i, int j)
1608 {
1609 if (i >= j) return;
1610
1611 int m = (i + j) / 2;
1612
1613 SlowSort(A, i, m);
1614 SlowSort(A, m+1, j);
1615
1616 if (A[m] > A[j])
1617 A.swap(m, j);
1618
1619 A.mark(j, 2);
1620
1621 SlowSort(A, i, j-1);
1622
1623 A.unmark(j);
1624 }
1625
SlowSort(SortArray & A)1626 void SlowSort(SortArray& A)
1627 {
1628 SlowSort(A, 0, A.size()-1);
1629 }
1630
1631 // ****************************************************************************
1632 // *** Cycle Sort
1633
1634 // Adapted from http://en.wikipedia.org/wiki/Cycle_sort
1635
CycleSort(SortArray & array,ssize_t n)1636 void CycleSort(SortArray& array, ssize_t n)
1637 {
1638 volatile ssize_t cycleStart = 0;
1639 array.watch(&cycleStart, 16);
1640
1641 volatile ssize_t rank = 0;
1642 array.watch(&rank, 3);
1643
1644 // Loop through the array to find cycles to rotate.
1645 for (cycleStart = 0; cycleStart < n - 1; ++cycleStart)
1646 {
1647 value_type& item = array.get_mutable(cycleStart);
1648
1649 do {
1650 // Find where to put the item.
1651 rank = cycleStart;
1652 for (ssize_t i = cycleStart + 1; i < n; ++i)
1653 {
1654 if (array[i] < item)
1655 rank++;
1656 }
1657
1658 // If the item is already there, this is a 1-cycle.
1659 if (rank == cycleStart) {
1660 array.mark(rank, 2);
1661 break;
1662 }
1663
1664 // Otherwise, put the item after any duplicates.
1665 while (item == array[rank])
1666 rank++;
1667
1668 // Put item into right place and colorize
1669 std::swap(array.get_mutable(rank), item);
1670 array.mark(rank, 2);
1671
1672 // Continue for rest of the cycle.
1673 }
1674 while (rank != cycleStart);
1675 }
1676
1677 array.unwatch_all();
1678 }
1679
CycleSort(SortArray & A)1680 void CycleSort(SortArray& A)
1681 {
1682 CycleSort(A, A.size());
1683 }
1684
1685 // ****************************************************************************
1686