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)
