Trouver une permutation de tri
Étant donné un std::vector<T>
et une comparaison pour T
nous voulons être en mesure de trouver la permutation que vous utiliseriez si vous deviez trier le vecteur en utilisant cette comparaison.
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;
}
Application d'une permutation de tri
Étant donné un std::vector<T>
et une permutation, nous voulons être capable de construire une nouvelle std::vector<T>
qui est réordonné selon la permutation.
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;
}
Vous pouvez bien sûr modifier apply_permutation
pour muter le vecteur que vous lui donnez plutôt que de retourner une nouvelle copie triée. Cette approche est toujours d'une complexité temporelle linéaire et utilise un bit par élément dans votre vecteur. Théoriquement, la complexité spatiale est toujours linéaire, mais en pratique, quand sizeof(T)
est importante, la réduction de l'utilisation de la mémoire peut être spectaculaire. ( Voir les détails )
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];
}
}
}
Ejemplo
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);
Ressources