C++ map的基本操作和使用

来源:互联网 发布:2017 大数据 大会 编辑:程序博客网 时间:2024/06/04 17:44

 

map是c++一类关联式容器,它是模板类。关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置类获取。它的特点是增加和删除节点对迭代器的影响很小,除了操作节点,对其他的节点都没有什么影响。对于迭代器来说,不可以修改键值,只能修改其对应的实值。

头文件

#include <map>


 map的基本操作函数:
 
     C++ Maps是一种关联式容器,包含“关键字/值”对
     begin()                 返回指向map头部的迭代器
     clear()                删除所有元素
     count()                 返回指定元素出现的次数
     empty()                如果map为空则返回true
     end()                    返回指向map末尾的迭代器
     equal_range()      返回特殊条目的迭代器对
     erase()                  删除一个元素
     find()                     查找一个元素
     get_allocator()      返回map的配置器
     insert()                  插入元素
     key_comp()          返回比较元素key的函数
     lower_bound()      返回键值>=给定元素的第一个位置
     max_size()            返回可以容纳的最大元素个数
     rbegin()                 返回一个指向map尾部的逆向迭代器
     rend()                    返回一个指向map头部的逆向迭代器
     size()                     返回map中元素的个数
     swap()                   交换两个map
     upper_bound()      返回键值>给定元素的第一个位置
     value_comp()        返回比较元素value的函数

1、 map最基本的构造函数;


        map<string , int >  mapstring2int;

        map<int ,string >   mapint2string;

        map<sring, char>  mapstring2char;

        map< char ,string> mapchar2string;

        map<char ,int>       mapchar2int;
 
        map<int ,char >      mapint2char;

 

    typedef  map<int, string > MAP_INT_STR

    MAP_INT_STR enumMap;


2、在map中插入元素

    改变map中的条目非常简单,因为map类已经对[]操作符进行了重载

    enumMap[1] = "One";

    enumMap[2] = "Two";

    .....

    这样非常直观,但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为"Two"; 该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。我们可以用以下方法来避免开销:

    enumMap.insert(map<int, string> :: value_type(2, "Two"))

    1) enumMap.insert(pair<int,string>(102,"aclive"));  //pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同
    2) enumMap.insert(map<int,string>::value_type(321,"hai"));
    3) enumMap[112]="April";                            //map中最简单最常用的插入添加!


3、查找并获取map中的元素

    我们可以使用Find()和Count()方法来发现一个键是否存在。
    1)查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key,在这里需要提到的是begin()和end()两个成员,分别代表map对象中第一个条目和最后一个条目,这两个数据的类型是iterator.
   
    find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器。

    int nFindKey = 112;                 //要查找的Key
    map<int ,string >::iterator iter;;  //定义一个条目变量(实际是指针)
    iter = enumMap.find(nFindKey);
    if(iter == enumMap.end())
    {
        cout<<"we do not find 112"<<endl;
    }
    else
    {
        cout<<"wo find 112"<<endl;
    }

    通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据 iterator->first 和 iterator->second 分别代表关键字和存储的数据
   
    2)下标操作符给出了获得一个值的最简单方法:

    string tmpstr = enumMap[2];

    但是,只有当map中有这个键的实例时才对,否则会自动插入一个实例,值为初始化值。

 


4、从map中删除元素

    移除某个map中某个条目用erase()

    该成员方法的定义如下

    iterator erase(iterator it);                    //通过一个条目对象删除
    iterator erase(iterator first, iterator last);  //删除一个范围
    size_type erase(const Key& key);                //通过关键字删除
    clear()就相当于 enumMap.erase(enumMap.begin(), enumMap.end());

     如果删除112;
     int iEraseKey = 112;
     map<int ,string >::iterator iter;;
     iter=enumMap.find(iEraseKey);
     if(iter==enumMap.end())
     {
        cout<<"we do not find 112"<<endl;   
     }
     else
     {
        enumMap.erase(iter); //delete 112;
     }
     像上面这样只是删除单个节点,map的形为不会出现任务问题.
     但是当在一个循环里用的时候,往往会被误用,那是因为使用者没有正确理解iterator的概念.
     像下面这样的一个例子就是错误的写法,
     eg.
     typedef map<int ,string >::iterator  ITER;
     for(ITER iter=mapTest.begin();iter!=mapTest.end();++iter)
     {
         cout<<iter->first<<":"<<iter->second<<endl;
         mapTest.erase(iter);
     }
    这是一种错误的写法,会导致程序行为不可知.究其原因是map是关联容器,对于关联容器来说,如果某一个元素已经被删除,那么其对应的迭代器就失效了,不应该再被使用;否则会导致程序无定义的行为。
   
    可以用以下方法解决这问题:
    正确的写法
    1).使用删除之前的迭代器定位下一个元素。STL建议的使用方式
    for(ITER iter=mapTest.begin();iter!=mapTest.end();)
    {
        cout<<iter->first<<":"<<iter->second<<endl;
        mapTest.erase(iter++); // 这是与之前代码不同的地方
    }

    2). erase() 成员函数返回下一个元素的迭代器
    for(ITER iter=mapTest.begin();iter!=mapTest.end();)
    {
        cout<<iter->first<<":"<<iter->second<<endl;
        iter=mapTest.erase(iter);
    }

    
