93 lines
2.1 KiB
C++
93 lines
2.1 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);
|
|
|
|
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;
|
|
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;
|
|
}
|