找到循环并排列每个循环的提示对我很有用。总结我的方法,我在构造函数中找到所有循环的开始索引。
然后,在
apply()
,我通过反复使用
std::swap
.
struct Permutation {
private:
/// The single vector which stores both the permutation
/// AND the indices of the cycles starts.
std::vector<size_t> perm;
/// The size of the permutation / index of first cycle index.
size_t permSize;
public:
Permutation(std::vector<size_t> table)
: perm{std::move(table)}, permSize{perm.size()} {
findCycles();
}
template <typename T>
void apply(T data[]) const {
for (size_t cycle = permSize; cycle < perm.size(); ++cycle) {
const size_t start = perm[cycle];
for (size_t prev = start, next = perm[prev];
next != start;
prev = next, next = perm[next]) {
std::swap(data[prev], data[next]);
}
}
}
size_t size() const {
return permSize;
}
private:
void findCycles();
}
findCycles()
也很容易实现,但需要临时分配位向量。
void Permutation::findCycles() {
std::vector<bool> visited(size());
for (size_t i = 0; i < size(); ++i) {
if (visited[i]) {
continue;
}
for (size_t j = i; not visited[j]; ) {
visited[j] = true;
j = perm[j];
}
perm.push_back(i);
}
}