如何使用C++14 STL算法根据权重向量对自定义类向量排序
解决方案
要实现按权重同步排序std::vector<A>和对应权重向量,不能直接单独对std::vector<A>调用std::sort,否则会破坏两个向量的元素对应关系。以下是两种符合C++14规范、基于STL算法的实现方案:
方案1:索引排序法(推荐,性能最优)
该方案通过排序间接索引的方式避免修改原向量的顺序,不需要额外拷贝自定义类实例,适合A类内存占用大、拷贝成本高的场景。
#include <vector> #include <algorithm> #include <numeric> #include <cassert> // 自定义类A的示例定义,可替换为实际实现 class A { // 类成员、方法定义 }; int main() { std::vector<A> a; std::vector<float> weights; // 此处省略a和weights的初始化逻辑 assert(a.size() == weights.size()); // 前置校验长度一致 // 1. 构造初始索引向量 std::vector<size_t> indices(a.size()); std::iota(indices.begin(), indices.end(), 0); // 2. 按权重升序排序索引,lambda直接捕获weights向量即可 std::sort(indices.begin(), indices.end(), [&weights](size_t i, size_t j) { return weights[i] < weights[j]; }); // 3. 根据排序后的索引重排原向量 std::vector<A> sorted_a; std::vector<float> sorted_weights; sorted_a.reserve(a.size()); sorted_weights.reserve(weights.size()); for (size_t idx : indices) { sorted_a.push_back(std::move(a[idx])); sorted_weights.push_back(weights[idx]); } // 替换原向量 a = std::move(sorted_a); weights = std::move(sorted_weights); return 0; }
方案2:配对打包排序法(写法简洁)
该方案将元素和对应权重打包为pair后直接排序,代码逻辑直观不易出错,适合A类移动成本低的场景。
#include <vector> #include <algorithm> #include <utility> #include <cassert> class A { // 类成员、方法定义 }; int main() { std::vector<A> a; std::vector<float> weights; // 此处省略a和weights的初始化逻辑 assert(a.size() == weights.size()); // 1. 打包权重和自定义类实例 std::vector<std::pair<float, A>> sorted_pairs; sorted_pairs.reserve(a.size()); for (size_t i = 0; i < a.size(); ++i) { sorted_pairs.emplace_back(weights[i], std::move(a[i])); } // 2. 直接排序pair向量,默认按first元素(权重)升序排列 std::sort(sorted_pairs.begin(), sorted_pairs.end()); // 3. 拆分回两个独立向量 a.clear(); weights.clear(); a.reserve(sorted_pairs.size()); weights.reserve(sorted_pairs.size()); for (auto& item : sorted_pairs) { weights.push_back(item.first); a.push_back(std::move(item.second)); } return 0; }
注意事项
- 两种方案均使用移动语义减少自定义类的拷贝开销,若A类未实现移动构造,会自动降级为拷贝操作
- 若排序后不需要保留权重向量,可以省略对weights的重排步骤
- C++14支持在lambda参数中使用
auto简化写法,例如索引排序的比较逻辑可改写为[&weights](auto i, auto j) { return weights[i] < weights[j]; }
内容的提问来源于stack exchange,提问作者Nicola Mori
相关产品推荐
相关产品推荐

