heap_sort.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. //----------------------------------------------------------------------------
  2. /// @file heap_sort.hpp
  3. /// @brief Insertion Sort algorithm
  4. ///
  5. /// @author Copyright (c) 2016 Francisco Jose Tapia (fjtapia@gmail.com )\n
  6. /// Distributed under the Boost Software License, Version 1.0.\n
  7. /// ( See accompanying file LICENSE_1_0.txt or copy at
  8. /// http://www.boost.org/LICENSE_1_0.txt )
  9. /// @version 0.1
  10. ///
  11. /// @remarks
  12. //-----------------------------------------------------------------------------
  13. #ifndef __BOOST_SORT_INTROSORT_DETAIL_HEAP_SORT_HPP
  14. #define __BOOST_SORT_INTROSORT_DETAIL_HEAP_SORT_HPP
  15. #include <cassert>
  16. #include <cstdint>
  17. #include <iterator>
  18. #include <stdexcept>
  19. #include <utility> // for std::swap
  20. #include <boost/sort/common/util/traits.hpp>
  21. namespace boost
  22. {
  23. namespace sort
  24. {
  25. namespace heap_detail
  26. {
  27. namespace bscu = boost::sort::common::util;
  28. //
  29. //---------------------------------------------------------------------------
  30. // struct : heap_sort
  31. /// @brief : Heap sort algorithm
  32. /// @remarks This algorithm is O(NLogN)
  33. //---------------------------------------------------------------------------
  34. template < class Iter_t, class Compare >
  35. struct heap_sort
  36. {
  37. typedef bscu::value_iter<Iter_t> value_t;
  38. //
  39. //------------------------------------------------------------------------
  40. // function : sort3
  41. /// @brief Sort and signal the changes of three values
  42. /// @param val_0 : first value to compare
  43. /// @param val_1 : second value to compare
  44. /// @param val_2 : third value to compare
  45. /// @param [out] bool_0 : if true indicates val_0 had been changed
  46. /// @param [out] bool_1 : if true indicates val_1 had been changed
  47. /// @param [out] bool_2 : if true indicates val_2 had been changed
  48. /// @return if true , some value had changed
  49. /// @remarks
  50. //------------------------------------------------------------------------
  51. bool sort3 (value_t &val_0, value_t &val_1, value_t &val_2, bool &bool_0,
  52. bool &bool_1, bool &bool_2)
  53. {
  54. bool_0 = bool_1 = bool_2 = false;
  55. int value = 0;
  56. if (val_0 < val_1) value += 4;
  57. if (val_1 < val_2) value += 2;
  58. if (val_0 < val_2) value += 1;
  59. switch (value)
  60. {
  61. case 0: break;
  62. case 2:
  63. std::swap (val_1, val_2);
  64. bool_1 = bool_2 = true;
  65. break;
  66. case 3:
  67. if (not(val_0 > val_1)) {
  68. std::swap (val_0, val_2);
  69. bool_0 = bool_2 = true;
  70. }
  71. else
  72. {
  73. auto aux = std::move (val_2);
  74. val_2 = std::move (val_1);
  75. val_1 = std::move (val_0);
  76. val_0 = std::move (aux);
  77. bool_0 = bool_1 = bool_2 = true;
  78. };
  79. break;
  80. case 4:
  81. std::swap (val_0, val_1);
  82. bool_0 = bool_1 = true;
  83. break;
  84. case 5:
  85. if (val_1 > val_2) {
  86. auto aux = std::move (val_0);
  87. val_0 = std::move (val_1);
  88. val_1 = std::move (val_2);
  89. val_2 = std::move (aux);
  90. bool_0 = bool_1 = bool_2 = true;
  91. }
  92. else
  93. {
  94. std::swap (val_0, val_2);
  95. bool_0 = bool_2 = true;
  96. };
  97. break;
  98. case 7:
  99. std::swap (val_0, val_2);
  100. bool_0 = bool_2 = true;
  101. break;
  102. default: abort ( );
  103. };
  104. return (bool_0 or bool_1 or bool_2);
  105. };
  106. //
  107. //-----------------------------------------------------------------------
  108. // function : make_heap
  109. /// @brief Make the heap for to extract the sorted elements
  110. /// @param first : iterator to the first element of the range
  111. /// @param nelem : number of lements of the range
  112. /// @param comp : object for to compare two elements
  113. /// @remarks This algorithm is O(NLogN)
  114. //------------------------------------------------------------------------
  115. void make_heap (Iter_t first, size_t nelem, Compare comp)
  116. {
  117. size_t pos_father, pos_son;
  118. Iter_t iter_father = first, iter_son = first;
  119. bool sw = false;
  120. for (size_t i = 1; i < nelem; ++i)
  121. {
  122. pos_father = i;
  123. iter_father = first + i;
  124. sw = false;
  125. do
  126. {
  127. iter_son = iter_father;
  128. pos_son = pos_father;
  129. pos_father = (pos_son - 1) >> 1;
  130. iter_father = first + pos_father;
  131. if ((sw = comp (*iter_father, *iter_son)))
  132. std::swap (*iter_father, *iter_son);
  133. } while (sw and pos_father != 0);
  134. };
  135. };
  136. //
  137. //------------------------------------------------------------------------
  138. // function : heap_sort
  139. /// @brief : Heap sort algorithm
  140. /// @param first: iterator to the first element of the range
  141. /// @param last : iterator to the next element of the last in the range
  142. /// @param comp : object for to do the comparison between the elements
  143. /// @remarks This algorithm is O(NLogN)
  144. //------------------------------------------------------------------------
  145. heap_sort (Iter_t first, Iter_t last, Compare comp)
  146. {
  147. assert ((last - first) >= 0);
  148. size_t nelem = last - first;
  149. if (nelem < 2) return;
  150. //--------------------------------------------------------------------
  151. // Creating the initial heap
  152. //--------------------------------------------------------------------
  153. make_heap (first, nelem, comp);
  154. //--------------------------------------------------------------------
  155. // Sort the heap
  156. //--------------------------------------------------------------------
  157. size_t pos_father, pos_son;
  158. Iter_t iter_father = first, iter_son = first;
  159. bool sw = false;
  160. for (size_t i = 1; i < nelem; ++i)
  161. {
  162. std::swap (*first, *(first + (nelem - i)));
  163. pos_father = 0;
  164. pos_son = 1;
  165. iter_father = first;
  166. sw = true;
  167. while (sw and pos_son < (nelem - i))
  168. {
  169. // if the father have two sons must select the bigger
  170. iter_son = first + pos_son;
  171. if ((pos_son + 1) < (nelem - i) and
  172. comp (*iter_son, *(iter_son + 1)))
  173. {
  174. ++pos_son;
  175. ++iter_son;
  176. };
  177. if ((sw = comp (*iter_father, *iter_son)))
  178. std::swap (*iter_father, *iter_son);
  179. pos_father = pos_son;
  180. iter_father = iter_son;
  181. pos_son = (pos_father << 1) + 1;
  182. };
  183. };
  184. };
  185. }; // End class heap_sort
  186. }; // end namespace heap_sort
  187. namespace bscu = boost::sort::common::util;
  188. template < class Iter_t, typename Compare = bscu::compare_iter < Iter_t > >
  189. void heap_sort (Iter_t first, Iter_t last, Compare comp = Compare())
  190. {
  191. heap_detail::heap_sort<Iter_t, Compare> ( first, last, comp);
  192. }
  193. //
  194. //****************************************************************************
  195. }; // End namespace sort
  196. }; // End namespace boost
  197. //****************************************************************************
  198. //
  199. #endif