• STL容器之map


    【1】map容器

    map 是关联容器。容器中的每一个元素都是由一个键值和一个数据值组成的。

    set 是一个集合它以其元素作为键值(同一个键值只能出现一次),且默认以升序排列。

    list 是一个顺序容器。

    【2】map容器使用方法以及实例

    (1)定义、插入数据方法实例

     1 // map容器定义、插入数据方式代码
     2 #include<map>
     3 #include<string>
     4 #include<iostream>
     5 using namespace std;
     6 
     7 // 打印map容器数据
     8 void print(map<int, string>& mapStu, int nValue)
     9 {
    10     cout << "mapStu" << nValue << "数据信息:" << endl;
    11     cout << "size: " << mapStu.size() << endl;
    12     map<int, string>::iterator iter = mapStu.begin();
    13     for (; iter != mapStu.end(); ++iter)
    14     {
    15         cout << "key: " << iter->first << " value: " << iter->second << endl;
    16     }
    17     cout << endl;
    18 }
    19 
    20 void main()
    21 {
    22     // 第一种定义map的方法
    23     map<int, string> mapStu1;
    24     // 第二种定义map的方法
    25     typedef map<int, string> mapType;
    26     mapType mapStu2, mapStu3, mapStu4;
    27 
    28     // 第一种插入数据方法:用insert函数插入value_type数据
    29     mapStu1.insert(map<int, string>::value_type(1, "Qin"));
    30     mapStu1.insert(map<int, string>::value_type(2, "Sun"));
    31     mapStu1.insert(map<int, string>::value_type(3, "Wang"));
    32     mapStu1.insert(map<int, string>::value_type(2, "Zhao"));
    33     print(mapStu1, 1);
    34     // 第二种插入数据方法:用insert函数插入pair数据
    35     mapStu2.insert(pair<int, string>(1, "Qin"));
    36     mapStu2.insert(pair<int, string>(2, "Sun"));
    37     mapStu2.insert(pair<int, string>(3, "Wang"));
    38     mapStu2.insert(pair<int, string>(2, "Zhao"));
    39     print(mapStu2, 2);
    40     // 第三种插入数据方法:用insert函数插入make_pair数据
    41     mapStu3.insert(make_pair<int, string>(1, "Qin"));
    42     mapStu3.insert(make_pair<int, string>(2, "Sun"));
    43     mapStu3.insert(make_pair<int, string>(3, "Wang"));
    44     mapStu3.insert(make_pair<int, string>(2, "Zhao"));
    45     print(mapStu3, 3);
    46     // 第四种插入数据方法:数组插入法
    47     mapStu4[1] = "Qin";
    48     mapStu4[2] = "Sun";
    49     mapStu4[3] = "Wang";
    50     mapStu4[2] = "Zhao";
    51     print(mapStu4, 4);
    52 
    53     pair<map<int, string>::iterator, bool> iter_pair;
    54     iter_pair = mapStu1.insert(map<int, string>::value_type(3, "Li"));
    55     cout << "插入成功与否:" << iter_pair.second << endl;
    56 
    57     system("pause");
    58 }
    59 
    60 // run out
    61 /*
    62 mapStu1数据信息:
    63 size: 3
    64 key: 1 value: Qin
    65 key: 2 value: Sun
    66 key: 3 value: Wang
    67 
    68 mapStu2数据信息:
    69 size: 3
    70 key: 1 value: Qin
    71 key: 2 value: Sun
    72 key: 3 value: Wang
    73 
    74 mapStu3数据信息:
    75 size: 3
    76 key: 1 value: Qin
    77 key: 2 value: Sun
    78 key: 3 value: Wang
    79 
    80 mapStu4数据信息:
    81 size: 3
    82 key: 1 value: Qin
    83 key: 2 value: Zhao
    84 key: 3 value: Wang
    85 
    86 插入成功与否:0
    87 请按任意键继续. . .
    88 */

    分析总结:

    以上四种用法,虽然都可以实现数据的插入,但是它们是有区别的。

    当然,第一、二、三种在效果上是完全一样的,用insert函数插入数据,在数据的插入过程中涉及到集合的唯一性这个概念:

    即当map中有这个关键字时,insert操作再插入数据是不会成功的。

    但是,用数组(第四种)方式就不同了,它可以覆盖以前该关键字对应的值,用程序说明如下:

    mapStu1.insert(map<int, string>::value_type(2, "Sun"));

    mapStu1.insert(map<int, string>::value_type(2, "Zhao"));

    上面这两条语句执行后,mapStu1中2这个关键字对应的值是“Sun”,第二条语句并没有生效。

    那么,这就涉及到我们怎么知道insert语句是否插入成功的问题?可以用pair来获得是否插入成功,程序如下:

    pair<map<int, string>::iterator, bool> iter_pair;

    iter_pair = mapStu1.insert(map<int, string>::value_type(3, "Li"));

    我们通过pair的第二个变量来判断是否插入成功,它的第一个变量返回的是一个map的迭代器,

    如果插入成功的话迭代器的变量iter_pair.second应该是true,否则为false。

    (2)遍历map容器的三种方式

    程序代码如下:

     1 #include <map>
     2 #include <iostream>
     3 #include <string>
     4 using namespace std;
     5 
     6 // 第一种方式
     7 void print1(map<int, string>& mapStu)
     8 {
     9     cout << "第一种遍历方式:" << endl;
    10     cout << "size: " << mapStu.size() << endl;
    11     // 迭代map容器中的数据
    12     map<int, string>::iterator iter = mapStu.begin();
    13     for (; iter != mapStu.end(); ++iter)
    14     {
    15         cout << "key: " << iter->first << " value: " << iter->second << endl;
    16     }
    17     cout << endl;
    18 }
    19 
    20 // 第二种方式
    21 void print2(map<int, string>& mapStu)
    22 {
    23     cout << "第二种遍历方式:" << endl;
    24     cout << "size: " << mapStu.size() << endl;
    25     // 迭代map容器中的数据
    26     map<int, string>::reverse_iterator iter = mapStu.rbegin();
    27     for (; iter != mapStu.rend(); ++iter)
    28     {
    29         cout << "key: " << iter->first << " value: " << iter->second << endl;
    30     }
    31 
    32     cout << endl;
    33 }
    34 
    35 // 第三种方式
    36 void print3(map<int, string>& mapStu)
    37 {
    38     cout << "第三种遍历方式:" << endl;
    39     int nSize = mapStu.size();
    40     cout << "size: " << mapStu.size() << endl;
    41     // 迭代map容器中的数据
    42     for(int nIndex = 1; nIndex < nSize + 1; ++nIndex)
    43     {
    44         cout << "<" << nIndex << " :: " << mapStu[nIndex] << ">" << endl;
    45     }
    46 }
    47 
    48 void main()
    49 {
    50     typedef map<int, string> mapType;
    51     mapType mapStu;
    52 
    53     // 用insert函数插入value_type数据
    54     mapStu.insert(map<int, string>::value_type(1, "Qin"));
    55     mapStu.insert(map<int, string>::value_type(2, "Sun"));
    56     mapStu.insert(map<int, string>::value_type(3, "Wang"));
    57     mapStu.insert(map<int, string>::value_type(4, "Zhao"));
    58     print1(mapStu);  // 第一种方式
    59     print2(mapStu);  // 第二种方式
    60     print3(mapStu);  // 第三种方式
    61 
    62     system("pause");
    63 }
    64 // run out:
    65 /*
    66 第一种遍历方式:
    67 size: 4
    68 key: 1 value: Qin
    69 key: 2 value: Sun
    70 key: 3 value: Wang
    71 key: 4 value: Zhao
    72 
    73 第二种遍历方式:
    74 size: 4
    75 key: 4 value: Zhao
    76 key: 3 value: Wang
    77 key: 2 value: Sun
    78 key: 1 value: Qin
    79 
    80 第三种遍历方式:
    81 size: 4
    82 <1 :: Qin>
    83 <2 :: Sun>
    84 <3 :: Wang>
    85 <4 :: Zhao>
    86 请按任意键继续. . .
    87 */

    (3)查找数据的三种方式

    应用实例代码如下:

      1 // 三种查找数据的方式
      2 #include <map>
      3 #include <iostream>
      4 #include <string>
      5 using namespace std;
      6 
      7 // 第一种方式
      8 void print1(map<int, string>& mapStu)
      9 {
     10     cout << "遍历容器数据:" << endl;
     11     cout << "size: " << mapStu.size() << endl;
     12     // 迭代map容器中的数据
     13     map<int, string>::iterator iter = mapStu.begin();
     14     for (; iter != mapStu.end(); ++iter)
     15     {
     16         cout << "key: " << iter->first << " value: " << iter->second << endl;
     17     }
     18 }
     19 
     20 void main()
     21 {
     22     typedef map<int, string> mapType;
     23     mapType mapStu;
     24 
     25     // 用insert函数插入value_type数据
     26     mapStu.insert(map<int, string>::value_type(1, "Qin"));
     27     mapStu.insert(map<int, string>::value_type(2, "Sun"));
     28     mapStu.insert(map<int, string>::value_type(3, "Wang"));
     29     mapStu.insert(map<int, string>::value_type(4, "Zhao"));
     30     // 第一种查找数据方式
     31     // count函数求的是关键字key的个数?key是不能重复的,所以返回只有0和1两种结果。
     32     cout << "查找关键字3的结果 : " << mapStu.count(1) << endl;
     33     cout << "查找关键字5的结果:  " << mapStu.count(5) << endl;
     34     // 第二种查找数据方式
     35     map<int, string>::iterator iter;
     36     iter = mapStu.find(1);
     37     if (iter != mapStu.end())
     38     {
     39         cout << "Find, the value is " << iter->second << endl;
     40     }
     41     else
     42     {
     43          cout << "Do not Find !" << endl;
     44     }
     45     // 第三种查找数据方式
     46     print1(mapStu);
     47     iter = mapStu.lower_bound(2);
     48     {
     49         cout << "lower_bound(2) :: (不小于2) " << iter->second << endl;
     50     }
     51 
     52     iter = mapStu.lower_bound(3);
     53     {
     54        cout << "lower_bound(3) :: (不小于3) " << iter->second << endl;
     55     }
     56 
     57     iter = mapStu.upper_bound(2);
     58     {
     59        cout << "upper_bound(2) :: (大于2) " << iter->second << endl;
     60     }
     61 
     62     iter = mapStu.upper_bound(3);
     63     {
     64        cout << "upper_bound(3) :: (大于3) " << iter->second << endl;
     65     }
     66 
     67     pair<map<int, string>::iterator, map<int, string>::iterator> mapPair;
     68     mapPair = mapStu.equal_range(2);
     69     if (mapPair.first == mapPair.second)
     70     {
     71         cout << "equal_range(2) :: Do not Find!" << endl;
     72     }
     73     else
     74     {
     75         cout << "equal_range(2) :: Find!" << endl;
     76     }
     77 
     78     mapPair = mapStu.equal_range(5);
     79     if (mapPair.first == mapPair.second)
     80     {
     81        cout << "equal_range(5) :: Do not Find!" << endl;
     82     }
     83     else
     84     {
     85         cout << "equal_range(5) :: Find!" << endl;
     86     }
     87 
     88     system("pause");
     89 }
     90 // run out:
     91 /*
     92 查找关键字3的结果 : 1
     93 查找关键字5的结果:  0
     94 Find, the value is Qin
     95 遍历容器数据:
     96 size: 4
     97 key: 1 value: Qin
     98 key: 2 value: Sun
     99 key: 3 value: Wang
    100 key: 4 value: Zhao
    101 lower_bound(2) :: (不小于2) Sun
    102 lower_bound(3) :: (不小于3) Wang
    103 upper_bound(2) :: (大于2) Wang
    104 upper_bound(3) :: (大于3) Zhao
    105 equal_range(2) :: Find!
    106 equal_range(5) :: Do not Find!
    107 请按任意键继续. . .
    108 */

    注意:

    lower_bound(x)不是下界,而是大于等于x的最小值。

    upper_bound(x) 大于x的最小值。

    (4)查询、修改、删除、大小、比较、清空、判空等等方法。

    应用实例代码如下:

      1 #include <map>
      2 #include <string>
      3 #include <iostream>
      4 using namespace std;
      5 
      6 // 打印map容器数据
      7 void print(map<int, string>& mapStu)
      8 {
      9     cout << "size: " << mapStu.size() << endl;
     10     // 迭代map容器中的数据
     11     map<int, string>::iterator iter = mapStu.begin();
     12     for (; iter != mapStu.end(); ++iter)
     13     {
     14         cout << "key: " << iter->first << " value: " << iter->second << endl;
     15     }
     16     cout << endl;
     17 }
     18 
     19 void main()
     20 {
     21     typedef map<int, string> mapType;
     22     mapType mapStu1;
     23 
     24     // 用insert函数插入value_type数据
     25     mapStu1.insert(map<int, string>::value_type(1, "Qin"));
     26     mapStu1.insert(map<int, string>::value_type(2, "Sun"));
     27     mapStu1.insert(map<int, string>::value_type(3, "Wang"));
     28     mapStu1.insert(map<int, string>::value_type(2, "Zhao"));
     29     print(mapStu1);
     30     // 查找数据的两种方式:
     31     // 方式1:
     32     string str2 = mapStu1[2];
     33     cout << str2 << endl;
     34     // 方式2:
     35     mapType::iterator my_Iter;
     36     my_Iter = mapStu1.find(3);
     37     string str3 = my_Iter->second;
     38     cout << str3 << endl << endl;
     39     // 修改数据的两种方式:
     40     // 方式1:
     41     mapStu1[2] = "Ma";
     42     // 方式2:
     43     my_Iter->second = "Yuan";
     44     print(mapStu1);
     45     // size 函数 和 empty函数
     46     cout << "size() :: " << mapStu1.size() << endl;
     47     cout << "empty() :: " << mapStu1.empty() << endl;
     48     mapStu1.clear();
     49     cout << "size() :: " << mapStu1.size() << endl;
     50     cout << "empty() :: " << mapStu1.empty() << endl;
     51     // 比较 ==、>=、<=、!=
     52     mapType mapStu2;
     53     cout << "mapStu1 == mapStu2 :: " << (mapStu1 == mapStu2) << endl; 
     54     cout << "mapStu1 >= mapStu2 :: " << (mapStu1 >= mapStu2) << endl;
     55     cout << "mapStu1 <= mapStu2 :: " << (mapStu1 <= mapStu2) << endl;
     56     cout << "mapStu1 != mapStu2 :: " << (mapStu1 != mapStu2) << endl << endl;
     57 
     58     mapStu1.insert(map<int, string>::value_type(1, "Qin"));
     59     mapStu1.insert(map<int, string>::value_type(2, "Sun"));
     60     mapStu1.insert(map<int, string>::value_type(3, "Wang"));
     61     mapStu1.insert(map<int, string>::value_type(4, "Qiang"));
     62     mapStu1.insert(map<int, string>::value_type(5, "Huang"));
     63     mapStu1.insert(map<int, string>::value_type(6, "Li"));
     64     mapStu1.insert(map<int, string>::value_type(7, "Hou"));
     65     mapStu1.insert(map<int, string>::value_type(8, "Lin"));
     66     mapStu1.insert(map<int, string>::value_type(9, "Li"));
     67 
     68     // 删除操作
     69     cout << "删除前打印数据信息:" << endl;
     70     print(mapStu1);
     71     mapType::iterator iter;
     72     // 第一种删除(代码1)
     73     for (iter = mapStu1.begin(); iter != mapStu1.end();)
     74     {
     75         if (5 == iter->first) 
     76         {
     77             iter = mapStu1.erase(iter);
     78         }
     79         else
     80         {
     81             ++iter;
     82         }
     83     }
     84 
     85     // 第一种删除(代码2)(注意代码层面的差异)
     86     for (iter = mapStu1.begin(); iter != mapStu1.end();)
     87     {
     88         if ("Li" == iter->second) 
     89         {
     90             mapStu1.erase(iter++);
     91         }
     92         else
     93         {
     94             ++iter;
     95         }
     96     }
     97     cout << "删除关键字5 以及 值“Li”后: " << endl;
     98     print(mapStu1);
     99 
    100     // 第一种删除(代码3)(注意代码层面的差异)
    101     my_Iter = mapStu1.find(2);
    102     mapStu1.erase(my_Iter);
    103     cout << "删除关键字2后: " << endl;
    104     print(mapStu1);
    105 
    106     // 第二种删除(直接删除关键字)
    107     int nResult = mapStu1.erase(3); // 如果删除了会返回1,否则返回0
    108     cout << nResult << endl;
    109     cout << "删除关键字3后: " << endl;
    110     print(mapStu1);
    111 
    112     // 第三种删除(用迭代器,成片的删除)
    113     mapStu1.erase(++mapStu1.begin(), mapStu1.end());
    114     cout << "剩第一位,其它全部删除后: " << endl;
    115     print(mapStu1);
    116 
    117     system("pause");
    118 }
    119 
    120 // run out:
    121 /*
    122 size: 3
    123 key: 1 value: Qin
    124 key: 2 value: Sun
    125 key: 3 value: Wang
    126 
    127 Sun
    128 Wang
    129 
    130 size: 3
    131 key: 1 value: Qin
    132 key: 2 value: Ma
    133 key: 3 value: Yuan
    134 
    135 size() :: 3
    136 empty() :: 0
    137 size() :: 0
    138 empty() :: 1
    139 mapStu1 == mapStu2 :: 1
    140 mapStu1 >= mapStu2 :: 1
    141 mapStu1 <= mapStu2 :: 1
    142 mapStu1 != mapStu2 :: 0
    143 
    144 删除前打印数据信息:
    145 size: 9
    146 key: 1 value: Qin
    147 key: 2 value: Sun
    148 key: 3 value: Wang
    149 key: 4 value: Qiang
    150 key: 5 value: Huang
    151 key: 6 value: Li
    152 key: 7 value: Hou
    153 key: 8 value: Lin
    154 key: 9 value: Li
    155 
    156 删除关键字5 以及 值“Li”后:
    157 size: 6
    158 key: 1 value: Qin
    159 key: 2 value: Sun
    160 key: 3 value: Wang
    161 key: 4 value: Qiang
    162 key: 7 value: Hou
    163 key: 8 value: Lin
    164 
    165 删除关键字2后:
    166 size: 5
    167 key: 1 value: Qin
    168 key: 3 value: Wang
    169 key: 4 value: Qiang
    170 key: 7 value: Hou
    171 key: 8 value: Lin
    172 
    173 1
    174 删除关键字3后:
    175 size: 4
    176 key: 1 value: Qin
    177 key: 4 value: Qiang
    178 key: 7 value: Hou
    179 key: 8 value: Lin
    180 
    181 剩第一位,其它全部删除后:
    182 size: 1
    183 key: 1 value: Qin
    184 
    185 请按任意键继续. . .
    186 */

    (5)map 容器排序问题

    请看下面一段代码:

     1 #include <map>
     2 #include <cstring>
     3 using namespace std;
     4 
     5 typedef struct tagStudentInfo
     6 {
     7     int nID;
     8     string strName;
     9 } StudentInfo, *PStudentInfo;  // 学生信息
    10 
    11 void main()
    12 {
    13     // 用学生信息映射分数
    14     map<StudentInfo, int> mapStudent;
    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 }

    注意:以上程序编译无法通过!

    由编译器错误提示分析:排序问题!STL中默认是采用小于号来排序的,当关键字是一个结构体时,涉及到排序就会出现问题。

    因为它没有小于号操作,insert等函数在编译的时候过不去,下面给出两个方法解决这个问题:

    1、解决方法1,重载运算符。

     1 // 解决方法1
     2 
     3 #include <map>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 typedef struct tagStudentInfo
     8 {
     9     int nID;
    10     string strName;
    11 
    12     bool operator < (tagStudentInfo const & _A)const
    13     {
    14         // 这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序。
    15         if (nID < _A.nID)
    16             return true;
    17         if (nID == _A.nID)
    18             return strName.compare(_A.strName) < 0;
    19 
    20         return false;
    21     }
    22 } StudentInfo, *PStudentInfo;  // 学生信息
    23 
    24 void main()
    25 {
    26     // 用学生信息映射分数
    27     map<StudentInfo, int> mapStudent;
    28     StudentInfo studentInfo;
    29     studentInfo.nID = 1;
    30     studentInfo.strName = "student_one";
    31     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
    32     studentInfo.nID = 2;
    33     studentInfo.strName = "student_two";
    34     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
    35 }

    2、解决方法2,仿函数。

     1 // 解决方法2
     2 
     3 #include <map>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 typedef struct tagStudentInfo
     8 {
     9     int nID;
    10     string strName;
    11 } StudentInfo, *PStudentInfo;  // 学生信息
    12 
    13 class sort
    14 {
    15 public:
    16     bool operator()(StudentInfo const & _A, StudentInfo const & _B) const
    17     {
    18         if (_A.nID < _B.nID)
    19             return true;
    20         if (_A.nID == _B.nID)
    21             return _A.strName.compare(_B.strName) < 0;
    22 
    23         return false;
    24     }
    25 };
    26 
    27 void main()
    28 {
    29     // 用学生信息映射分数
    30     map<StudentInfo, int, sort> mapStudent;
    31     StudentInfo studentInfo;
    32     studentInfo.nID = 1;
    33     studentInfo.strName = "student_one";
    34     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
    35     studentInfo.nID = 2;
    36     studentInfo.strName = "student_two";
    37     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
    38 }

    (6)待续...

    【3】总结说明

    (1)由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起。

    比如,在排序方面,这里默认用的是小于号,即less<>,如果要从大到小排序呢,这里涉及到的东西很多,在此无法一一加以说明。

    (2)map容器内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,用map函数可以实现的功能,而STL Algorithm也可以完成该功能。

    但是,建议用map自带函数,效率更高一些。

    (3)map在空间上的特性。

    由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节:

    一个父节点指针,左右两个孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子)。

     

    Good  Good  Study,  Day  Day  Up.

    顺序  选择  循环  总结

  • 相关阅读:
    30 Day Challenge Day 11 | Leetcode 55. Jump Game
    30 Day Challenge Day 11 | Leetcode 11. Container With Most Water
    30 Day Challenge Day 10 | Leetcode 701. Insert into a Binary Search Tree
    30 Day Challenge Day 10 | Leetcode 1. Two Sum
    30 Day Challenge Day 10 | Leetcode 3. Longest Substring Without Repeating Characters
    30 Day Challenge Day 9 | Leetcode 425. Word Squares
    30 Day Challenge Day 8 | Leetcode 200. Number of Islands
    30 Day Challenge Day 7 | Leetcode 235. Lowest Common Ancestor of a Binary Search Tree
    30 Day Challenge Day 7 | Hackerrank: Tree: Huffman Decoding
    30 Day Challenge Day 6 | Leetcode 92. Reverse Linked List II
  • 原文地址:https://www.cnblogs.com/Braveliu/p/6427050.html
Copyright © 2020-2023  润新知