C++实现:查找Route数组中出现频率最高的5个Address
解决思路:统计并排序Address出现频率
要找出Route数组中出现频率最高的5个Address,核心步骤是统计每个Address的出现次数,然后按频率排序取前5。下面一步步拆解实现方法:
1. 先确保Address可以被正确比较(关键前提)
因为我们需要把Address作为键存入哈希表或有序map来计数,所以必须让C++能够判断两个Address是否相等,以及(如果用std::map的话)比较两个Address的大小。
我们需要给Address和Location类重载必要的运算符:
- 重载
==:判断两个Address是否相同(通常要比较包含的Location以及其他地址属性,比如街道、城市等) - 重载
<:如果用std::map的话需要,用来排序键;如果用std::unordered_map,则需要自定义哈希函数(后面会给出两种方案)
2. 遍历所有Route,统计Address出现次数
创建一个计数容器(比如std::map<Address, int>或者std::unordered_map<Address, int>),然后遍历每个Route里的每一个Address,每遇到一次就把对应计数加1。
3. 将统计结果排序,取前5个
把计数容器里的键值对转换成std::vector<std::pair<Address, int>>,然后自定义排序规则,按计数从大到小排序。最后取前5个元素即可。
完整代码示例
先补全你的类定义,然后实现统计逻辑:
#include <iostream> #include <vector> #include <map> #include <algorithm> #include <string> // Location类:包含经纬度等位置信息 class Location { public: double lat; double lng; Location(double lat_, double lng_) : lat(lat_), lng(lng_) {} // 重载==,判断两个Location是否相同 bool operator==(const Location& other) const { // 考虑浮点数精度,这里简化直接比较,实际项目可以加误差范围(比如1e-9) return lat == other.lat && lng == other.lng; } // 重载<,用于std::map的排序 bool operator<(const Location& other) const { if (lat != other.lat) return lat < other.lat; return lng < other.lng; } }; // Address类:包含Location和其他地址属性 class Address { public: Location loc; std::string street; std::string city; Address(Location loc_, std::string street_, std::string city_) : loc(loc_), street(street_), city(city_) {} // 重载==,判断两个Address是否相同 bool operator==(const Address& other) const { return loc == other.loc && street == other.street && city == other.city; } // 重载<,用于std::map的排序 bool operator<(const Address& other) const { if (!(loc == other.loc)) return loc < other.loc; if (street != other.street) return street < other.street; return city < other.city; } }; // Route类:包含Address数组(这里用vector更灵活) class Route { public: std::vector<Address> addresses; Route(std::vector<Address> addrs_) : addresses(addrs_) {} }; int main() { // 测试数据:创建几个Route对象 Location loc1(39.9042, 116.4074); // 北京天安门 Location loc2(31.2304, 121.4737); // 上海外滩 Address addr1(loc1, "天安门广场", "北京市"); Address addr2(loc2, "中山东一路", "上海市"); Address addr3(loc1, "东长安街", "北京市"); Route route1({addr1, addr2, addr1}); Route route2({addr2, addr3, addr1, addr2}); Route route3({addr3, addr1, addr2, addr3}); std::vector<Route> routes = {route1, route2, route3}; // 步骤1:统计每个Address的出现次数 std::map<Address, int> addrCount; for (const auto& route : routes) { for (const auto& addr : route.addresses) { addrCount[addr]++; } } // 步骤2:将统计结果转换为vector并排序 std::vector<std::pair<Address, int>> countVec(addrCount.begin(), addrCount.end()); // 按出现次数从高到低排序,如果次数相同,按Address排序(可选) std::sort(countVec.begin(), countVec.end(), [](const auto& a, const auto& b) { if (a.second != b.second) { return a.second > b.second; } return a.first < b.first; }); // 步骤3:输出前5个频率最高的Address std::cout << "出现频率最高的5个Address:\n"; int take = std::min(5, (int)countVec.size()); for (int i = 0; i < take; ++i) { const auto& pair = countVec[i]; std::cout << "Address: " << pair.first.street << ", " << pair.first.city << " | 出现次数: " << pair.second << "\n"; } return 0; }
可选:用std::unordered_map优化性能
如果你的Address数量很大,std::unordered_map的查找和插入效率更高,但需要自定义哈希函数。可以给Address添加哈希特化:
#include <functional> // 为Location自定义哈希 namespace std { template<> struct hash<Location> { size_t operator()(const Location& loc) const { // 组合lat和lng的哈希值,这里用简单的方法,实际可以用更稳健的哈希组合 size_t h1 = hash<double>()(loc.lat); size_t h2 = hash<double>()(loc.lng); return h1 ^ (h2 << 1); } }; // 为Address自定义哈希 template<> struct hash<Address> { size_t operator()(const Address& addr) const { size_t h1 = hash<Location>()(addr.loc); size_t h2 = hash<string>()(addr.street); size_t h3 = hash<string>()(addr.city); return h1 ^ (h2 << 1) ^ (h3 << 2); } }; }
然后把统计部分的std::map换成std::unordered_map即可,其他逻辑不变。
注意事项
- 浮点数比较:如果Location的lat/lng是浮点数,直接用
==可能有精度问题,建议改成判断两个值的差小于某个极小值(比如1e-9)。 - 自定义排序:如果两个Address出现次数相同,可以根据业务需求调整排序规则(比如按地址名称排序)。
- 边界情况:如果总共有少于5个不同的Address,就输出全部即可,代码里用
std::min(5, (int)countVec.size())处理了这种情况。
内容的提问来源于stack exchange,提问作者Robert1428
相关产品推荐
相关产品推荐

