Sort.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //
  2. // Copyright (c) 2008-2017 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #pragma once
  23. #include "../Container/Swap.h"
  24. #include "../Container/VectorBase.h"
  25. namespace Atomic
  26. {
  27. static const int QUICKSORT_THRESHOLD = 16;
  28. // Based on Comparison of several sorting algorithms by Juha Nieminen
  29. // http://warp.povusers.org/SortComparison/
  30. /// Perform insertion sort on an array.
  31. template <class T> void InsertionSort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end)
  32. {
  33. for (RandomAccessIterator<T> i = begin + 1; i < end; ++i)
  34. {
  35. T temp = *i;
  36. RandomAccessIterator<T> j = i;
  37. while (j > begin && temp < *(j - 1))
  38. {
  39. *j = *(j - 1);
  40. --j;
  41. }
  42. *j = temp;
  43. }
  44. }
  45. /// Perform insertion sort on an array using a compare function.
  46. template <class T, class U> void InsertionSort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end, U compare)
  47. {
  48. for (RandomAccessIterator<T> i = begin + 1; i < end; ++i)
  49. {
  50. T temp = *i;
  51. RandomAccessIterator<T> j = i;
  52. while (j > begin && compare(temp, *(j - 1)))
  53. {
  54. *j = *(j - 1);
  55. --j;
  56. }
  57. *j = temp;
  58. }
  59. }
  60. /// Perform quick sort initial pass on an array. Does not sort fully.
  61. template <class T> void InitialQuickSort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end)
  62. {
  63. while (end - begin > QUICKSORT_THRESHOLD)
  64. {
  65. // Choose the pivot by median
  66. RandomAccessIterator<T> pivot = begin + ((end - begin) / 2);
  67. if (*begin < *pivot && *(end - 1) < *begin)
  68. pivot = begin;
  69. else if (*(end - 1) < *pivot && *begin < *(end - 1))
  70. pivot = end - 1;
  71. // Partition and sort recursively
  72. RandomAccessIterator<T> i = begin - 1;
  73. RandomAccessIterator<T> j = end;
  74. T pivotValue = *pivot;
  75. for (;;)
  76. {
  77. while (pivotValue < *(--j));
  78. while (*(++i) < pivotValue);
  79. if (i < j)
  80. Swap(*i, *j);
  81. else
  82. break;
  83. }
  84. InitialQuickSort(begin, j + 1);
  85. begin = j + 1;
  86. }
  87. }
  88. /// Perform quick sort initial pass on an array using a compare function. Does not sort fully.
  89. template <class T, class U> void InitialQuickSort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end, U compare)
  90. {
  91. while (end - begin > QUICKSORT_THRESHOLD)
  92. {
  93. // Choose the pivot by median
  94. RandomAccessIterator<T> pivot = begin + ((end - begin) / 2);
  95. if (compare(*begin, *pivot) && compare(*(end - 1), *begin))
  96. pivot = begin;
  97. else if (compare(*(end - 1), *pivot) && compare(*begin, *(end - 1)))
  98. pivot = end - 1;
  99. // Partition and sort recursively
  100. RandomAccessIterator<T> i = begin - 1;
  101. RandomAccessIterator<T> j = end;
  102. T pivotValue = *pivot;
  103. for (;;)
  104. {
  105. while (compare(pivotValue, *(--j)));
  106. while (compare(*(++i), pivotValue));
  107. if (i < j)
  108. Swap(*i, *j);
  109. else
  110. break;
  111. }
  112. InitialQuickSort(begin, j + 1, compare);
  113. begin = j + 1;
  114. }
  115. }
  116. /// Sort in ascending order using quicksort for initial passes, then an insertion sort to finalize.
  117. template <class T> void Sort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end)
  118. {
  119. InitialQuickSort(begin, end);
  120. InsertionSort(begin, end);
  121. }
  122. /// Sort in ascending order using quicksort for initial passes, then an insertion sort to finalize, using a compare function.
  123. template <class T, class U> void Sort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end, U compare)
  124. {
  125. InitialQuickSort(begin, end, compare);
  126. InsertionSort(begin, end, compare);
  127. }
  128. }