map, set 为 类模板,创建对象时需要指定 comparator, 如果不指定,默认使用 less. 因此,我们有 2 中方式可以选择:
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;
}
#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;
}
延伸阅读:
因篇幅问题不能全部显示,请点此查看更多更全内容