优先选 std::unordered_map 统计字符频次,因其平均 o(1) 时间复杂度;需 ascii 排序时才用 std::map;注意大小写区分、空格标点独立计数;避免对空串或含 '\0' 串使用 map[ch]++;utf-8 多字节字符需专用处理;降序输出须转 vector 后按 second 排序。

用 std::map<char int></char> 统计字符频次最直观
直接遍历字符串,对每个 char 在 std::map 中自增计数即可。它自动按字符 ASCII 顺序排序,适合需要有序输出的场景。
- 注意
std::map插入不存在的 key 时会默认初始化为 0,所以freq[c]++安全可用 - 区分大小写:'
A' 和 'a' 被视为不同字符 - 空格、换行符、标点都会被计入,如需忽略需提前过滤
- 性能上,单次插入/查找是
O(log n),总复杂度O(n log k)(k 是不同字符数)
追求速度?改用 std::unordered_map<char int></char>
当字符串很长、字符集较小时(比如纯英文文本),std::unordered_map 平均 O(1) 查找更快,但不保证遍历顺序。
- 必须包含
<unordered_map></unordered_map>头文件 - 若需按出现顺序打印结果,不能依赖遍历
unordered_map的顺序——它和插入顺序无关 - 极端情况下哈希冲突多时退化为
O(n),但实际中极少发生 - 示例写法:
freq[c]++同样适用,无需手动检查 key 是否存在
ASCII 字符专用:数组代替 map 更快更省
如果确定输入只含 ASCII 字符(0–127),用长度为 128 的 int 数组替代 map,性能提升明显,内存也更紧凑。
- 声明:
int freq[128] = {};—— 确保全部初始化为 0 - 访问:
freq[static_cast<unsigned char>(c)]++</unsigned>,强制转为unsigned char防止负值下标(如char在某些平台默认 signed) - 打印时跳过计数为 0 的索引,或只遍历可见 ASCII(32–126)
- 不适用于 Unicode(UTF-8 多字节)或宽字符,强行扩展到 65536 会浪费大量空间
遇到中文或 UTF-8 字符怎么办
标准 char 无法表示一个中文字符(UTF-8 中占 3 字节),直接按 char 统计只会得到乱码字节频次,不是你想要的“汉字频次”。
- 真正统计汉字需先做 UTF-8 解码,提取 Unicode 码点,再用
std::map<char32_t int></char32_t>或std::unordered_map - 简单方案:用
std::string的substr()+ 自行解析 UTF-8 字节序列(首字节高位模式判断长度),但易出错 - 推荐借助 ICU 或
utf8cpp库,例如用utf8::next()逐个提取合法码点 - 命令行读入时确认终端编码与程序处理一致,否则
std::cin可能截断多字节序列
unordered_map 是通用平衡选择,而中文场景绕不开 UTF-8 解码这一步——跳过它,统计结果就只是字节分布,不是字符分布。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











