Sort.h 4.4 KB

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