C++中能否对map元素按值重排序?如何优雅实现字母频率表排序
问题1:是否可以重载map的比较器实现按值排序?
不可以。std::map是有序关联容器,它的排序规则仅作用于键(key),比较器的输入参数只有两个待比较的键,无法获取键对应的存储值。即使用特殊手段把value的指针传给比较器,也会存在两个核心问题:
- 插入元素时value还未完成赋值,比较逻辑会失效
- 后续修改value的值时,
std::map不会自动触发重排,完全不符合容器的设计预期
问题2:优雅的替代实现方案
你只需要将map中存储的键值对转存到vector中,再自定义排序规则即可,代码非常简洁,不需要复杂逻辑:
#include <vector> #include <string> #include <map> #include <algorithm> std::vector<char> get_rank(const std::string& str) { std::map<char, int> m; // 初始化26个小写字母计数为0 for (char i = 'a'; i <= 'z'; i++) m[i] = 0; // 统计字符出现次数 for (char ch : str) m[ch]++; // 将键值对转存到vector用于排序 std::vector<std::pair<char, int>> vec(m.begin(), m.end()); // 按出现次数降序排序,次数相同则按字母升序排序(符合字母频率表的常规规则) std::sort(vec.begin(), vec.end(), [](const std::pair<char, int>& a, const std::pair<char, int>& b) { if (a.second != b.second) return a.second > b.second; return a.first < b.first; }); // 提取排序后的字符到结果vector std::vector<char> res; res.reserve(26); for (auto& p : vec) res.push_back(p.first); return res; }
方案说明
- 整个逻辑只比原有代码多了转存vector、自定义排序、提取结果3步,代码清晰易读
- 排序规则可以灵活调整,如果需要按频率升序、或者频率相同按字母降序,只需要修改lambda表达式的返回逻辑即可
- 性能完全满足需求,26个元素的排序开销可以忽略不计
- 已修正原有代码中
v变量未声明就使用的编译问题
内容的提问来源于stack exchange,提问作者RussianStranger
相关产品推荐
相关产品推荐