5、map中 swap的用法:

 Map中的swap不是一个容器中的元素交换,而是两个容器交换;
 For example:
 
 #include <map>
 #include <iostream>

 using namespace std;

 int main( )
 {
    map <int, int> m1, m2, m3;
    map <int, int>::iterator m1_Iter;

    m1.insert ( pair <int, int> ( 1, 10 ) );
    m1.insert ( pair <int, int> ( 2, 20 ) );
    m1.insert ( pair <int, int> ( 3, 30 ) );
    m2.insert ( pair <int, int> ( 10, 100 ) );
    m2.insert ( pair <int, int> ( 20, 200 ) );
    m3.insert ( pair <int, int> ( 30, 300 ) );

     cout << "The original map m1 is:";
     for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
     {
        cout << " " << m1_Iter->second; 
     }
     cout << "." << endl;

    // This is the member function version of swap
    //m2 is said to be the argument map; m1 the target map
    m1.swap( m2 );

    cout << "After swapping with m2, map m1 is:";
    for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
    {
        cout << " " << m1_Iter -> second;
    }
    cout << "." << endl;
   
    cout << "After swapping with m2, map m2 is:";
    for ( m1_Iter = m2.begin( ); m1_Iter != m2.end( ); m1_Iter++ )
    {
        cout << " " << m1_Iter -> second;  
    }
    cout << "." << endl;
   
    // This is the specialized template version of swap
    swap( m1, m3 );

    cout << "After swapping with m3, map m1 is:";
    for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
    {
        cout << " " << m1_Iter -> second;
    }

    cout << "." << endl;
}

6、map的sort问题:

 Map中的元素是自动按key升序排序,所以不能对map用sort函数:
 For example:
 #include <map>
 #include <iostream>

 using namespace std;


 int main( )
 {
     map <int, int> m1;
     map <int, int>::iterator m1_Iter;

     m1.insert ( pair <int, int> ( 1, 20 ) );
     m1.insert ( pair <int, int> ( 4, 40 ) );
     m1.insert ( pair <int, int> ( 3, 60 ) );
     m1.insert ( pair <int, int> ( 2, 50 ) );
     m1.insert ( pair <int, int> ( 6, 40 ) );
     m1.insert ( pair <int, int> ( 7, 30 ) );

     cout << "The original map m1 is:"<<endl;
     for ( m1_Iter = m1.begin( ); m1_Iter != m1.end( ); m1_Iter++ )
     cout << m1_Iter->first<<" "<<m1_Iter->second<<endl;
    
}

 The original map m1 is:
 1 20
 2 50
 3 60
 4 40
 6 40
 7 30
 请按任意键继续. . .
 
map的举例
 
要求: 将mymap中itemstruct的a大于100的项删除 
struct itemstruct
{
    int    a;
    char   b[20];
};
 
map<string, itemstruct> mymap.
 
解答1:
#include   <iostream>
#include   <ctime>
#include   <map>
using   namespace   std;
typedef struct itemstruct
{
    int   a;
    char  b[20];
}itemS;
itemS s[4] =
{
    {102,"what"},
    {33, "hello"},
    {198,"world"},
    {45, "c++"}
};


int main()
{
    map<string,   itemS>     mymap;
    string   str[4]   =   {"1st","2nd","3rd","4th"};
    for(int   i   =   0;   i<4;   i++)
    {
        mymap.insert(make_pair(str[i],   s[i]));
    }

    map<string,itemS>::iterator   it;
    for(it=mymap.begin();   it!=mymap.end(); it++)
    {
        if(it->second.a >100){
        i=mymap.erase(it);  ----->正确
        mymap.erase(it);     ----->it失效..
    }
   
    //first是Key, second是value;
    for(it = mymap.begin();  it!=mymap.end(); it++)
    {
        cout<<it->first<<"   "<<it->second.a<<"   "<<it->second.b<<endl;
    }
    system("pause");
    return   0;
}


 

 

0 0