How can I apply a permutation in-place? My permutations are effectively size_t[]
where perm[i]
represents the target index for an input index i
.
I know how to apply a permutation if I have an input and output array:
struct Permutation {
std::vector<size_t> perm;
template <typename T>
void apply(const T in[], T out[]) const
{
for (size_t i = 0; i < size(); ++i) {
out[i] = std::move(in[perm[i]]);
}
}
}
However, I would like to do this with only one array, similar to how std::sort
works, so just using std::swap
. My idea so far is:
struct Permutation {
std::vector<size_t> perm;
template <typename T>
void apply(T data[]) const
{
for (size_t i = 0; i < size(); ++i) {
std::swap(data[i], data[perm[i]]);
}
}
}
But this wouldn't work. For example:
Permutation perm = {2, 1, 0};
char data[] {'a', 'b', 'c'};
perm.apply(data);
// because I swap indices 0 and 2 twice, I end up with the input array
data == {'a', 'b', 'c'};
So how do I correctly permute an array in-place? It is okay if additional memory is allocated, as long as this happens in a pre-computation step when the Permutation
is constructed. I want the in-place permutation to happen fast and from the looks of it, demanding that no additional memory is allocated at all will lead to some severe performance sacrifices.
I am specifically referencing Algorithm to apply permutation in constant memory space, where all of the provided answers either cheat by using negative-integer space to avoid an allocation or enter "nasty" nested loops which blow up the time complexity to O(n²).
Edits
Please pay attention before suggesting std::next_permutation
. I am not trying to generate all possible permutations, which I could do with std::next_permutation
. I am instead trying to apply a single particular permutation to an array.