-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmulti_apply_permutation.cpp
61 lines (50 loc) · 1.53 KB
/
multi_apply_permutation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// multi_apply_permutation.cpp
//
// A sample program (not overly generic) for applying
// a permutation to multiple random access ranges (e.g.,
// vectors).
//
// The implementation is an in-place Fich-Munro-Poblete
// cycle leader algorithm that runs in \Theta(n) time,
// which is obviously optimal up to constant factors.
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
namespace detail
{
template <typename T, typename... Ts>
std::size_t size_helper(const T& first, const Ts&...)
{
return first.size();
}
}
template <typename... Ts>
void multi_apply_permutation(std::vector<std::size_t>& perm, Ts&... ranges)
{
const std::size_t size = detail::size_helper(ranges...);
for (std::size_t i = 0; i < size; ++i)
{
std::size_t current = i;
auto permIt = perm.begin();
while (i != permIt[current])
{
const std::size_t next = permIt[current];
((void)std::swap(ranges[current], ranges[next]), ...);
permIt[current] = current;
current = next;
}
permIt[current] = current;
}
}
int main()
{
std::vector<int> a{ 1,2,3,4,5,6 };
std::vector<int> b{ 1,2,3,4,5,6 };
std::vector<int> c{ 6,5,4,3,2,1 };
std::vector<std::size_t> perm{ 5,4,3,2,1,0 };
multi_apply_permutation(perm, a, b, c);
for (auto e : a) std::cout << e << " "; std::cout << "\n";
for (auto e : b) std::cout << e << " "; std::cout << "\n";
for (auto e : c) std::cout << e << " "; std::cout << "\n";
}