aca-tasks/task1/mergesort.h

71 lines
2.2 KiB
C++

#pragma once
#include <vector>
#include <algorithm>
namespace algo {
template<typename Iterator, typename Comparator>
void merge(Iterator start, Iterator middle, Iterator end, Comparator cmp, Iterator output_start) {
Iterator start_m = start;
Iterator start2 = middle + 1;
//merge from input until one half completes
while (start <= middle && start2 <= end) {
if (cmp(*start, *start2)) {
*output_start = *start;
start++;
} else {
*output_start = *start2;
start2++;
}
output_start++;
}
//try to finish first half
while (start <= middle) {
*output_start = *start;
start++;
output_start++;
}
while (start2 <= end) {
*output_start = *start2;
start2++;
output_start++;
}
const auto nit = std::distance(start_m, end);
for (auto i = 0; i <= nit; i++, start_m++, output_start++) {
*start_m = *output_start;
}
}
template<typename Container, typename Iterator, typename Comparator>
void mergesort_splitup(Container &output_vec, Iterator start, Iterator end, Comparator cmp, Iterator output_start) {
Iterator middle = start;
Iterator output_started_from = output_start;
//move middle iterator litterally to the middle
std::advance(middle, std::distance(start, end) / 2);
//sort the first half within an recursion
mergesort_splitup(output_vec, start, middle, cmp, output_start);
//move output iterator
std::advance(output_start, std::distance(start, middle + 1));
//sort the second half within a recursion
mergesort_splitup(output_vec, middle + 1, end, cmp, output_start);
//merge everything together starting from the complete beginning
merge(start, middle, end, cmp, output_started_from);
}
template<typename Iterator, typename Comparator>
void mergesort(Iterator start, Iterator end, Comparator cmp) {
using valtype = typename std::iterator_traits<Iterator>::value_type;
std::vector<valtype> output_vec(std::distance(start, end));
}
}