Eine Sortierpermutation finden
Mit einem std::vector<T>und einem Vergleich für T's möchten wir in der Lage sein, die Permutation zu finden, die Sie verwenden würden, wenn Sie den Vektor mithilfe dieses Vergleichs sortieren würden.
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;
}
Anwenden einer Sortierpermutation
Bei einer std::vector<T>und einer Permutation möchten wir in der Lage sein, eine neue zu erstellen std::vector<T>, die entsprechend der Permutation neu angeordnet wird.
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;
}
Sie können natürlich ändern apply_permutation den Vektor , den Sie ihm geben, anstatt eine neue sortierte Kopie zurückzugeben. Dieser Ansatz ist immer noch linear zeitlich komplex und verwendet ein Bit pro Element in Ihrem Vektor. Theoretisch ist es immer noch lineare Raumkomplexität; In der Praxis kann sizeof(T)die Reduzierung der Speichernutzung jedoch dramatisch sein , wenn sie groß ist. ( Siehe Details )
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];
}
}
}
Beispiel
vector<MyObject> vectorA;
vector<int> vectorB;
auto p = sort_permutation(vectorA,
[](T const& a, T const& b){ });
vectorA = apply_permutation(vectorA, p);
vectorB = apply_permutation(vectorB, p);
Ressourcen