13 template<
class random_it_t>
22 template<
class random_it_t,
class compare_t>
28 for (random_it_t i = begin + 1; i != end; ++i)
29 for (random_it_t j = i; j != begin && compare(*j, *(j - 1)); --j)
30 std::iter_swap(j - 1, j);
33 template<
class container_t,
class compare_t>
39 template<
class random_it_t,
class compare_t>
45 for (random_it_t it = begin; it != end; ++it)
47 random_it_t itMin = it;
48 for (random_it_t j = it + 1; j != end; ++j)
49 if (compare(*j, *itMin))
52 std::iter_swap(it, itMin);
56 template<
class container_t,
class compare_t>
62 template<
class random_it_t,
class compare_t>
63 void sort_bubble(random_it_t begin, random_it_t end, compare_t compare)
72 for (random_it_t it = begin, itEnd = end - 1; it != itEnd; ++it)
74 if (compare(*(it + 1), *it))
76 std::iter_swap(it, it + 1);
83 template<
class container_t,
class compare_t>
89 template<
class random_it_t,
class compare_t>
90 void adjust_heap(random_it_t begin,
size_t nHeapSize,
size_t nPosition, compare_t compare)
92 using iter_diff = decltype(random_it_t() - random_it_t());
94 while (nPosition < nHeapSize)
96 size_t nChildPos = nPosition * 2 + 1;
97 if (nChildPos < nHeapSize)
99 if ((nChildPos + 1 < nHeapSize)
101 *(begin +
static_cast<iter_diff
>(nChildPos)),
102 *(begin +
static_cast<iter_diff
>(nChildPos) + 1)))
107 if (compare(*(begin +
static_cast<iter_diff
>(nChildPos)), *(begin +
static_cast<iter_diff
>(nPosition))))
113 std::iter_swap(begin +
static_cast<iter_diff
>(nPosition), begin +
static_cast<iter_diff
>(nChildPos));
116 nPosition = nChildPos;
120 template<
class random_it_t,
class compare_t>
121 void make_heap(random_it_t begin, random_it_t end, compare_t compare)
123 auto max = end - begin;
124 for (
int i =
static_cast<int>(max) / 2; i >= 0; --i)
128 static_cast<size_t>(max),
129 static_cast<size_t>(i),
134 template<
class random_it_t,
class compare_t>
135 void sort_heap(random_it_t begin, random_it_t end, compare_t compare)
142 auto nLastPosition = end - begin - 1;
143 while (nLastPosition > 0)
145 std::iter_swap(begin, begin + nLastPosition);
146 adjust_heap(begin,
static_cast<size_t>(nLastPosition), 0u, compare);
151 template<
class container_t,
class compare_t>
157 template<
class random_it_t,
class compare_t>
163 i64 nRight = (end - begin) - 1;
168 auto nPivot = *(begin + nLeft + (nRight - nLeft) / 2);
170 while (nLeft <= nRight)
172 while (compare(*(begin + nLeft), nPivot))
175 while (compare(nPivot, *(begin + nRight)))
179 std::iter_swap(begin + nLeft++, begin + nRight--);
187 template<
class container_t,
class compare_t>
193 template<
class random_it_t,
class compare_t>
199 const i64 nRight = (end - begin) - 1;
204 auto pivot = *(begin + nLeft + (nRight - nLeft) / 2);
209 i64 nIndex1 = nLeft - 1;
210 i64 nIndex2 = nRight + 1;
214 while (compare(*(begin + i), pivot))
217 while (compare(pivot, *(begin + j)))
222 if (compare(pivot, *(begin + i)))
224 if (compare(*(begin + j), pivot))
227 std::swap(*(begin + i), *(begin + j));
232 std::swap(*(begin + i), *(begin + j));
233 std::swap(*(begin + ++nIndex1), *(begin + i));
236 else if (compare(*(begin + j), pivot))
239 std::iter_swap(begin + i, begin + j);
240 std::iter_swap(begin + j, begin + --nIndex2);
245 std::iter_swap(begin + ++nIndex1, begin + i);
246 std::iter_swap(begin + j, begin + --nIndex2);
260 for (i64 k = nLeft; k <= nIndex1; ++k)
261 std::iter_swap(begin + k, begin + j--);
263 for (i64 k = nRight; k >= nIndex2; --k)
264 std::iter_swap(begin + i++, begin + k);
271 template<
class container_t,
class compare_t>
277 template<
class random_it_t,
class compare_t>
283 i64 nRight = (end - begin) - 1;
288 std::iter_swap(begin + nLeft + (nRight - nLeft) / 3, begin + nLeft);
289 std::iter_swap(begin + nRight - (nRight - nLeft) / 3, begin + nRight);
291 if (compare(*(begin + nRight), *(begin + nLeft)))
292 std::iter_swap(begin + nLeft, begin + nRight);
294 if (nRight - nLeft == 1)
297 auto pivot1 = *(begin + nLeft);
298 auto pivot2 = *(begin + nRight);
300 if (compare(pivot1, pivot2))
302 i64 nLess = nLeft + 1;
303 i64 nGreater = nRight - 1;
305 while (!compare(*(begin + nGreater), pivot2))
308 while (!compare(pivot1, *(begin + nLess)))
312 while (k <= nGreater)
314 if (!compare(pivot1, *(begin + k)))
316 std::iter_swap(begin + k, begin + nLess++);
318 else if (!compare(*(begin + k), pivot2))
320 std::iter_swap(begin + k, begin + nGreater--);
321 while (!compare(*(begin + nGreater), pivot2))
324 if (!compare(pivot1, *(begin + k)))
325 std::iter_swap(begin + k, begin + nLess++);
331 std::iter_swap(begin + nLess - 1, begin + nLeft);
332 std::iter_swap(begin + nGreater + 1, begin + nRight);
341 i64 nLess = nLeft + 1;
342 i64 nGreater = nRight - 1;
344 while (compare(pivot1, *(begin + nGreater)))
347 while (compare(*(begin + nLess), pivot1))
351 while (k <= nGreater)
353 if (compare(*(begin + k), pivot1))
355 std::iter_swap(begin + k, begin + nLess++);
357 else if (compare(pivot1, *(begin + k)))
359 std::iter_swap(begin + k, begin + nGreater--);
360 while (compare(pivot1, *(begin + nGreater)))
363 if (compare(*(begin + k), pivot1))
364 std::iter_swap(begin + k, begin + nLess++);
370 std::iter_swap(begin + nLess - 1, begin + nLeft);
371 std::iter_swap(begin + nGreater + 1, begin + nRight);
379 template<
class container_t,
class compare_t>
385 template<
class random_it_t,
class compare_t>
386 void merge(random_it_t begin, random_it_t end, compare_t compare, vector_of_values<random_it_t>* pPreallocatedBuffer)
388 using iter_diff = decltype(random_it_t() - random_it_t());
392 random_it_t mid = begin + (end - begin) / 2;
394 const bool bCreateBuffer = !pPreallocatedBuffer;
396 pPreallocatedBuffer =
new vector_of_values<random_it_t>;
398 pPreallocatedBuffer->resize(
static_cast<size_t>(end - begin));
401 while ((begin +
static_cast<iter_diff
>(nInd1) < mid) && (mid +
static_cast<iter_diff
>(nInd2) < end))
403 if (compare(*(begin +
static_cast<iter_diff
>(nInd1)), *(mid +
static_cast<iter_diff
>(nInd2))))
405 (*pPreallocatedBuffer)[nInd1 + nInd2] = *(begin +
static_cast<iter_diff
>(nInd1));
411 (*pPreallocatedBuffer)[nInd1 + nInd2] = *(mid +
static_cast<iter_diff
>(nInd2));
418 while (begin +
static_cast<iter_diff
>(nInd1) < mid)
420 (*pPreallocatedBuffer)[nInd1 + nInd2] = *(begin +
static_cast<iter_diff
>(nInd1));
425 while (mid +
static_cast<iter_diff
>(nInd2) < end)
427 (*pPreallocatedBuffer)[nInd1 + nInd2] = *(mid +
static_cast<iter_diff
>(nInd2));
433 for (
auto it = begin; it < end; ++it)
434 *it = (*pPreallocatedBuffer)[
static_cast<size_t>(it - begin)];
437 delete pPreallocatedBuffer;
440 template<
class random_it_t,
class compare_t>
445 vector_of_values<random_it_t>* pPreallocatedBuffer)
450 const bool bCreateBuffer = !pPreallocatedBuffer;
452 pPreallocatedBuffer =
new vector_of_values<random_it_t>;
456 auto nLen = end - begin;
457 pPreallocatedBuffer->reserve(
static_cast<size_t>(nLen));
459 sort_merge(begin, begin + nLen / 2, compare, pPreallocatedBuffer);
460 sort_merge(begin + nLen / 2, end, compare, pPreallocatedBuffer);
461 merge(begin, end, compare, pPreallocatedBuffer);
464 delete pPreallocatedBuffer;
467 template<
class container_t,
class compare_t>
471 vector_of_values<typename container_t::iterator>* pPreallocatedBuffer)
473 sort_merge(cont.begin(), cont.end(), compare, pPreallocatedBuffer);
476 template<
class random_it_t,
class compare_t>
477 bool sort_counting(random_it_t begin, random_it_t end, compare_t compare,
size_t nMaxBufferSize)
479 static_assert(std::is_integral_v<iterator_value_t<random_it_t>>,
"Integral type required for counting sort");
484 auto minMax = std::minmax_element(begin, end);
485 auto min = *minMax.first;
486 auto max = *minMax.second;
488 const size_t nSizeRequired =
static_cast<size_t>(max) - min + 1;
489 if (nSizeRequired <= nMaxBufferSize)
491 std::vector<size_t> counts(nSizeRequired, 0);
493 for (random_it_t it = begin; it < end; ++it)
494 ++counts[
static_cast<size_t>(*it) - min];
496 if constexpr (compare(0, 1))
499 for (
size_t i = 0; i < nSizeRequired; ++i)
500 begin = std::fill_n(begin, counts[i], min++);
505 for (
size_t i = 0; i < nSizeRequired; ++i)
506 begin = std::fill_n(begin, counts[nSizeRequired - i - 1], max--);
515 template<
class container_t,
class compare_t>
516 bool sort_counting(container_t& cont, compare_t compare,
size_t nMaxBufferSize)
518 return sort_counting(cont.begin(), cont.end(), compare, nMaxBufferSize);
521 template<
class random_it_t,
class compare_t>
522 void sort(random_it_t begin, random_it_t end, compare_t compare)
524 bool bSorted =
false;
527 if constexpr (std::is_integral_v<iterator_value_t<random_it_t>>)
530 if (end - begin > 1000)
540 template<
class container_t,
class compare_t>
541 void sort(container_t& cont, compare_t compare)
543 qx::sort(cont.begin(), cont.end(), compare);
void sort_selection(random_it_t begin, random_it_t end, compare_t compare=compare_t())
Selection sort.
void sort_quick_three_way(random_it_t begin, random_it_t end, compare_t compare=compare_t())
Quick sort based on three-way partitioning.
void sort_insertion(random_it_t begin, random_it_t end, compare_t compare=compare_t())
Insertion sort.
void sort_heap(random_it_t begin, random_it_t end, compare_t compare=compare_t())
Heap sort.
void sort_bubble(random_it_t begin, random_it_t end, compare_t compare=compare_t())
Bubble sort.
void sort(random_it_t begin, random_it_t end, compare_t compare=compare_t())
Sort by the most suitable algorithm.
bool sort_counting(random_it_t begin, random_it_t end, compare_t compare=compare_t(), size_t nMaxBufferSize=SORT_COUNTING_MAX_BUFFER_SIZE)
Counting sort for integral values.
void adjust_heap(random_it_t begin, size_t nHeapSize, size_t nPosition, compare_t compare=compare_t())
Adjust heap.
bool sort_required(random_it_t begin, random_it_t end)
Check if sort really needed.
void sort_quick_hoare(random_it_t begin, random_it_t end, compare_t compare=compare_t())
Quick sort based on Hoare partitioning.
void make_heap(random_it_t begin, random_it_t end, compare_t compare=compare_t())
Make heap at range.
void merge(random_it_t begin, random_it_t end, compare_t compare=compare_t(), vector_of_values< random_it_t > *pPreallocatedBuffer=nullptr)
Merge with temp vector.
void sort_quick_dual_pivot(random_it_t begin, random_it_t end, compare_t compare=compare_t())
Quick sort based on dual-pivot partitioning.
void sort_merge(random_it_t begin, random_it_t end, compare_t compare=compare_t(), vector_of_values< random_it_t > *pPreallocatedBuffer=nullptr)
Merge sort based on merge with temp vector.