若干問題:

struct Node { int k, b; friend bool operator <(Node a, Node b) { return a.k < b.k; } }node1, node2; map<Node, int> mp; int main() { node1.k = 1; node1.b = 1; mp[node1] = 1; node1.k = 1; node1.b = 2; printf("%d\n", mp.count(node1)); //輸出1 return 0; }

struct Node { int k, b; friend bool operator <(Node a, Node b) { if (a.k != b.k) return a.k < b.k; else return a.b < b.b; } }node1, node2; map<Node, int> mp; int main() { node1.k = 1; node1.b = 1; mp[node1] = 1; node1.k = 1; node1.b = 2; printf("%d\n", mp.count(node1)); //輸出0 return 0; }
1、以結構體為Key
map內部自建一顆紅黑樹(一種非嚴格意義上的平衡二叉樹),紅黑樹具有對數據自動排序(默認是以less<>升序對元素排序(排序准則也可以修改))的功能,因此在map內部所有的關鍵字都是有序的。當key為基本數據類型時,不存在問題。但是當關鍵字是一個結構體時,涉及到排序就會出現問題,因為它沒有小於號操作,insert等函數在編譯的時候就會出錯,下面給出解決這個問題的方法:
對操作符"<"進行重載(不可以重載大於號)
#include <map> #include <iostream> #include <string> using namespace std; struct Node{ int id; string name; friend bool operator < (Node a,Node b) { //指定排序策略,按id排序,如果id相等的話,按name排序 if (a.id != b.id) return a.id > b.id; else return a.name > b.name; } }StudentInfo, *pStudentInfo; //學生信息 int main(){ int nSize; //用學生信息映射分數 map<Node, int> mapStudent; map<Node, int>::iterator it; StudentInfo.id = 1; StudentInfo.name = "student_one"; mapStudent.insert(pair<Node, int>(StudentInfo, 90)); StudentInfo.id = 1; StudentInfo.name = "student_two"; mapStudent.insert(pair<Node, int>(StudentInfo, 80)); for (it = mapStudent.begin(); it != mapStudent.end(); it++) cout << it->first.id << " " << it->first.name << " " << it->second << endl; }
printf("%d",mp.find(StudentInfo)->second); printf("%d",mp[StudentInfo]); 都可以
重載的部分可以寫到結構體外,但有三點要求:
1、把friend去掉,把小於號改成一對小括號。
2、用struct把函數包裝起來。
3、map的定義方式改為map<Node, int, cmp> mapStudent;
如:
#include <map> #include <iostream> #include <string> using namespace std; struct Node{ int id; string name; }StudentInfo, *pStudentInfo; //學生信息 struct cmp { bool operator () (Node a, Node b) { //指定排序策略,按nID排序,如果nID相等的話,按strName排序 if (a.id != b.id) return a.id > b.id; else return a.name > b.name; } }; map<Node, int, cmp> mapStudent; map<Node, int, cmp>::iterator it; int main(){ int nSize; //用學生信息映射分數 StudentInfo.id = 1; StudentInfo.name = "student_one"; mapStudent.insert(pair<Node, int>(StudentInfo, 90)); StudentInfo.id = 1; StudentInfo.name = "student_two"; mapStudent.insert(pair<Node, int>(StudentInfo, 80)); for (it = mapStudent.begin(); it != mapStudent.end(); it++) cout << it->first.id << " " << it->first.name << " " << it->second << endl; }
printf("%d",mp.find(StudentInfo)->second); printf("%d",mp[StudentInfo]); 也可以
2、以結構體指針為Key,可以不重載<號,因為地址可以比較大小。
但是也可以根據指針指向的內容重載小於號,但此時重載函數必須放在自定義的結構體外面。(原因不詳。。。)
#include <map> #include <iostream> #include <cstdio> using namespace std; struct Key { int x,y; }*ptr; struct CompareKey { bool operator()(Key *in_a, Key *in_b) { return in_a->x < in_b->x; } }; map<Key *, int, CompareKey> mp; int main() { for (int i = 0; i < 10; i++) { Key *k = new Key; if(i==6) ptr=k; k->x = i; k->y = i+1; mp.insert(make_pair(k, i)); } map<Key *, int, CompareKey>::iterator it; for(it=mp.begin();it!=mp.end();it++){ if(it->first==ptr){ printf("%d %d %d\n",it->first->x,it->first->y,it->second); } } }