Set、Map:
对于map、set来说如果是基本类型,默认从小到大。但如果是自定义类型或者非基本类型(比如vector这种),那么就需要自己重载相应的规则。
举例:
我知道的map重载从大到小的几种方法:
1、Lambda:
auto cmp=[](int x,int y){return x>y;}; map<int,int,decltype(cmp)> p(cmp);
2、定义比较函数:
bool cmp(int x,int y){ return x>y; } map<int,int,decltype(cmp)> p(cmp);
3、结构体作为key的话,结构体中重载小于号(重载大于号也可以)
struct eg { int x,y; eg(int a,int b):x(a),y(b){} bool operator<(const eg& other)const{ return x>other.x; } }; int main() { map<eg,int> p; p[eg(1,2)]=1; getchar(); }
4、利用仿函数(在类中重载函数运算符)
struct eg { int x,y; eg(int a,int b):x(a),y(b){} // bool operator<(const eg& other)const{ // return x>other.x; // } }; struct cmp{ bool operator() (const eg& a,const eg& b){ return a.x>b.x; } }; int main() { map<eg,int,cmp> p; p[eg(1,2)]=1; getchar(); }
对于set来说也是一样的,大家自己试试就好了。
unordered_map和unordered_set:
这两种容器内部实现是HASH表,并且本身就是无序的,所以不需要之前map和set的比较大小函数,而是需要一种唯一映射key的方式。
这两种容器的Key如果是非基本类型or自定义类型,我们就需要指定一个hash函数。比如我们定义了一个类info,里面有学号、姓名、班级等等。系统不知道怎么确定不同的info变量是不是应该映射到一个值还是不同的值。
当然我们本身是希望系统按照学号给我们Hash就好了,即把学号作为主键。但系统不知道呀,所以我们得告诉它怎么来计算哈希。并且经过我的测试还需要重载==号,可能是当hash值相同的情况下比较元素到底相同还是不同用的。
用法如下:
struct eg { int x,y; eg(int a,int b):x(a),y(b){} bool operator==(const eg& other) const{//这个重载==号必须要写,否则报错 return x==other.x and y==other.y; } }; struct eg_hash { size_t operator() (const eg& a)const{//利用x的hash值和y的hansh值做异或得到eg的hash值 return hash<int>()(a.x) ^ hash<int>()(a.y); } }; int main() { unordered_map<eg,int,eg_hash> mp; unordered_set<eg,eg_hash> st; mp[eg(1,2)]=1; mp[eg(5,3)]=55; st.insert(eg(534,4235)); st.insert(eg(5,634)); getchar(); }
其中hash<int>()是一个hash模板类对象。该类重载了函数调用运算符,所以我们使用hash<int>()(xxxx)来计算xxxx的哈希值。
我们也可以写为:hash<int>().operator()(a.x)
如果你觉得两个括号不好理解的话,可以分两步写:
auto MyHash=hash<int>(); //创造一个hash模板类对象 int hash_result=MyHash(a.x) //或者 MyHash.operator(a.x)