精华内容
下载资源
问答
  • map容器详细用法

    万次阅读 2016-10-06 17:28:00
    map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程...
     
     
    map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

    下面举例说明什么是一对一的数据映射。比如一个班级中,每个学生的学号跟他的姓名就存在着一一映射的关系,这个模型用map可能轻易描述,很明显学号用int描述,姓名用字符串描述(本篇文章中不用char *来描述字符串,而是采用STL中string来描述),下面给出map描述代码:

     

    点击进入我的个人博客

     

    [cpp]  view plain  copy
     
    1. map<int, string> mapStudent;  

     

     

    1.map的构造函数
    map共提供了6个构造函数,这块涉及到内存分配器这些东西,略过不表,在下面我们将接触到一些map的构造方法,这里要说下的就是,我们通常用如下方法构造一个map:

     

     

    [cpp]  view plain  copy
     
    1. map<int, string> mapStudent; 

     

     

    2.数据的插入
    在构造map容器后,我们就可以往里面插入数据了。这里讲三种插入数据的方法:
    第一种:用insert函数插入pair数据,下面举例说明(以下代码虽然是随手写的,应该可以在VC和GCC下编译通过,大家可以运行下看什么效果,在VC下请加入这条语句,屏蔽4786警告  #pragma warning (disable:4786) )

     

     

    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;//pair<int,string>p;p=make_pair(v1,v2);<span style="color: rgb(255, 0, 0); background-color: rgb(240, 248, 255); font-family: Arial; font-size: 13px; "> </span>  
    8.        mapStudent.insert(pair<int, string>(1, "student_one"));  
    9.        mapStudent.insert(pair<int, string>(2, "student_two"));  
    10.        mapStudent.insert(pair<int, string>(3, "student_three"));  
    11.        map<int, string>::iterator  iter;  
    12.        for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  
    13.        {  
    14.           cout<<iter->first<<"  "<<iter->second<<endl;  
    15.        }  
    16. }  

     

    [cpp]  view plain  copy
     
    1. make_pair()//返回类型为对应的pair类型  
    2. 无需写出类别,就可以生成一个pair对象  
    3. 例:  
    4. make_pair(1,'@')  
    5. 而不必费力的写成  
    6. pair<int ,char>(1,'@')  

     

    第二种:用insert函数插入value_type数据,下面举例说明
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;  
    8.        mapStudent.insert(map<int, string>::value_type (1, "student_one"));  
    9.        mapStudent.insert(map<int, string>::value_type (2, "student_two"));  
    10.        mapStudent.insert(map<int, string>::value_type (3, "student_three"));  
    11.        map<int, string>::iterator  iter;  
    12.        for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  
    13.        {  
    14.            cout<<iter->first<<" "<<iter->second<<endl;  
    15.        }  
    16. }  
    第三种:用数组方式插入数据,下面举例说明
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;  
    8.        mapStudent[1] =  "student_one";  
    9.        mapStudent[2] =  "student_two";  
    10.        mapStudent[3] =  "student_three";  
    11.        map<int, string>::iterator  iter;  
    12.        for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  
    13.        {  
    14.           cout<<iter->first<<"   "<<iter->second<<endl;  
    15.        }  
    16. }  
    以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值,用程序说明
    [cpp]  view plain  copy
     
    1. mapStudent.insert(map<int, string>::value_type (1, "student_one"));  
    2. mapStudent.insert(map<int, string>::value_type (1, "student_two"));  
    上面这两条语句执行后,map中1这个关键字对应的值是"student_one",第二条语句并没有生效,那么这就涉及到我们怎么知道insert语句是否插入成功的问题了,可以用pair来获得是否插入成功,程序如下
    [cpp]  view plain  copy
     
    1. Pair<map<int, string>::iterator, bool> Insert_Pair;  
    2. Insert_Pair = mapStudent.insert(map<int, string>::value_type (1, "student_one"));  
    我们通过pair的第二个变量来知道是否插入成功,它的第一个变量返回的是一个map的迭代器,如果插入成功的话Insert_Pair.second应该是true的,否则为false。
    下面给出完成代码,演示插入成功与否问题
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;  
    8.        Pair<map<int, string>::iterator, bool> Insert_Pair;  
    9.        Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_one"));  
    10.        If(Insert_Pair.second == true)  
    11.        {  
    12.              cout<<"Insert Successfully"<<endl;  
    13.        }  
    14.        Else  
    15.        {  
    16.               cout<<"Insert Failure"<<endl;  
    17.        }  
    18.        Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_two"));  
    19.        If(Insert_Pair.second == true)  
    20.        {  
    21.               cout<<"Insert Successfully"<<endl;  
    22.        }  
    23.        Else  
    24.        {  
    25.               cout<<"Insert Failure"<<endl;  
    26.        }  
    27.        map<int, string>::iterator  iter;  
    28.        for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  
    29.        {  
    30.             cout<<iter->first<<"   "<<iter->second<<endl;  
    31.        }  
    32. }  
    大家可以用如下程序,看下用数组插入在数据覆盖上的效果
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;  
    8.        mapStudent[1] =  "student_one";  
    9.        mapStudent[1] =  "student_two";  
    10.        mapStudent[2] =  "student_three";  
    11.        map<int, string>::iterator  iter;  
    12.        for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  
    13.        {  
    14.           cout<<iter->first<<"   "<<iter->second<<endl;  
    15.        }  
    16. }  
    3.map的大小
    在往map里面插入了数据,我们怎么知道当前已经插入了多少数据呢,可以用size函数,用法如下:
    [cpp]  view plain  copy
     
    1. int nSize = mapStudent.size();  
    4.数据的遍历
    这里也提供三种方法,对map进行遍
    第一种:应用前向迭代器,上面举例程序中到处都是了,略过不表
    第二种:应用反相迭代器,下面举例说明,要体会效果,请自个动手运行程序
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;  
    8.        mapStudent.insert(pair<int, string>(1, "student_one"));  
    9.        mapStudent.insert(pair<int, string>(2, "student_two"));  
    10.        mapStudent.insert(pair<int, string>(3, "student_three"));  
    11.        map<int, string>::reverse_iterator  iter;  
    12.        for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)  
    13.        {  
    14.           cout<<iter->first<<"   "<<iter->second<<endl;  
    15.        }  
    16. }  
    第三种:用数组方式,程序说明如下
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;  
    8.        mapStudent.insert(pair<int, string>(1, "student_one"));  
    9.        mapStudent.insert(pair<int, string>(2, "student_two"));  
    10.        mapStudent.insert(pair<int, string>(3, "student_three"));  
    11.        int nSize = mapStudent.size()  
    12. //此处有误,应该是 for(int nIndex = 1; nIndex <= nSize; nIndex++)   
    13. //by rainfish  
    14.        for(int nIndex = 0; nIndex < nSize; nIndex++)  
    15.        {  
    16.            cout<<mapStudent[nIndex]<<end;  
    17.        }  
    18. }  
    5.数据的查找(包括判定这个关键字是否在map中出现)
    在这里我们将体会,map在数据插入时保证有序的好处。
    要判定一个数据(关键字)是否在map中出现的方法比较多,这里标题虽然是数据的查找,在这里将穿插着大量的map基本用法。
    这里给出三种数据查找方法
    第一种:用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置,由于map的特性,一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了
    第二种:用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器,程序说明
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;  
    8.        mapStudent.insert(pair<int, string>(1, "student_one"));  
    9.        mapStudent.insert(pair<int, string>(2, "student_two"));  
    10.        mapStudent.insert(pair<int, string>(3, "student_three"));  
    11.        map<int, string>::iterator iter;  
    12.        iter = mapStudent.find(1);  
    13.        if(iter != mapStudent.end())  
    14.       {  
    15.            cout<<"Find, the value is "<<iter->second<<endl;  
    16.        }  
    17.        Else  
    18.        {  
    19.            cout<<"Do not Find"<<endl;  
    20.        }  
    21. }  
    第三种:这个方法用来判定数据是否出现,是显得笨了点,但是,我打算在这里讲解
    Lower_bound函数用法,这个函数用来返回要查找关键字的下界(是一个迭代器)
    Upper_bound函数用法,这个函数用来返回要查找关键字的上界(是一个迭代器)
    例如:map中已经插入了1,2,3,4的话,如果lower_bound(2)的话,返回的2,而upper-bound(2)的话,返回的就是3
    Equal_range函数返回一个pair,pair里面第一个变量是Lower_bound返回的迭代器,pair里面第二个迭代器是Upper_bound返回的迭代器,如果这两个迭代器相等的话,则说明map中不出现这个关键字,程序说明
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;  
    8.        mapStudent[1] =  "student_one";  
    9.        mapStudent[3] =  "student_three";  
    10.        mapStudent[5] =  "student_five";  
    11.        map<int, string>::iterator  iter;  
    12.        iter = mapStudent.lower_bound(2);  
    13.       {  
    14.        //返回的是下界3的迭代器  
    15.        cout<<iter->second<<endl;  
    16.        }  
    17.        iter = mapStudent.lower_bound(3);  
    18.        {  
    19.        //返回的是下界3的迭代器  
    20.        cout<<iter->second<<endl;  
    21.        }  
    22.         iter = mapStudent.upper_bound(2);  
    23.        {  
    24.        //返回的是上界3的迭代器  
    25.         cout<<iter->second<<endl;  
    26.        }  
    27.        iter = mapStudent.upper_bound(3);  
    28.       {  
    29.        //返回的是上界5的迭代器  
    30.        cout<<iter->second<<endl;  
    31. }  
    32.       Pair<map<int, string>::iterator, map<int, string>::iterator> mapPair;  
    33.       mapPair = mapStudent.equal_range(2);  
    34.       if(mapPair.first == mapPair.second)  
    35.       {  
    36.           cout<<"Do not Find"<<endl;  
    37.        }  
    38.        Else  
    39.        {  
    40.             cout<<"Find"<<endl;  
    41.         }  
    42.        mapPair = mapStudent.equal_range(3);  
    43.        if(mapPair.first == mapPair.second)  
    44.        {  
    45.             cout<<"Do not Find"<<endl;  
    46.         }  
    47.        Else  
    48.        {  
    49.            cout<<"Find"<<endl;  
    50.        }  
    51. }  
    6.  数据的清空与判空
    清空map中的数据可以用clear()函数,判定map中是否有数据可以用empty()函数,它返回true则说明是空map
    7.  数据的删除
    这里要用到erase函数,它有三个重载了的函数,下面在例子中详细说明它们的用法
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. #include <iostream>  
    4. using namespace std;  
    5. int main()  
    6. {  
    7.        map<int, string> mapStudent;  
    8.        mapStudent.insert(pair<int, string>(1, "student_one"));  
    9.        mapStudent.insert(pair<int, string>(2, "student_two"));  
    10.        mapStudent.insert(pair<int, string>(3, "student_three"));  
    11.        //如果你要演示输出效果,请选择以下的一种,你看到的效果会比较好  
    12.        //如果要删除1,用迭代器删除  
    13.        map<int, string>::iterator iter;  
    14.        iter = mapStudent.find(1);  
    15.        mapStudent.erase(iter);  
    16.        //如果要删除1,用关键字删除  
    17.        int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0  
    18.        //用迭代器,成片的删除  
    19.        //一下代码把整个map清空  
    20.        mapStudent.earse(mapStudent.begin(), mapStudent.end());  
    21.        //成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合  
    22.      //自个加上遍历代码,打印输出吧  
    23. }  
    8.其他一些函数用法
    这里有swap,key_comp,value_comp,get_allocator等函数,感觉到这些函数在编程用的不是很多,略过不表,有兴趣的话可以自个研究
    9.排序
    这里要讲的是一点比较高深的用法了,排序问题,STL中默认是采用小于号来排序的,以上代码在排序上是不存在任何问题的,因为上面的关键字是int型,它本身支持小于号运算,在一些特殊情况,比如关键字是一个结构体,涉及到排序就会出现问题,因为它没有小于号操作,insert等函数在编译的时候过不去,下面给出两个方法解决这个问题
    第一种:小于号重载,程序举例
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. uing namespace std;  
    4. Typedef struct tagStudentInfo  
    5. {  
    6.        int      nID;  
    7.        String   strName;  
    8. }StudentInfo, *PStudentInfo;  //学生信息  
    9. int main()  
    10. {  
    11.        int nSize;  
    12.        //用学生信息映射分数  
    13.        map<StudentInfo, int>mapStudent;  
    14.        map<StudentInfo, int>::iterator iter;  
    15.        StudentInfo studentInfo;  
    16.        studentInfo.nID = 1;  
    17.        studentInfo.strName = "student_one"  
    18.        mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));  
    19.        studentInfo.nID = 2;  
    20.        studentInfo.strName = "student_two";  
    21.        mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));  
    22.        for (iter=mapStudent.begin(); iter!=mapStudent.end(); iter++)  
    23.          cout<<iter->first.nID<<endl<<iter->first.strName<<endl<<iter->second<<endl;  
    24. }  
    以上程序是无法编译通过的,只要重载小于号,就OK了,如下:
    [cpp]  view plain  copy
     
    1. Typedef struct tagStudentInfo  
    2. {  
    3.        int      nID;  
    4.        String   strName;  
    5.        Bool operator < (tagStudentInfo const& _A) const  
    6.        {  
    7.               //这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序  
    8.               If(nID < _A.nID)  return true;  
    9.               If(nID == _A.nID) return strName.compare(_A.strName) < 0;  
    10.               Return false;  
    11.        }  
    12. }StudentInfo, *PStudentInfo;  //学生信息  
    第二种:仿函数的应用,这个时候结构体中没有直接的小于号重载,程序说明
    [cpp]  view plain  copy
     
    1. #include <map>  
    2. #include <string>  
    3. using namespace std;  
    4. Typedef struct tagStudentInfo  
    5. {  
    6.        int      nID;  
    7.        String   strName;  
    8. }StudentInfo, *PStudentInfo;  //学生信息  
    9. class sort  
    10. {  
    11.        Public:  
    12.        Bool operator() (StudentInfo const &_A, StudentInfo const &_B) const  
    13.        {  
    14.               If(_A.nID < _B.nID) return true;  
    15.               If(_A.nID == _B.nID) return _A.strName.compare(_B.strName) < 0;  
    16.               Return false;  
    17.        }  
    18. };  
    19. int main()  
    20. {  
    21.        //用学生信息映射分数  
    22.        map<StudentInfo, int, sort>mapStudent;  
    23.        StudentInfo studentInfo;  
    24.        studentInfo.nID = 1;  
    25.        studentInfo.strName = "student_one";  
    26.        mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));  
    27.        studentInfo.nID = 2;  
    28.        studentInfo.strName = "student_two";  
    29.        mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));  
    30. }  
    10.另外
    由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起,比如在排序上,这里默认用的是小于号,即less<>,如果要从大到小排序呢,这里涉及到的东西很多,在此无法一一加以说明。
    还要说明的是,map中由于它内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,如果用map函数可以实现的功能,而STL  Algorithm也可以完成该功能,建议用map自带函数,效率高一些。
    下面说下,map在空间上的特性,否则,估计你用起来会有时候表现的比较郁闷,由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节的,一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子),我想大家应该知道,这些地方很费内存了。
     

     

     

    展开全文
  • map容器find用法

    2020-12-22 19:56:30
    map容器是STL中比较强大的一个container,下面的代码主要讲的是map容器中find函数的用法,// map::find#include #include int main (){std::map mymap;std::map::iterator it;mymap['a']=50;mymap['b']=100;mymap['c...

    map容器是STL中比较强大的一个container,下面的代码主要讲的是map容器中find函数的用法,

    // map::find

    #include

    #include

    int main ()

    {

    std::map mymap;

    std::map::iterator it;

    mymap['a']=50;

    mymap['b']=100;

    mymap['c']=150;

    mymap['d']=200;

    it=mymap.find('b');

    mymap.erase (it);

    mymap.erase (mymap.find('d'));

    // print content:

    std::cout << "elements in mymap:" << '\n';

    std::cout << "a => " << mymap.find('a')->second << '\n';

    std::cout << "c => " << mymap.find('c')->second << '\n';

    return 0;

    }

    Output:

    elements in mymap:

    a => 50

    c => 150

    下面部分是我自己写的代码:

    // test_map.cpp : 定义控制台应用程序的入口点。

    //

    #include "stdafx.h"

    #include

    #include

    int _tmain(int argc, _TCHAR* argv[])

    {

    std::map myMap;

    typedef std::map::iterator mapIter;

    myMap['a'] = 20;

    myMap['b'] = 30;

    myMap['c'] = 60;

    myMap['d'] = 70;

    myMap.find('a')->second = 120;

    myMap.find('b')->second = 130;

    myMap.find('c')->second = 160;

    myMap.find('d')->second = 170;

    mapIter it;

    it = myMap.find('a');

    std::cout<second<<:endl>

    it = myMap.find('b');

    std::cout<second<<:endl>

    it = myMap.find('c');

    std::cout<second<<:endl>

    it = myMap.find('d');

    std::cout<second<<:endl>

    return 0;

    }

    展开全文
  • C++ STL 标准库中提供有 4 种无序关联式容器,本节先讲解unordered_map 容器。unordered_map 容器,直译过来就是"无序 map 容器"的意思。所谓“无序”,指的是 unordered_map 容器不会像 map 容器那样对存储的数据...

    C++ STL 标准库中提供有 4 种无序关联式容器,本节先讲解unordered_map 容器。

    unordered_map 容器,直译过来就是"无序 map 容器"的意思。所谓“无序”,指的是 unordered_map 容器不会像 map 容器那样对存储的数据进行排序。换句话说,unordered_map 容器和 map 容器仅有一点不同,即 map 容器中存储的数据是有序的,而 unordered_map 容器中是无序的。

    对于已经学过 map 容器的读者,可以将 unordered_map 容器等价为无序的 map 容器。

    具体来讲,unordered_map 容器和 map 容器一样,以键值对(pair类型)的形式存储数据,存储的各个键值对的键互不相同且不允许被修改。但由于 unordered_map 容器底层采用的是哈希表存储结构,该结构本身不具有对数据的排序功能,所以此容器内部不会自行对存储的键值对进行排序。

    值得一提的是,unordered_map 容器在头文件中,并位于 std 命名空间中。因此,如果想使用该容器,代码中应包含如下语句:

    #include

    using namespace std;

    注意,第二行代码不是必需的,但如果不用,则后续程序中在使用此容器时,需手动注明 std 命名空间(强烈建议初学者使用)。

    unordered_map 容器模板的定义如下所示:

    template < class Key, //键值对中键的类型

    class T, //键值对中值的类型

    class Hash = hash, //容器内部存储键值对所用的哈希函数

    class Pred = equal_to, //判断各个键值对键相同的规则

    class Alloc = allocator< pair > // 指定分配器对象的类型

    > class unordered_map;

    以上 5 个参数中,必须显式给前 2 个参数传值,并且除特殊情况外,最多只需要使用前 4 个参数,各自的含义和功能如表 1 所示。

    表 1 unordered_map 容器模板类的常用参数

    参数

    含义

    前 2 个参数分别用于确定键值对中键和值的类型,也就是存储键值对的类型。

    Hash = hash

    用于指明容器在存储各个键值对时要使用的哈希函数,默认使用 STL 标准库提供的 hash 哈希函数。注意,默认哈希函数只适用于基本数据类型(包括 string 类型),而不适用于自定义的结构体或者类。

    Pred = equal_to

    要知道,unordered_map 容器中存储的各个键值对的键是不能相等的,而判断是否相等的规则,就由此参数指定。默认情况下,使用 STL 标准库中提供的 equal_to 规则,该规则仅支持可直接用 == 运算符做比较的数据类型。

    总的来说,当无序容器中存储键值对的键为自定义类型时,默认的哈希函数 hash以及比较函数 equal_to将不再适用,只能自己设计适用该类型的哈希函数和比较函数,并显式传递给 Hash 参数和 Pred 参数。至于如何实现自定义,后续章节会做详细讲解。

    创建C++ unordered_map容器的方法

    常见的创建 unordered_map 容器的方法有以下几种。

    1) 通过调用 unordered_map 模板类的默认构造函数,可以创建空的 unordered_map 容器。比如:

    std::unordered_map<:string std::string> umap;

    由此,就创建好了一个可存储 类型键值对的 unordered_map 容器。

    2) 当然,在创建 unordered_map 容器的同时,可以完成初始化操作。比如:

    std::unordered_map<:string std::string> umap{

    {"Python教程","http://c.biancheng.net/python/"},

    {"Java教程","http://c.biancheng.net/java/"},

    {"Linux教程","http://c.biancheng.net/linux/"} };

    通过此方法创建的 umap 容器中,就包含有 3 个键值对元素。

    3) 另外,还可以调用 unordered_map 模板中提供的复制(拷贝)构造函数,将现有 unordered_map 容器中存储的键值对,复制给新建 unordered_map 容器。

    例如,在第二种方式创建好 umap 容器的基础上,再创建并初始化一个 umap2 容器:

    std::unordered_map<:string std::string> umap2(umap);

    由此,umap2 容器中就包含有 umap 容器中所有的键值对。

    除此之外,C++ 11 标准中还向 unordered_map 模板类增加了移动构造函数,即以右值引用的方式将临时 unordered_map 容器中存储的所有键值对,全部复制给新建容器。例如:

    //返回临时 unordered_map 容器的函数

    std::unordered_map <:string std::string> retUmap(){

    std::unordered_map<:string std::string>tempUmap{

    {"Python教程","http://c.biancheng.net/python/"},

    {"Java教程","http://c.biancheng.net/java/"},

    {"Linux教程","http://c.biancheng.net/linux/"} };

    return tempUmap;

    }

    //调用移动构造函数,创建 umap2 容器

    std::unordered_map<:string std::string> umap2(retUmap());

    注意,无论是调用复制构造函数还是拷贝构造函数,必须保证 2 个容器的类型完全相同。

    4) 当然,如果不想全部拷贝,可以使用 unordered_map 类模板提供的迭代器,在现有 unordered_map 容器中选择部分区域内的键值对,为新建 unordered_map 容器初始化。例如:

    //传入 2 个迭代器,

    std::unordered_map<:string std::string> umap2(++umap.begin(),umap.end());

    通过此方式创建的 umap2 容器,其内部就包含 umap 容器中除第 1 个键值对外的所有其它键值对。

    C++ unordered_map容器的成员方法

    unordered_map 既可以看做是关联式容器,更属于自成一脉的无序容器。因此在该容器模板类中,既包含一些在学习关联式容器时常见的成员方法,还有一些属于无序容器特有的成员方法。

    表 2 列出了 unordered_map 类模板提供的所有常用的成员方法以及各自的功能。

    表 2 unordered_map类模板成员方法

    成员方法

    功能

    begin()

    返回指向容器中第一个键值对的正向迭代器。

    end()

    返回指向容器中最后一个键值对之后位置的正向迭代器。

    cbegin()

    和 begin() 功能相同,只不过在其基础上增加了 const 属性,即该方法返回的迭代器不能用于修改容器内存储的键值对。

    cend()

    和 end() 功能相同,只不过在其基础上,增加了 const 属性,即该方法返回的迭代器不能用于修改容器内存储的键值对。

    empty()

    若容器为空,则返回 true;否则 false。

    size()

    返回当前容器中存有键值对的个数。

    max_size()

    返回容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同。

    operator[key]

    该模板类中重载了 [] 运算符,其功能是可以向访问数组中元素那样,只要给定某个键值对的键 key,就可以获取该键对应的值。注意,如果当前容器中没有以 key 为键的键值对,则其会使用该键向当前容器中插入一个新键值对。

    at(key)

    返回容器中存储的键 key 对应的值,如果 key 不存在,则会抛出 out_of_range 异常。

    find(key)

    查找以 key 为键的键值对,如果找到,则返回一个指向该键值对的正向迭代器;反之,则返回一个指向容器中最后一个键值对之后位置的迭代器(如果 end() 方法返回的迭代器)。

    count(key)

    在容器中查找以 key 键的键值对的个数。

    equal_range(key)

    返回一个 pair 对象,其包含 2 个迭代器,用于表明当前容器中键为 key 的键值对所在的范围。

    emplace()

    向容器中添加新键值对,效率比 insert() 方法高。

    emplace_hint()

    向容器中添加新键值对,效率比 insert() 方法高。

    insert()

    向容器中添加新键值对。

    erase()

    删除指定键值对。

    clear()

    清空容器,即删除容器中存储的所有键值对。

    swap()

    交换 2 个 unordered_map 容器存储的键值对,前提是必须保证这 2 个容器的类型完全相等。

    bucket_count()

    返回当前容器底层存储键值对时,使用桶(一个线性链表代表一个桶)的数量。

    max_bucket_count()

    返回当前系统中,unordered_map 容器底层最多可以使用多少桶。

    bucket_size(n)

    返回第 n 个桶中存储键值对的数量。

    bucket(key)

    返回以 key 为键的键值对所在桶的编号。

    load_factor()

    返回 unordered_map 容器中当前的负载因子。负载因子,指的是的当前容器中存储键值对的数量(size())和使用桶数(bucket_count())的比值,即 load_factor() = size() / bucket_count()。

    max_load_factor()

    返回或者设置当前 unordered_map 容器的负载因子。

    rehash(n)

    将当前容器底层使用桶的数量设置为 n。

    reserve()

    将存储桶的数量(也就是 bucket_count() 方法的返回值)设置为至少容纳count个元(不超过最大负载因子)所需的数量,并重新整理容器。

    hash_function()

    返回当前容器使用的哈希函数对象。

    注意,对于实现互换 2 个相同类型 unordered_map 容器的键值对,除了可以调用该容器模板类中提供的 swap() 成员方法外,STL 标准库还提供了同名的 swap() 非成员函数。

    下面的样例演示了表 2 中部分成员方法的用法:

    #include

    #include

    #include

    using namespace std;

    int main()

    {

    //创建空 umap 容器

    unordered_map umap;

    //向 umap 容器添加新键值对

    umap.emplace("Python教程", "http://c.biancheng.net/python/");

    umap.emplace("Java教程", "http://c.biancheng.net/java/");

    umap.emplace("Linux教程", "http://c.biancheng.net/linux/");

    //输出 umap 存储键值对的数量

    cout << "umap size = " << umap.size() << endl;

    //使用迭代器输出 umap 容器存储的所有键值对

    for (auto iter = umap.begin(); iter != umap.end(); ++iter) {

    cout << iter->first << " " << iter->second << endl;

    }

    return 0;

    }

    程序执行结果为:

    umap size = 3

    Python教程 http://c.biancheng.net/python/

    Linux教程 http://c.biancheng.net/linux/

    Java教程 http://c.biancheng.net/java/

    有关表 2 中其它成员方法的用法,后续章节会做详细讲解。当然,读者也可以自行查询 C++ STL标准库手册。

    展开全文
  • STL — map容器用法的详解

    千次阅读 2017-11-06 15:30:54
    详解map容器使用 map是STL的一个关联容器,它提供一对一 的数据处理能力. 也就是内部存储的有两个部分,一个是固定的键值(从开始插入后就不 会再改变的值)也可以称为关键字另外一...

    详解map容器的使用




    map是STL的一个关联容器,它提供一对一 的数据处理能力. 也就是内部存储的有两个部分,一个是固定的键值(从开始插入后就不

    会再改变的值)也可以称为关键字另外一个是记录该关键字的状态(大小,翻译,对应关系).所以map的作用很广泛,生活中一一对

    的东西太多了,比如你的身份证号和你,比如你需要记录很多不同东西的数量,还有很多很多. 而且map还是有序的.应用场景相

    广泛. 但是map也是有不能存储的数据 只要该数据不能够互相比较大小那么就不能使用map存储. 那么为什么呢?

    这里是由于map容器底层是使用搜索树来存储数据的,所以你在构建搜索树的时候需要不停的比较大小,这就是原因.而这里使用的搜

    索树是较为成熟的红黑树,正因为底层是红黑色所以 map的查找,删 除,插入的 效率都很高. 那么如果你还是不了解为什么,那么你

    就需要了解 红黑树的知识了,我有一篇博客专门介绍红黑树原理和实现如果不是很清楚 希望这个可以帮助到你.

    我们可以通过map的迭代器改变map的元素内容吗? 如果想要修正元素的键值,答案是不行的,因为Map元素的键值关系到map元素的排

    列顺序.任意改变map元素键值将会严重破坏map组织.但如果想要修正元素的实值,答案是可以,因为map元素的实值并不影响map元素的

    排列规则,因此,map iterator既不是一种consttant iterator,也不是一种mutable iterato

    map拥有与list相同的某些性质: 当客户端对它进行元素新增操作或删除操作时,操作之前的所有迭代器,在操作完成之后都依然有效,当然

    那个被删除元素迭代器必然是个例外.



    map的成员函数

    at
    查找具有指定键值的元素。
    begin 返回一个迭代器,此迭代器指向映射中的第一个元素。
    cbegin 返回一个常量迭代器,此迭代器指向映射中的第一个元素。
    cend 返回一个超过末尾常量迭代器。
    clear 清除映射的所有元素。
    count 返回映射中其键与参数中指定的键匹配的元素数量。
    crbegin 返回一个常量迭代器,此迭代器指向反向映射中的第一个元素。
    crend 返回一个常量迭代器,此迭代器指向反向映射中最后一个元素之后的位置。
    emplace 将就地构造的元素插入到映射。
    emplace_hint 将就地构造的元素插入到映射,附带位置提示。
    empty 如果映射为空,则返回 true。
    end 返回超过末尾迭代器。
    equal_range 返回一对迭代器。 此迭代器对中的第一个迭代器指向 map 中其键大于指定键的第一个元素。 此迭代器对中的第二个迭代器指向 map 中其键等于或大于指定键的第一个元素。
    erase 从指定位置移除映射中的元素或元素范围。
    find 返回一个迭代器,此迭代器指向映射中其键与指定键相等的元素的位置。
    get_allocator 返回用于构造映射的 allocator 对象的副本。
    insert 将元素或元素范围插入到映射中的指定位置。
    key_comp 返回用于对映射中的键进行排序的比较对象副本。
    lower_bound 返回一个迭代器,此迭代器指向映射中其键值等于或大于指定键的键值的第一个元素。
    max_size 返回映射的最大长度。
    rbegin 返回一个迭代器,此迭代器指向反向映射中的第一个元素。
    rend 返回一个迭代器,此迭代器指向反向映射中最后一个元素之后的位置。
    size 返回映射中的元素数量。
    swap 交换两个映射的元素。
    upper_bound 返回一个迭代器,此迭代器指向映射中其键值大于指定键的键值的第一个元素。
    value_comp 检索用于对映射中的元素值进行排序的比较对象副本。
    shrink_to_fit 放弃额外容量。
    size 返回vector元素个数
    swap 交换两个向量的元素。


    访问操作



    这里我们需要熟练运用的函数为:at,begin,end,count,find. 


    map<int, int> T;
    
    	T[0] = 1;
    	T[1] = 2;
    	T[2] = 3;
    	T[3] = 4;
    	//operator[]返回指定下标的引用.
    
    	cout << "map容器中关键值为2的val为:";
    	cout << T.at(2) << endl;
    	//at函数查找输入键值对应的元素. 
    
    	cout << "从头遍历该map元素" << endl;
    	map<int, int>::iterator it = T.begin();
    	//返回map中第一个元素位置的迭代器
    
    	while (it != T.end())
    	//返回map中最后一个元素下一个位置的迭代器
    	{
    		cout << it->first << "  ->>>  " << it->second << endl;
    		++it;
    		//让迭代器跳转到下一个元素的位置.
    	}
    
    	cout << "find一个元素的迭代器并且访问它:";
    	cout << T.find(3)->first << "  ->>>  " << T.find(3)->second << endl;

    运行结果:



    插入操作



    插入的操作我们我们不是直接就把两个值传给他,我们需要先把两个放进pair里面,比如最基本的插入insert(pair<K,V>(key,val));

    这里每次插入的时候都要给pair传入模板类型有点繁琐,所以我想着在这里封装一个函数让模板参数可以自动识别,所以写一个函数为

    template<typename K, typename V>
    pair<K, V> mymake_pair(const K& key,const V& val)
    {
    	return pair<K, V>(key, val);
    }

    其实编译器有一个这个函数,但是我们也需要明白函数的底层构造以及为什么需要这个函数,接下来我们看几种不同的重载的插入:

    	map<int, int> T;
    
    	//***1*** 最正常的插入
    	T.insert(pair<int, int>(1, 1));
    	T.insert(pair<int, int>(2, 2));
    	T.insert(pair<int, int>(3, 3));
    	//这是最基本的插入操作,这里没有前插后插的,因为搜索树会负责给你安排位置
    	//这里不需要你操心.
    
    	T.insert(mymake_pair(4, 4));
    	T.insert(mymake_pair(5, 5));
    	T.insert(mymake_pair(6, 6));
    
    	map<int, int>::iterator it1 = T.begin();
    
    	cout << "遍历T中的元素:" << endl;
    	while (it1 != T.end())
    	{
    		cout << it1->second << " ";
    		cout << "的val为" << " ";
    		cout << it1->first << endl;
    		++it1;
    	}
    	cout << endl;
    
    	//***2** 利用迭代器进行区间插入
    
    	std::map<int, int> anothermap;
    	anothermap.insert(T.begin(), T.find(4));
    	//
    
    	map<int, int>::iterator it2 = anothermap.begin();
    
    	cout << "遍历anothermap中的元素:" << endl;
    	while (it2 != anothermap.end())
    	{
    		cout << it2->second << " ";
    		cout << "的val为 " << " ";
    		cout << it2->first << endl;
    		++it2;
    	}

    运行结果:





    删除操作




    其实当你明白插入操作之后,我觉得删除操作,以及删除操作里面的删除迭代器区间的操作你会很容易就Get到. 我这里就直接撸代码了!

    	map<int, int> T;
    
    	T.insert(mymake_pair(1, 1));
    	T.insert(mymake_pair(2, 2));
    	T.insert(mymake_pair(3, 3));
    	T.insert(mymake_pair(4, 4));
    	T.insert(mymake_pair(5, 5));
    	T.insert(mymake_pair(6, 6));
    
    	map<int, int>::iterator it1 = T.begin();
    
    	cout << "遍历T中的元素:" << endl;
    	while (it1 != T.end())
    	{
    		cout << it1->second << " ";
    		cout << "的val为" << " ";
    		cout << it1->first << endl;
    		++it1;
    	}
    	cout << endl;
    
    	//***2*** 删除单个迭代器
    
    	map<int, int>::iterator it3 = T.find(2);
    	//通过find拿到关键字为2的迭代器
    
    	T.erase(it3);
    	//然后删除该元素.
    
    	it1 = T.begin();
    
    	cout << "遍历T中的元素:" << endl;
    	while (it1 != T.end())
    	{
    		cout << it1->second << " ";
    		cout << "的val为" << " ";
    		cout << it1->first << endl;
    		++it1;
    	}
    	cout << endl;
    
    
    	//***2*** 删除迭代器区间
    
    	it3 = T.find(3);
    	//通过find拿到关键字为3的迭代器
    
    	T.erase(it3, T.end());
    	//删除掉it3到map容器结束的所有节点.
    
    	it1 = T.begin();
    
    	cout << "遍历T中的元素:" << endl;
    	while (it1 != T.end())
    	{
    		cout << it1->second << " ";
    		cout << "的val为" << " ";
    		cout << it1->first << endl;
    		++it1;
    	}
    	cout << endl;
    
    
    	//***3*** 终极大招 删除所有元素.
    
    	T.insert(mymake_pair(1, 1));
    	T.insert(mymake_pair(2, 2));
    	T.insert(mymake_pair(3, 3));
    	T.insert(mymake_pair(4, 4));
    	T.insert(mymake_pair(5, 5));
    	T.insert(mymake_pair(6, 6));
    
    	T.clear();
    	//删除所有元素.
    
    	it1 = T.begin();
    
    	cout << "遍历T中的元素:" << endl;
    	while (it1 != T.end())
    	{
    		cout << it1->second << " ";
    		cout << "的val为" << " ";
    		cout << it1->first << endl;
    		++it1;
    	}
    	cout << endl;

    运行结果:




    其他操作


    这里map也有和vector和list相似的其他功能,比如size,empty,swap...... 相信大家会用vector,list的功能就会使用map的这些功能.

    如果不会使用也没关系! 详细vector的用法 以及 详细的list的用法 这两个博客我写了好久,功能也挺全的,不懂的可以顺便过去

    瞧一瞧~   map其实挺好用的,最重要的是尝试自己实现一个Map,这样你的红黑树的理解,你的设计结构能力会有很高的进步.等我实

    现ok,会再写一个博客的.



    展开全文
  • C++ map容器用法

    万次阅读 2018-09-22 20:09:01
    C++ map容器用法   介绍 Map是键-值对的集合,map中的所有元素都是pair,可以使用键作为下标来获取一个值。Map中所有元素都会根据元素的值自动被排序,同时拥有实值value和键值key,pair的第一元素被视为键值,...
  • map 容器的说明和使用技巧

    千次阅读 多人点赞 2018-07-27 16:17:02
    Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在...
  • Map容器使用

    千次阅读 2016-09-17 10:49:00
    这里主要介绍map容器使用,map通过键值对key-value的形式集合。 根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。 快速插入Key -Value 记录...
  • map容器的insert用法总结

    万次阅读 2018-01-25 20:02:07
    如果试图插入的元素所对应的键已经在容器中,则insert 将不做任何操作。 通常来说,下标操作符返回左值。它返回的左值是特定键所关联的值。 有别于vector或string类型,map下标操作符返回的类型与对map迭代器...
  • 标准C++中map容器用法总结

    万次阅读 2013-08-06 17:12:29
    (3)Traits:它是一个能提供比较两个元素的关键字来决定它们在map容器中的相对位置。它是可选的,它的默认值是 less (4)Allocator:它代表存储管理设备。它是可选的,它的默认值为allocator, Type> > map ...
  • 这篇结束学习map容器的API,通过学习map容器的排序,引出一个新的知识点:仿函数,然后继续学习仿函数相关的知识点。 1.map容器默认排序 我们知道map容器是该容器本身提供的sort()排序算法,不是直接调用全局...
  • c++中map容器使用

    千次阅读 2018-03-02 13:21:02
    C++中map容器提供一个键值对容器,map与multimap差别仅仅在于multiple允许一个键对应多个值。 一、map的说明 1头文件 #include<map> 2定义 map<string,int>my_Map; 或者是typedefmap<string,int>...
  • map容器讲解

    2012-01-05 16:35:28
    Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程...
  • ts Map容器使用

    千次阅读 2020-04-01 16:10:48
    interface Map<K, V> { //清空 clear(): void; //删除:通过key来删除value delete(key: K): boolean; //遍历 forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): ...
  • 主要介绍了C++中的哈希容器unordered_map使用示例,本文直接给出实例代码,并讲解了一些hash table的知识,需要的朋友可以参考下
  • 关联容器与序列容器有着根本性的...两个主要的关联容器类型是map与set。 1.1简介:set里面每个元素只存有一个key,它支持高效的关键字查询操作。set对应数学中的“集合”。 1.2特点: 储存同一类型的数据元素(这点和
  • matlab map容器类型

    千次阅读 2021-01-18 17:16:25
    matlab map容器类型 map容器类型以及map类概述 map是将一个量映射到另一个量上,此是前面的量就是map的键(key),后面的量就是map的数据(value)。map的键和对应的数据都储存在map中。一个map条目包括唯一的键和...
  • C++ map容器和multimap容器(STL map容器

    万次阅读 多人点赞 2018-11-08 22:30:05
    2.2 map容器的一般常用属性(方法) 2.3 插入数据 2.4 数据的访问和遍历 2.5 数据的删除 2.6 map中关键词的排序 3. multimap容器 3.1 访问元素 3.2 删除元素 1. 关联容器和map容器概述 map容器是关联容器的...
  • 主要介绍了c++容器list、vector、map、set区别与用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • C++STL之map容器

    万次阅读 多人点赞 2018-08-08 21:12:08
    map容器的数据结构也采用红黑树来实现的,插入元素的键值不允许重复,比较函数只对元素的键值进行 比较,元素的各项数据可通过键值检索出来。由于map与set采用的都是红黑树的结构,所以,用法基本相似。  ...
  • std map容器用法总结

    2011-03-19 16:01:19
    c++中标准STL容器MAP用法总结,对C++学习者有用.
  • map容器用法总结

    2019-08-11 20:07:19
    一、骚操作 1、map容器实现对元素进行计数。...使用方法:定义一个双类型的map容器map<string,ll> mp;,第一个用来存元素,第二个用来计数。 使用示例见https://mp.csdn.net/postedit/99222398 ...
  • C++ STL之map容器用法详解 map 容器是关联容器的一种。在关联容器中,对象的位置取决于和它关联的键的值。键可以是基本类型,也可以是类类型。字符串经常被用来作为键,如果想要保存姓名和地址的记录,就可以这么...
  • 可以修改一个特定的节点而不对其他节点不产生影响,由于map是一种关联式容器,Key--value结构我们必须明确,在map中我们可以根据key的值修改其对应的value的值,而不能修改key的值,其最大的特点是key和value的值...
  • map容器插入数据的4种方法

    万次阅读 2017-08-02 18:56:50
    在构造map容器后,我们就可以往里面插入数据了。这里讲四种插入数据的方法: 第一种:用insert函数插入pair数据:在VC下请加入这条语句,屏蔽4786警告 #pragma warning (disable:4786) )  mapint, ...
  • C++ 中 map 容器的内存...通常在使用 map 的时候直接通过 erase,或者 clean 方法就可以删除数据,如果结合智能指针,用户不用关心内存的问题。但是需要注意的是,调用 erase 或者 clean 方法后,内存并没有立马释放,
  • 使用 list、set 或 map遍历删除某些元素时可以这样使用,如下所示
  • C++ STL 中 map 容器的说明和使用技巧

    万次阅读 多人点赞 2014-07-22 10:04:02
    Map是c++的一个标准容器,她提供了很好一对一的关系,在一些程序中建立一个map可以起到事半功倍的效果,总结了一些map基本简单实用的操作!   1、map简介 map是一类关联式容器。它的特点是增加和删除节点...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 257,324
精华内容 102,929
关键字:

map容器的详细用法