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还是很耗内存的

posted on 2016-06-15 18:41  迪米特  阅读(9563)  评论(0编辑  收藏  举报

导航