#pragma once #include #include #include #include #include #include #include #include #include #include std::vector generateJacobsthal(size_t n); template 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 Container fordJohnsonSort(const Container &input) { typedef typename Container::value_type T; Container result; if (input.size() <= 1) return input; std::vector > 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 order = generateJacobsthal(pairs.size()); std::vector 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; }