如何实现按分数降序、科目字典序排序的成绩报表?
嘿,我来帮你搞定这个成绩排序的问题!先说说你之前踩的坑,再给你几个靠谱的实现方案~
先分析你之前的问题
继承
std::map的思路不合理
std::map压根不是设计来让你继承的——它没有虚析构函数,用基类指针操作派生类对象时会触发未定义行为。而且map的排序逻辑是由模板参数里的比较器决定的,重写insert方法完全是找错了方向。std::set的代码错误
你原代码里有个明显的笔误:lmark写成了lmarks,这会直接导致编译失败。另外用std::function作为set的比较器类型虽然可行,但会引入不必要的开销,而且你没把定义好的compare传给set的构造函数,这也是运行出错的原因之一。
方案一:用std::vector + std::sort(最推荐!简单灵活)
这个方法最直观,先把所有成绩存入vector,再用自定义规则排序,完美匹配你的需求,代码也清爽:
#include <vector> #include <algorithm> #include <string> #include <iostream> // 定义成绩的存储类型 using ScorePair = std::pair<std::string, long>; int main() { std::vector<ScorePair> scores = { {"Math", 90}, {"English", 85}, {"Physics", 90}, {"Chemistry", 88} }; // 自定义排序规则:先按分数降序,同分按科目字典序升序 std::sort(scores.begin(), scores.end(), [](const ScorePair& a, const ScorePair& b) { if (a.second != b.second) { return a.second > b.second; // 分数高的排前面 } return a.first < b.first; // 同分则科目字典序小的排前面 }); // 输出测试 for (const auto& pair : scores) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; }
这个方案的优势:逻辑清晰,不需要关联容器的复杂规则,遍历、修改都很方便,性能也不错。
方案二:修正后的std::set实现
如果你一定要用关联容器自动维护排序,那得把比较器的问题搞定,同时确保满足STL要求的严格弱序:
#include <set> #include <string> #include <iostream> using ScorePair = std::pair<std::string, long>; int main() { // 自定义比较器,严格遵循排序规则 auto compare = [](const ScorePair& a, const ScorePair& b) { if (a.second != b.second) { return a.second > b.second; // 分数降序 } return a.first < b.first; // 同分科目升序 }; // 用decltype推导比较器类型,避免std::function的额外开销 std::set<ScorePair, decltype(compare)> marks(compare); // 插入成绩 marks.insert({"Math", 90}); marks.insert({"English", 85}); marks.insert({"Physics", 90}); marks.insert({"Chemistry", 88}); // 输出结果 for (const auto& pair : marks) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; }
这里的关键:
- 用
decltype(compare)指定set的比较器类型,比std::function更高效 - 比较器严格满足严格弱序(不会同时返回
compare(a,b)和compare(b,a)为true) - 修正了原代码中的变量名笔误
为什么不推荐用自定义比较器的std::map?
虽然可以通过把「分数+科目」作为key,配合自定义比较器实现排序,但这样的写法很别扭——map的value会变成无用的占位符,而且插入、遍历的逻辑远不如vector直观,完全没必要舍近求远。
内容的提问来源于stack exchange,提问作者user13120769
相关产品推荐
相关产品推荐

