You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现按分数降序、科目字典序排序的成绩报表?

嘿,我来帮你搞定这个成绩排序的问题!先说说你之前踩的坑,再给你几个靠谱的实现方案~

先分析你之前的问题

  1. 继承std::map的思路不合理
    std::map压根不是设计来让你继承的——它没有虚析构函数,用基类指针操作派生类对象时会触发未定义行为。而且map的排序逻辑是由模板参数里的比较器决定的,重写insert方法完全是找错了方向。

  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 11:18:15