並べ替えの順列を見つける
std::vector<T>
と の比較が与えられたT
場合、この比較を使用してベクトルをソートする場合に使用する順列を見つけられるようにしたいと考えています。
template <typename T, typename Compare>
std::vector<std::size_t> sort_permutation(
const std::vector<T>& vec,
Compare& compare)
{
std::vector<std::size_t> p(vec.size());
std::iota(p.begin(), p.end(), 0);
std::sort(p.begin(), p.end(),
[&](std::size_t i, std::size_t j){ return compare(vec[i], vec[j]); });
return p;
}
並べ替え順列の適用
a と a の順列が与えられた場合、順列に従って並べ替えられstd::vector<T>
た new を構築できるようにしたいと考えています。std::vector<T>
template <typename T>
std::vector<T> apply_permutation(
const std::vector<T>& vec,
const std::vector<std::size_t>& p)
{
std::vector<T> sorted_vec(vec.size());
std::transform(p.begin(), p.end(), sorted_vec.begin(),
[&](std::size_t i){ return vec[i]; });
return sorted_vec;
}
apply_permutation
もちろん、新しい並べ替えられたコピーを返すのではなく、指定したベクトルを変更するように変更することもできます。このアプローチは依然として線形時間の複雑さであり、ベクトル内の項目ごとに 1 ビットを使用します。理論的には、依然として線形空間の複雑さです。しかし、実際には、sizeof(T)
が大きい場合、メモリ使用量が大幅に削減される可能性があります。(詳細を見る)
template <typename T>
void apply_permutation_in_place(
std::vector<T>& vec,
const std::vector<std::size_t>& p)
{
std::vector<bool> done(vec.size());
for (std::size_t i = 0; i < vec.size(); ++i)
{
if (done[i])
{
continue;
}
done[i] = true;
std::size_t prev_j = i;
std::size_t j = p[i];
while (i != j)
{
std::swap(vec[prev_j], vec[j]);
done[j] = true;
prev_j = j;
j = p[j];
}
}
}
例
vector<MyObject> vectorA;
vector<int> vectorB;
auto p = sort_permutation(vectorA,
[](T const& a, T const& b){ /*some comparison*/ });
vectorA = apply_permutation(vectorA, p);
vectorB = apply_permutation(vectorB, p);
資力