Sort.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /* Copyright The kNet Project.
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License. */
  11. #pragma once
  12. /** @file Sort.h
  13. @brief A range of comparison sort algorithms. */
  14. #include "Clock.h"
  15. //#include "LCG.h"
  16. #include "SortCmp.h"
  17. namespace kNet
  18. {
  19. /** @brief A range of comparison sort algorithms.
  20. When to use one of these sorts and when to use the std sorts?
  21. (std::sort, std::stable_sort, std::list::sort etc.)
  22. 1) Always consider using the standard versions first. For example, the visual c++
  23. std::sort is on average faster than the introsort described here. Additionally,
  24. your code has the advantage of being more portable.
  25. 2) The sorting algorithms described here operate only on contiguous data. This means
  26. that they can only be used to sort vectors and arrays. If you have a linked
  27. list, you can only use list::sort. Additionally, the data type T must be assignable.
  28. 3) If the std:: sorting performance is not acceptable, figure out the "profile"
  29. of your sortable data. Is it in random or mostly sorted order? Is it sorted
  30. once, occasionally or on a per-frame basis? Are all items unique or are there several
  31. that are equivalent? Is stable sort-property required? Then look at the actual
  32. implementations of these algorithms and decide what fits the data profile the best.
  33. And of course, always measure the actual performance.
  34. Note that a few of these algorithms have only been implemented as a curiosity.
  35. Selection sort for example just plain sucks.
  36. The client-implemented comparison function must be of this form:
  37. template<typename T>
  38. int CmpFunc(const T &a, const T &b);
  39. @param a The first comparison operand.
  40. @param b The second comparison operand.
  41. @return a negative value if a < b, 0 if a == b and a positive value when b < a. */
  42. namespace sort
  43. {
  44. /** Selection sort is a stable sort that has FIXED running time of ~n^2/2. It can
  45. contend only against Bubble sort, which in general performs far better.
  46. The only advantage of this against other sorts is that CmpFunc can be a partial ordering instead
  47. of a total ordering (For other sort functions, cmp must be a total order). */
  48. template<typename T, typename CmpFunc>
  49. void SelectionSort(T *list, int numItems, CmpFunc &cmp);
  50. /** The same as above, but only partially sorts the list so that the numItemsToSort first items in the
  51. list are in order, the rest are unordered. Gives a slight performance boost when only a part of the list
  52. needs to get ordered. Doesn't affect the asymptotics though, which is O(k*n), where k=numItemsToSort. */
  53. template<typename T, typename CmpFunc>
  54. void PartialSelectionSort(T *list, int numItems, int numItemsToSort, CmpFunc &cmp);
  55. /** Insertion sort is efficent on data that is almost sorted. Worst case O(n^2), avg.
  56. n^2/4, Best case O(n). This sort is stable. */
  57. template<typename T, typename CmpFunc>
  58. void InsertionSort(T *list, int numItems, CmpFunc &cmp);
  59. /** Shell sort is an optimization of insertion sort, performs in O(n^1.25) on average.
  60. Worst case O(n^2). This sort is not stable. */
  61. template<typename T, typename CmpFunc>
  62. void ShellSort(T *list, int numItems, CmpFunc &cmp);
  63. /** Bubble sort sorts in worst case O(n^2) time, best case O(n) if the list is already almost sorted.
  64. This sort is stable. */
  65. template<typename T, typename CmpFunc>
  66. void BubbleSort(T *list, int numItems, CmpFunc &cmp);
  67. /** Cocktail sort == Bidirectional Bubble sort == Shaker sort == Ripple sort == Shuttle sort:
  68. Stable optimization of Bubble sort, worst case O(n^2). If the list is mostly ordered,
  69. then the running time is near O(n). */
  70. template<typename T, typename CmpFunc>
  71. void CocktailSort(T *list, int numItems, CmpFunc &cmp);
  72. /** Comb sort is a "diminishing" Bubble sort, an unstable optimization of Bubble sort.
  73. Generally performs far better than Bubble/Cocktail sorts. */
  74. template<typename T, typename CmpFunc>
  75. void CombSort(T *list, int numItems, CmpFunc &cmp);
  76. /** Merge sort has constant running time O(n*logn). Requires O(n) of additional space and
  77. has a recursive call overhead of 2n-1. This sort is stable. Note that this sort dynamically
  78. allocates memory with a call to new[]. */
  79. template<typename T, typename CmpFunc>
  80. void MergeSort(T *list, int numItems, CmpFunc &cmp);
  81. /** Quicksort sorts in avg. O(n*logn) time, with a O(logn) recursive call overhead. In worst case
  82. (array is sorted in descending order) degenerates into a selection sort with O(n^2)
  83. complexity. The middle element of the sublist is chosen as pivot. This sort is not
  84. stable, and it has a potential security vulnerability due to recursive calls. */
  85. template<typename T, typename CmpFunc>
  86. void QuickSort(T *list, int numItems, CmpFunc &cmp);
  87. /** Heapsort is an in-place working algorithm that runs in O(n*logn) time. Generally
  88. slower than Quicksort, but is better in worst case scenario when the list is almost sorted.
  89. This sort is not stable. */
  90. template<typename T, typename CmpFunc>
  91. void HeapSort(T *list, int numItems, CmpFunc &cmp);
  92. /** Introspective sort starts as Quicksort, but switches to Heapsort when the maximum
  93. number of recursion levels has been exceeded. This shields the implementation against
  94. stack overflow. If it's known that Introsorting a particular list will cause it to switch
  95. to Heapsort, it is faster to directly call Heapsort instead. Introsort is not stable. */
  96. template<typename T, typename CmpFunc>
  97. void IntroSort(T *list, int numItems, int nMaxRecursionLevels, CmpFunc &cmp);
  98. /// This can be used for debugging.
  99. template<typename T, typename CmpFunc>
  100. bool IsSorted(T *list, int numItems, CmpFunc &cmp);
  101. // The following lines define shortcuts for easier using when the standard < and == comparison operators are involved:
  102. template<typename T> void SelectionSort(T *list, int numItems) { SelectionSort<T>(list, numItems, TriCmp<T>); }
  103. template<typename T> void InsertionSort(T *list, int numItems) { InsertionSort<T>(list, numItems, TriCmp<T>); }
  104. template<typename T> void ShellSort(T *list, int numItems) { ShellSort<T>(list, numItems, TriCmp<T>); }
  105. template<typename T> void BubbleSort(T *list, int numItems) { BubbleSort<T>(list, numItems, TriCmp<T>); }
  106. template<typename T> void CocktailSort(T *list, int numItems) { CocktailSort<T>(list, numItems, TriCmp<T>); }
  107. template<typename T> void CombSort(T *list, int numItems) { CombSort<T>(list, numItems, TriCmp<T>); }
  108. template<typename T> void MergeSort(T *list, int numItems) { MergeSort<T>(list, numItems, TriCmp<T>); }
  109. template<typename T> void QuickSort(T *list, int numItems) { QuickSort<T>(list, numItems, TriCmp<T>); }
  110. template<typename T> void HeapSort(T *list, int numItems) { HeapSort<T>(list, numItems, TriCmp<T>); }
  111. template<typename T> void IntroSort(T *list, int numItems, int nMaxRecursionLevels = 1000) { IntroSort<T>(list, numItems, nMaxRecursionLevels, TriCmp<T>); }
  112. } // ~sort
  113. } // ~kNet
  114. #include "Sort.inl"