112 lines
2.3 KiB
C++
112 lines
2.3 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 T>
|
|
struct Pair {
|
|
T first;
|
|
T second;
|
|
};
|
|
|
|
template <typename T>
|
|
struct PairComp {
|
|
bool operator()(const Pair<T> &x, const Pair<T> &y) const
|
|
{
|
|
return x.second < y.second;
|
|
}
|
|
};
|
|
|
|
template <typename Container>
|
|
Container fordJohnsonSort(const Container &input)
|
|
{
|
|
typedef typename Container::value_type T;
|
|
Container result;
|
|
|
|
if (input.size() <= 1)
|
|
return input;
|
|
|
|
std::vector<Pair<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);
|
|
Pair<T> p;
|
|
p.first = a;
|
|
p.second = b;
|
|
pairs.push_back(p);
|
|
}
|
|
|
|
std::sort(pairs.begin(), pairs.end(), PairComp<T>());
|
|
|
|
for (size_t k = 0; k < pairs.size(); ++k)
|
|
result.push_back(pairs[k].second);
|
|
|
|
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 = std::lower_bound(
|
|
result.begin(), result.end(), 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 = std::lower_bound(
|
|
result.begin(), result.end(), pairs[j].first);
|
|
result.insert(pos, pairs[j].first);
|
|
}
|
|
}
|
|
|
|
if (i < input.size())
|
|
{
|
|
T leftover = input[i];
|
|
typename Container::iterator pos = std::lower_bound(result.begin(), result.end(), leftover);
|
|
result.insert(pos, leftover);
|
|
}
|
|
|
|
return result;
|
|
}
|