元素为自定义复合结构时 map,set 如何处理重复 key 及排序?
2015-07-26 13:50
471 查看
map, set 为 类模板,创建对象时需要指定 comparator, 如果不指定,默认使用 less. 因此,我们有 2 中方式可以选择:
1. 采用默认的 less, 我们需要重载关系运算符 "<". 但是我们不推荐这样做,这种方式可读性很差,因为我们从代码上根本看不出来 "<" 在哪里被调用;
2. 指定 functor, 传入的是一个functor 类名,而不是一个函数或 functor 对象。
下面的例子是一个排行榜,排序规则如下:
1. 按分数由高到低排;
2. 分数一样的情况下,按时间由新到旧排;
3. 时间也一样的情况下,按用户 ID 由小到大排。
延伸阅读:
函数调用符重载
【STL】<algorithm><numeric><functional> 中的常用算法
【map】【set】poj 3297
STL中map,multimap,set,multiset,unordered_map,unordered_multimap,unordered_set,unordered_multiset的实现方法
STL map, multimap, set, multiset 函数介绍
1. 采用默认的 less, 我们需要重载关系运算符 "<". 但是我们不推荐这样做,这种方式可读性很差,因为我们从代码上根本看不出来 "<" 在哪里被调用;
2. 指定 functor, 传入的是一个functor 类名,而不是一个函数或 functor 对象。
下面的例子是一个排行榜,排序规则如下:
1. 按分数由高到低排;
2. 分数一样的情况下,按时间由新到旧排;
3. 时间也一样的情况下,按用户 ID 由小到大排。
方法一:重载 "<"
#include <iostream> #include <map> namespace test { // sorted by score in descending order > // then sorted by timestamp in descending order > // then sorted by id in ascending order class UserRank { public: UserRank(int id, int score, int timestamp) : id(id), score(score), timestamp(timestamp) { } ~UserRank() { } // The default comparator of map(set) is class template "less", // for user defined types, you must overload operator "<". friend bool operator<(const UserRank& left, const UserRank& right); friend void PrintUserRank(const UserRank& userRank); private: int id; int score; int timestamp; }; bool operator<(const UserRank& left, const UserRank& right) { if (left.score == right.score) { if (left.timestamp == right.timestamp) { return (left.id < right.id); } else { return (left.timestamp > right.timestamp); } } else { return (left.score > right.score); } } void PrintUserRank(const UserRank& userRank) { std::cout << "id: " << userRank.id << ", " << "score: " << userRank.score << ", " << "timestamp: " << userRank.timestamp << std::endl; } } int main() { /////////////////////////////////////////////////////// std::map<test::UserRank, int> rankList; test::UserRank user1(1, 100, 2015); test::UserRank user2(1, 100, 2015); test::UserRank user3(1, 100, 2014); rankList[user1] = 1; rankList[user2] = 2; rankList[user3] = 3; std::cout << rankList[user1] << std::endl; // 2 std::cout << rankList[user2] << std::endl; // 2 std::cout << rankList[user3] << std::endl; // 3 /////////////////////////////////////////////////////// // check order test::UserRank user4(1, 100, 2015); test::UserRank user5(1, 200, 2015); test::UserRank user6(1, 200, 2014); test::UserRank user7(2, 200, 2014); rankList.clear(); rankList[user4] = 1; rankList[user5] = 2; rankList[user6] = 3; rankList[user7] = 4; for (std::map<test::UserRank, int>::iterator it = rankList.begin(); it != rankList.end(); ++it) { PrintUserRank(it->first); } return 0; }
方法二:自定义 functor
#include <iostream> #include <map> namespace test { // sorted by score in descending order > // then sorted by timestamp in descending order > // then sorted by id in ascending order class UserRank { public: UserRank(int id, int score, int timestamp) : id(id), score(score), timestamp(timestamp) { } ~UserRank() { } // The default comparator of map(set) is class template "less", // for user defined types, you must overload operator "<". friend struct UserComp; friend void PrintUserRank(const UserRank& userRank); private: int id; int score; int timestamp; }; struct UserComp { bool operator()(const UserRank& left, const UserRank& right) { if (left.score == right.score) { if (left.timestamp == right.timestamp) { return (left.id < right.id); } else { return (left.timestamp > right.timestamp); } } else { return (left.score > right.score); } } }; void PrintUserRank(const UserRank& userRank) { std::cout << "id: " << userRank.id << ", " << "score: " << userRank.score << ", " << "timestamp: " << userRank.timestamp << std::endl; } } int main() { /////////////////////////////////////////////////////// std::map<test::UserRank, int, test::UserComp> rankList; test::UserRank user1(1, 100, 2015); test::UserRank user2(1, 100, 2015); test::UserRank user3(1, 100, 2014); rankList[user1] = 1; rankList[user2] = 2; rankList[user3] = 3; std::cout << rankList[user1] << std::endl; // 2 std::cout << rankList[user2] << std::endl; // 2 std::cout << rankList[user3] << std::endl; // 3 /////////////////////////////////////////////////////// // check order test::UserRank user4(1, 100, 2015); test::UserRank user5(1, 200, 2015); test::UserRank user6(1, 200, 2014); test::UserRank user7(2, 200, 2014); rankList.clear(); rankList[user4] = 1; rankList[user5] = 2; rankList[user6] = 3; rankList[user7] = 4; for (std::map<test::UserRank, int>::iterator it = rankList.begin(); it != rankList.end(); ++it) { PrintUserRank(it->first); } return 0; }
延伸阅读:
函数调用符重载
【STL】<algorithm><numeric><functional> 中的常用算法
【map】【set】poj 3297
STL中map,multimap,set,multiset,unordered_map,unordered_multimap,unordered_set,unordered_multiset的实现方法
STL map, multimap, set, multiset 函数介绍
相关文章推荐
- POJ 2724 Purifying Machine
- 曾国藩:成大事者不纠结
- 字符串指针与char型指针数组
- 01-复杂度1. 最大子列和问题(20)
- 【转】C/C++中可变参数的详细介绍(va_list,va_start,va_arg,va_end)
- jdbc 配置properties实现
- nfs
- java:用UDP协议,开发一个聊天工具代码
- 在自己的网站添加关注新浪关注按钮
- WCF分布式事务(EF)
- BCB中的TLabel,TEdit和TMaskEdit
- 九度oj 1183
- 2015-点餐系统(客户端)
- 服务器的响应数据
- 科技咨询笔记
- Maticsoft.Framework for Asp.Net框架应用实例(一)
- SQL基础学习_01_数据库和表
- 输入、输出、错误输出
- listView分批和分页加载数据
- Sublime Text 2 注册码、插件