应选用 std::unordered_map<unsigned char, int> 统计字符频次,遍历时转 unsigned char 防符号扩展;再导出为 vector<pair<unsigned char, int>>,按频次降序、ASCII 升序排序;输出时区分可打印字符、控制符和非 ASCII 字节并格式化。

用 std::map 或 std::unordered_map 统计字符频次
直接遍历字符串,对每个 char 做计数即可。优先选 std::unordered_map<char int></char>,因为字符范围小(最多 256 种),哈希无冲突风险,插入和访问都是 O(1) 平均复杂度;而 std::map 是红黑树,O(log n) 且没必要排序——我们后续要自己重排。
注意点:
-
std::string中的char可能是带符号的,若字符串含非 ASCII 字符(如 UTF-8 中的多字节),char负值会作为 key 导致越界或误统计;此时应先转为unsigned char再映射 - 空字符串、只含空白符的字符串要能正常处理(频次 map 为空)
std::unordered_map<unsigned char, int> freq;
for (unsigned char c : s) {
freq[c]++;
}
用 std::vector + std::sort 按频次降序排列
std::unordered_map 本身不支持按 value 排序,必须导出为可排序容器。推荐转成 std::vector<std::pair<unsigned char, int>>,再用自定义 lambda 排序:
- 排序逻辑必须写清楚:先比
second(频次)降序,频次相同时建议按first(字符 ASCII 码)升序,避免相同频次输出顺序不确定 - 别直接对 map 迭代器排序——语法不合法;也别用
std::multimap<int, char>反向建索引,插入时频次未定,易出错 - 如果原字符串很大但不同字符极少(比如只有 20 种),vector 尺寸很小,排序开销可忽略
std::vector<std::pair<unsigned char, int>> vec(freq.begin(), freq.end());
std::sort(vec.begin(), vec.end(), [](const auto& a, const auto& b) {
if (a.second != b.second) return a.second > b.second;
return a.first < b.first;
});
输出时注意字符的可读性与转义
直接打印 unsigned char 可能输出不可见字符(如 <p>直接打印 <code>unsigned char 可能输出不可见字符(如