I am trying to sort vectors based on a reference vector. First I am getting the indexes for the reference vector and then using that I am doing inplace sorting for the rest of the vectors.
#include <vector>
#include <cassert>
#include <iostream>
#include <algorithm>
using iter = std::vector<int>::iterator;
using order_type = std::vector<std::pair<size_t, iter>>;
void create_permutation(order_type &order)
{
struct ordering {
bool operator ()(std::pair<size_t, iter> const& a, std::pair<size_t, iter> const& b) {
return *(a.second) < *(b.second);
}
};
std::sort(order.begin(), order.end(), ordering());
}
void reorder(std::vector<int> &vect, order_type index)
{
for (int i=0; i< vect.size(); i++)
{
while (index[i].first != i)
{
int old_target_idx = index[index[i].first].first;
int old_target_v = vect[index[i].first];
vect[index[i].first] = vect[i];
index[index[i].first].first = index[i].first;
index[i].first = old_target_idx;
vect[i] = old_target_v;
}
}
}
template<typename... argtype>
void sort_from_ref(argtype... args);
template<typename T, typename A, typename... argtype>
void sort_from_ref(order_type order, std::vector<T,A> &vect, argtype &&...args)
{
reorder(vect, order);
sort_from_ref(order, std::forward<argtype>(args)...);
}
template<>
void sort_from_ref(order_type order, std::vector<int> &vect) {
reorder(vect, order);
}
int main()
{
size_t n = 0;
std::vector<int> vect_1{ 1, 0, 2, 3 };
std::vector<int> vect_2{ 100, 200, 300, 400 };
std::vector<int> vect_3{ 100, 200, 300, 400 };
std::vector<int> vect_4{ 400, 200, 3000, 4000 };
std::vector<int> vect_5{ 500, 200, 360, 400 };
order_type order(vect_1.size());
for (iter it = vect_1.begin(); it != vect_1.end(); ++it) {
order[n] = std::make_pair(n, it);
n++;
}
create_permutation(order);
sort_from_ref(order, vect_2, vect_3, vect_4, vect_5);
{
std::vector<int> test{200, 100, 300, 400};
assert(vect_2 == test);
}
{
std::vector<int> test{200, 100, 300, 400};
assert(vect_3 == test);
}
{
std::vector<int> test{200, 400, 3000, 4000};
assert(vect_4 == test);
}
{
std::vector<int> test{200, 500, 360, 400};
assert(vect_5 == test);
}
return 0;
}