对于您对代理排序(对索引列表进行排序)感兴趣的情况,您可能希望实现一种更灵活的算法,允许您处理不支持随机访问的容器(例如std::list)。例如:
#include <algorithm>
#include <iostream>
#include <list>
#include <numeric>
#include <vector>
template <typename Container>
auto sorted_indices(const Container& c) {
std::vector<typename Container::size_type> indices(c.size());
std::iota(indices.begin(), indices.end(), 0);
std::sort(indices.begin(), indices.end(), [&c](auto lhs, auto rhs) {
return (*(std::next(c.begin(), lhs)) < *(std::next(c.begin(), rhs)));
});
return indices;
}
template <typename Container, typename Indices>
auto display_sorted(const Container& c, const Indices& indices) {
std::cout << "sorted: ";
for (auto&& index : indices) {
std::cout << *(std::next(c.begin(), index)) << " ";
}
std::cout << std::endl;
}
template <typename Container>
auto display_sorted(const Container& c) {
return display_sorted(c, sorted_indices(c));
}
template <typename Container>
auto display(const Container& c) {
std::cout << "as provided: ";
for (auto&& ci : c) std::cout << ci << " ";
std::cout << std::endl;
}
int main() {
// random access
const std::vector<int> a{9, 5, 2, 3, 1, 6, 4};
display(a);
display_sorted(a);
display(a);
std::cout << "---\n";
// no random access
const std::list<int> b{9, 5, 2, 3, 1, 6, 4};
display(b);
display_sorted(b);
display(b);
}
示例运行:
$ clang++ example.cpp -std=c++17 -Wall -Wextra
$ ./a.out
as provided: 9 5 2 3 1 6 4
sorted: 1 2 3 4 5 6 9
as provided: 9 5 2 3 1 6 4
---
as provided: 9 5 2 3 1 6 4
sorted: 1 2 3 4 5 6 9
as provided: 9 5 2 3 1 6 4
如您所料,依赖代理排序可能会对性能产生重要影响。例如:每次要按顺序遍历时,都可能会发生缓存未命中。另外,对于随机访问,遍历会和底层容器一样复杂:std::vector的情况下std::next(v.begin(), n)是O(1),但std::list的情况下std::next(l.begin(), n)是O(n) .