#pragma once
|
|
#include <gp/algorithms/move.hpp>
|
|
#include <gp/algorithms/partition.hpp>
|
|
|
|
namespace gp {
|
|
|
|
namespace __details {
|
|
template<typename it_t, typename pred>
|
|
void selection_sort(it_t first, it_t last, pred predicate = pred{}) {
|
|
|
|
while(first != last) {
|
|
it_t traveler = first;
|
|
it_t it = first;
|
|
it++;
|
|
for(;it!=last;it++) {
|
|
if(predicate(*it, *traveler)) traveler = it;
|
|
}
|
|
gp::swap(*first, *traveler);
|
|
first++;
|
|
}
|
|
}
|
|
|
|
template<typename it_t, typename pred>
|
|
bool sort2(auto it0, auto it1, pred predicate = pred{}){
|
|
if(it0 != it1 && predicate(*it1, *it0)) {
|
|
gp::swap(*it0, *it1);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
/*
|
|
template<typename it_t, typename pred>
|
|
void quick_sort(it_t first, it_t last, pred predicate = pred{}) {
|
|
using __details::sort2;
|
|
if(last - first <= 2) {
|
|
auto nit = first + (size_t)(last == first + 1);
|
|
__details::sort2<it_t>(first, nit, predicate);
|
|
return;
|
|
}
|
|
auto pivot_v = *(first + (last - first)/2);
|
|
auto pivot = gp::partition(first, last, [&](auto& a) -> bool{
|
|
return predicate(a, pivot_v);
|
|
});
|
|
gp::__details::quick_sort(first, pivot, predicate);
|
|
gp::__details::quick_sort(pivot, last, predicate);
|
|
}
|
|
*/
|
|
template<typename it_t, typename pred>
|
|
void bubble_sort(it_t first, it_t last, pred predicate = pred{}) {
|
|
if(last - first <= 2) {
|
|
auto nit = first + (size_t)(last == first + 1);
|
|
__details::sort2<it_t>(first, nit, predicate);
|
|
return;
|
|
}
|
|
size_t swaps;
|
|
do {
|
|
swaps = 0;
|
|
auto it = first;
|
|
auto nit = it + 1;
|
|
for(;;) {
|
|
swaps += __details::sort2<it_t>(it, nit, predicate);
|
|
++it; ++nit;
|
|
if(nit == last) break;
|
|
}
|
|
} while(swaps);
|
|
}
|
|
}
|
|
|
|
|
|
template<typename it_t, typename pred>
|
|
void sort(it_t first, it_t last, pred predicate = pred{}) {
|
|
return gp::__details::selection_sort(first, last, predicate);
|
|
}
|
|
}
|