Sort.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Container/Swap.h"
  5. #include "../Container/VectorBase.h"
  6. namespace Urho3D
  7. {
  8. static const int QUICKSORT_THRESHOLD = 16;
  9. // Based on Comparison of several sorting algorithms by Juha Nieminen
  10. // http://warp.povusers.org/SortComparison/
  11. /// Perform insertion sort on an array.
  12. template <class T> void InsertionSort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end)
  13. {
  14. for (RandomAccessIterator<T> i = begin + 1; i < end; ++i)
  15. {
  16. T temp = *i;
  17. RandomAccessIterator<T> j = i;
  18. while (j > begin && temp < *(j - 1))
  19. {
  20. *j = *(j - 1);
  21. --j;
  22. }
  23. *j = temp;
  24. }
  25. }
  26. /// Perform insertion sort on an array using a compare function.
  27. template <class T, class U> void InsertionSort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end, U compare)
  28. {
  29. for (RandomAccessIterator<T> i = begin + 1; i < end; ++i)
  30. {
  31. T temp = *i;
  32. RandomAccessIterator<T> j = i;
  33. while (j > begin && compare(temp, *(j - 1)))
  34. {
  35. *j = *(j - 1);
  36. --j;
  37. }
  38. *j = temp;
  39. }
  40. }
  41. /// Perform quick sort initial pass on an array. Does not sort fully.
  42. template <class T> void InitialQuickSort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end)
  43. {
  44. while (end - begin > QUICKSORT_THRESHOLD)
  45. {
  46. // Choose the pivot by median
  47. RandomAccessIterator<T> pivot = begin + ((end - begin) / 2);
  48. if (*begin < *pivot && *(end - 1) < *begin)
  49. pivot = begin;
  50. else if (*(end - 1) < *pivot && *begin < *(end - 1))
  51. pivot = end - 1;
  52. // Partition and sort recursively
  53. RandomAccessIterator<T> i = begin - 1;
  54. RandomAccessIterator<T> j = end;
  55. T pivotValue = *pivot;
  56. for (;;)
  57. {
  58. while (pivotValue < *(--j));
  59. while (*(++i) < pivotValue);
  60. if (i < j)
  61. Swap(*i, *j);
  62. else
  63. break;
  64. }
  65. InitialQuickSort(begin, j + 1);
  66. begin = j + 1;
  67. }
  68. }
  69. /// Perform quick sort initial pass on an array using a compare function. Does not sort fully.
  70. template <class T, class U> void InitialQuickSort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end, U compare)
  71. {
  72. while (end - begin > QUICKSORT_THRESHOLD)
  73. {
  74. // Choose the pivot by median
  75. RandomAccessIterator<T> pivot = begin + ((end - begin) / 2);
  76. if (compare(*begin, *pivot) && compare(*(end - 1), *begin))
  77. pivot = begin;
  78. else if (compare(*(end - 1), *pivot) && compare(*begin, *(end - 1)))
  79. pivot = end - 1;
  80. // Partition and sort recursively
  81. RandomAccessIterator<T> i = begin - 1;
  82. RandomAccessIterator<T> j = end;
  83. T pivotValue = *pivot;
  84. for (;;)
  85. {
  86. while (compare(pivotValue, *(--j)));
  87. while (compare(*(++i), pivotValue));
  88. if (i < j)
  89. Swap(*i, *j);
  90. else
  91. break;
  92. }
  93. InitialQuickSort(begin, j + 1, compare);
  94. begin = j + 1;
  95. }
  96. }
  97. /// Sort in ascending order using quicksort for initial passes, then an insertion sort to finalize.
  98. template <class T> void Sort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end)
  99. {
  100. InitialQuickSort(begin, end);
  101. InsertionSort(begin, end);
  102. }
  103. /// Sort in ascending order using quicksort for initial passes, then an insertion sort to finalize, using a compare function.
  104. template <class T, class U> void Sort(RandomAccessIterator<T> begin, RandomAccessIterator<T> end, U compare)
  105. {
  106. InitialQuickSort(begin, end, compare);
  107. InsertionSort(begin, end, compare);
  108. }
  109. }