Files
cpp09/ex02/PmergeMe.hpp

113 lines
2.5 KiB
C++

#pragma once
#include <stdexcept>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <climits>
#include <cstdlib>
#include <vector>
#include <ctime>
#include <deque>
std::vector<size_t> generateJacobsthal(size_t n)
{
std::vector<size_t> seq;
if (n == 0)
return seq;
seq.push_back(0);
if (n == 1)
return seq;
seq.push_back(1);
size_t j0 = 0, j1 = 1;
while (true)
{
size_t jn = j1 + 2 * j0;
if (jn >= n)
break;
seq.push_back(jn);
j0 = j1;
j1 = jn;
}
return seq;
}
template <typename Container, typename T>
typename Container::iterator binaryInsertPosition(Container &c, const T &value)
{
typename Container::iterator first = c.begin();
typename Container::iterator last = c.end();
while (first < last)
{
typename Container::iterator mid = first + (last - first) / 2; //tzvetan told me a better way iirc but i don't remember D:
if (*mid < value)
first = mid + 1;
else
last = mid;
}
return first;
}
template <typename Container>
Container fordJohnsonSort(const Container &input)
{
typedef typename Container::value_type T;
Container result;
if (input.size() <= 1)
return input;
std::vector<std::pair<T, T> > pairs;
size_t i = 0;
for (; i + 1 < input.size(); i += 2)
{
T a = input[i];
T b = input[i+1];
if (a > b)
std::swap(a, b);
pairs.push_back(std::make_pair(a, b));
}
Container larger;
for (size_t j = 0; j < pairs.size(); ++j)
larger.push_back(pairs[j].second);
larger = fordJohnsonSort(larger);
result = larger;
std::vector<size_t> order = generateJacobsthal(pairs.size());
std::vector<bool> inserted(pairs.size(), false);
for (size_t idx = 0; idx < order.size(); ++idx)
{
size_t j = order[idx];
if (j < pairs.size() && !inserted[j])
{
typename Container::iterator pos = binaryInsertPosition(result, pairs[j].first);
result.insert(pos, pairs[j].first);
inserted[j] = true;
}
}
for (size_t j = 0; j < pairs.size(); ++j)
{
if (!inserted[j])
{
typename Container::iterator pos = binaryInsertPosition(result, pairs[j].first);
result.insert(pos, pairs[j].first);
}
}
if (i < input.size())
{
T leftover = input[i];
typename Container::iterator pos = binaryInsertPosition(result, leftover);
result.insert(pos, leftover);
}
return result;
}