Tìm một hoán vị sắp xếp
Đưa ra một std::vector<T>
và một so sánh cho T
's, chúng tôi muốn có thể tìm thấy hoán vị mà bạn sẽ sử dụng nếu bạn sắp xếp vectơ bằng cách sử dụng so sánh này.
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;
}
Áp dụng một hoán vị sắp xếp
Cho trước một std::vector<T>
hoán vị và một hoán vị, chúng ta muốn có thể xây dựng một std::vector<T>
hoán vị mới được sắp xếp lại theo hoán vị.
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;
}
Tất nhiên, bạn có thể sửa đổi apply_permutation
để thay đổi vectơ mà bạn cung cấp cho nó thay vì trả lại một bản sao được sắp xếp mới. Cách tiếp cận này vẫn là độ phức tạp thời gian tuyến tính và sử dụng một bit cho mỗi mục trong vectơ của bạn. Về mặt lý thuyết, nó vẫn là độ phức tạp không gian tuyến tính; nhưng, trong thực tế, khi sizeof(T)
lớn, việc giảm sử dụng bộ nhớ có thể rất đáng kể. ( Xem chi tiết )
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];
}
}
}
Thí dụ
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);
Tài nguyên