/mergesort.hpp

https://bitbucket.org/mild1/sorting · C++ Header · 170 lines · 156 code · 14 blank · 0 comment · 47 complexity · 382d3625152af3d22ecf0a035dffbd1f MD5 · raw file

  1. #define USE_PREFIX//prefix increment faster than postfix even for size_t
  2. template <typename T> inline void smerge(const T* src, T* dst, size_t middle, size_t right)
  3. {
  4. size_t i = 0;
  5. size_t j = middle;
  6. size_t k = 0;
  7. #ifdef USE_PREFIX
  8. while(i < middle && j < right)
  9. {
  10. if(src[i] < src[j])
  11. {
  12. dst[k] = src[i];
  13. ++i;
  14. }
  15. else
  16. {
  17. dst[k] = src[j];
  18. ++j;
  19. }
  20. ++k;
  21. }
  22. #else
  23. while(i < middle && j < right)
  24. {
  25. if(src[i] < src[j])
  26. dst[k++] = src[i++];
  27. else
  28. dst[k++] = src[j++];
  29. }
  30. #endif
  31. if(i < middle)
  32. memcpy(dst + k, src + i, sizeof(T)*(middle - i));
  33. else if(j < right)
  34. memcpy(dst + k, src + j, sizeof(T)*(right - j));
  35. }
  36. template <typename Iter, typename DestinationIter> inline void merge(Iter& first, const Iter& end, DestinationIter& dst, size_t width)
  37. {
  38. size_t actualSize = end - first;
  39. if(actualSize < width)
  40. {
  41. for(;first != end; ++first, ++dst)
  42. *dst = *first;
  43. return;
  44. }
  45. Iter first2(first + width);
  46. const Iter end1(first2);
  47. const Iter end2(first2 + tMin(width, actualSize - width));
  48. while(first != end1 || first2 != end2)
  49. {
  50. if(first2 == end2)
  51. {
  52. *dst = *first;
  53. ++first;
  54. }
  55. else if(first == end1)
  56. {
  57. *dst = *first2;
  58. ++first2;
  59. }
  60. else if(*first2 < *first)
  61. {
  62. *dst = *first2;
  63. ++first2;
  64. }
  65. else
  66. {
  67. *dst = *first;
  68. ++first;
  69. }
  70. ++dst;
  71. }
  72. first = first2;
  73. }
  74. template <typename Vec> void mergesort_vector_memcpy(Vec& a)
  75. {
  76. typedef typename Vec::value_type T;
  77. const size_t size = a.size();
  78. if(size < 2)
  79. return;
  80. const size_t PresortSize = 2;
  81. T* src = &a[0];
  82. for (size_t i = 0; i < size - 1; i += 2)
  83. {
  84. size_t next = i + 1;
  85. if(src[next] < src[i])
  86. mswap(src[next], src[i]);
  87. }
  88. Vec buf(size);
  89. T* dst = &buf[0];
  90. for(size_t width = PresortSize; width < size; width <<= 1)
  91. {
  92. size_t doubleWidth = width << 1;
  93. for(size_t i = 0; i < size; i += doubleWidth)
  94. smerge(src + i, dst + i, tMin(width, size - i), tMin(doubleWidth, size - i));
  95. std::swap(src, dst);
  96. }
  97. if(dst == &a[0])
  98. memcpy(&a[0], &buf[0], size*sizeof(T));
  99. }
  100. template <typename Iter> void mergesort(const Iter& begin, const Iter& end)
  101. {
  102. const size_t size = end - begin;
  103. if(size < 2)
  104. return;
  105. typedef typename std::iterator_traits<Iter>::value_type T;
  106. const size_t PresortSize = 2;
  107. Iter last = end - 1;
  108. for (Iter i = begin; i < last; i += 2)
  109. {
  110. Iter next = i + 1;
  111. if(*next < *i)
  112. mswap(*next, *i);
  113. }
  114. std::vector<T> buf(size);
  115. T* b2 = &buf[0];
  116. T* e2 = b2 + buf.size();
  117. size_t iterationsCounter = 0;
  118. for(size_t width = PresortSize; width < size; width <<= 1, ++iterationsCounter)
  119. {
  120. if(iterationsCounter%2)
  121. {
  122. Iter dst(begin);
  123. T* first = b2;
  124. while (first != e2)
  125. merge<T*, Iter>(first, e2, dst, width);
  126. }
  127. else
  128. {
  129. Iter first(begin);
  130. T* dst = b2;
  131. while (first != end)
  132. merge<Iter, T*>(first, end, dst, width);
  133. }
  134. }
  135. if(iterationsCounter%2)
  136. {
  137. typename std::vector<T>::iterator j = buf.begin();
  138. for(Iter i = begin; i != end; ++i, ++j)
  139. *i = *j;
  140. }
  141. }
  142. template <typename Container> void mergesort_through_vec(Container& l)
  143. {
  144. size_t size = l.size();
  145. if(size < 2)
  146. return;
  147. typedef typename Container::value_type T;
  148. std::vector<T> buf(size);
  149. size_t i = 0;
  150. for(typename Container::const_iterator it = l.begin(), e = l.end(); it != e; ++it, ++i)
  151. buf[i] = *it;
  152. mergesort(&buf[0], &buf[0] + size);
  153. i = 0;
  154. for(typename Container::iterator it = l.begin(), e = l.end(); it != e; ++it, ++i)
  155. *it = buf[i];
  156. }