C++ map详解
1.什么是map
map是一个键值对容器。在处理一对一数据是,很有用。
2.map数据结构的特点
map内部自建一颗红黑树,这棵树具有对数据自动排序的功能,
因此,map内的数据都是按key的值排好序的。
3.map数据插入
数据的插入有三种方法:
第一种,调用insert函数,插入pair类型数据
示例如下所示:
#include <map> #include <string> #include <iostream> Using namespace std; int main() { map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, “student_one”)); mapStudent.insert(pair<int, string>(2, “student_two”)); mapStudent.insert(pair<int, string>(3, “student_three”)); map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) { cout<<iter->first<<” ”<<iter->second<<end; } return 0; }
第二种,调用insert插入value_type类型数据
示例如下所示:
#include <map> #include <string> #include <iostream> Using namespace std; int main() { map<int, string> mapStudent; mapStudent.insert(map<int, string>::value_type(1, “student_one”)); mapStudent.insert(map<int, string>::value_type(2, “student_two”)); mapStudent.insert(map<int, string>::value_type(3, “student_three”)); map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) { cout<<iter->first<<” ”<<iter->second<<end; } return 0; }
第三种,使用数组赋值方式
#include <map> #include <string> #include <iostream> Using namespace std; int main() { map<int, string> mapStudent; mapStudent[1]="student_one"; mapStudent[2]="student_two"; mapStudent[3]="student_three"; map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) { cout<<iter->first<<” ”<<iter->second<<end; } return 0; }
如何判断数据是否插入成功?
insert函数的返回值类型为:Pair<map<int,string>::iterator,bool>
返回值的key值表示,返回map的迭代器
返回值的value值表示,是否插入成功
因此,我们可以使用以下代码来判断,map键值对是否插入成功
Pair<map<int,string>::iterator,bool> Insert_Pair=mapStudent.insert(pair<int, string>(1, “student_one”)); if(Insert_Pair.second) cout<<"success.\n"; else cout<<"failed.\n";
4.map数据查找
第一种,使用count方法判定是否存在
第二种,使用find方法,定位key出现的位置,该方法返回一个迭代器。
当数据出现时,返回数据所在位置的迭代器;
否则,返回的迭代器等于end方法返回的迭代器。
示例代码如下:
map<int,string>::iterator iter; iter=mapStudent.find(1); if(iter!=mapStudent.end()) cout<<"success find.\n"; else cout<<"failed.\n";
第三种,使用Lower_bound,Upper_bound方法,返回key的边界,在此,不再详细介绍。
5.map数据删除
使用了我们很熟悉的erase函数,map中该函数有三个重载。
1)使用迭代器删除
map<int,string>::iterator iter; iter = mapStudent.find(1); mapStudent.erase(iter);
2)使用关键字key删除
int result = mapStudent.erase(1);
成功返回1,否则返回0
3)使用迭代器,删除区间内的数据
mapStudent.erase(mapStudent.begin(),mapStudent.end());
6.关于map的自动排序
前面我们说过,map内的数据会根据key值由大到小排序,
也就是说key值必须支持小于<运算,否则无法插入map。
对于上面的示例,我们知道int类型本身是支持小于运算的。
但是对于不支持小于运算的key类型,我们该如何插入map呢?
很显然,我们需要自定义该类型的<操作符。
如下例所示,我们要建立一个map<学生信息,分数>:
typedef struct tagStudentInfo { int nID; string strName; bool operator<(tagStudentInfo const &_A) const { if(nID<_A.nID) return true; return false; } }StudentInfo,*PStudentInfo; int main() { map<StudentInfo,int> mapStudent; StudentInfo studentInfo; studentInfo.nID=1; studentInfo.strName="student_one"; mapStudent.insert(pair<StudentInfo, int>(studentInfo,80)); return 0; }
另外一种方式是,定义一个单独的类,类中定义key类型的比较函数
示例代码如下:
typedef struct tagStudentInfo { int nID; string strName; }StudentInfo,*PStudentInfo; class sort { public: bool operator()(tagStudentInfo const &_A,tagStudentInfo const &_B) const { if(_A.nID<_B.nID) return true; return false; } } int main() { map<StudentInfo,int,sort> mapStudent; StudentInfo studentInfo; studentInfo.nID=1; studentInfo.strName="student_one"; mapStudent.insert(pair<StudentInfo, int>(studentInfo,80)); return 0; }
7.map内存占用
前面我们介绍过,map的数据结构为一颗红黑树,
该树的一个节点在不保存数据时,占用16字节的空间,
包括一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子),
可见,map还是很耗内存的。