学科分类
目录
C++基础

map/multimap类模板

与前面所学容器都不相同,map与multimap中存储的是元素对(key-value),映射类型的容器通常也可理解为关联数组,可使用键作为下标来获取对应的值,关联的本质在于元素的值与某个特定的键相关联,而不是通过在数组中的位置来获取。接下来我们就来学习一下映射的对象创建及常用操作方法。

1、创建对象

map与multimap中也重载了不同的构造函数,可用不同的方式创建对象,map对象的创建方式有以下几种:

map<T1, T2> m; //创建一个空的map容器
map<T1,T2, op> m; //创建一个空的map容器,以op为准则排序
map<T1, T2> m(begin, end); //创建一个map容器,用[begin, end)区间值赋值
map<T1, T2> m(begin,end,op);//创建一个map容器,用[begin, end)区间值赋值,op为排序准则
map<T1, T2> m(m1); //创建一个map容器,用另一个map容器m1初始化

map对象的创建方式有以上五种,接下来我们分别用这五种方式创建不同的map对象,代码如下所示:

map<int, int> m1;
map<char, float, greater<int>()> m2;
map<string, int> m3(begin, end);
map<string, int, greater<string>()> m4(begin, end);
map<int, int> m5(m1);

上述代码分别调用不同的构造函数创建了五个map对象,注意,在创建map对象时,类型参数必须有两个。

与map一样,multimap也重载了这五种类型的构造函数,接下来我们再用这五种方式创建multimap的对象,代码如下所示:

multimap<int, int> mt1;
multimap<char, float, greater<int>()> mt2;
multimap<string, int> mt3(begin, end);
multimap<string, int, greater<string>()> mt4(begin, end);
multimap<int, int> mt5(m1);

上述代码分别用五种不同的方式创建了不同的multimap对象,其中参数含义与map一样,这里不再赘述。

2、元素的访问与统计及容器大小

对于map容器来说,支持[]运算来通过键访问值,同时map也提供了at()函数来随机访问容器中的元素,例如下面的代码:

m.at(key);
m[key];

map容器可以通过这两种方式来随机访问容器中元素,但multimap中允许存在重复的键值,因此无法使用这两种方式来随机访问容器中元素。

注意:上述m对象,在后面讲解中,如无特殊说明,代表map或multimap。

与集合一样,映射也提供了count()、max_size()与size()分别用于统计元素的个数、求算容器最大存储量和容器大小,其函数调用如下所示:

m.count(key);
m.max_size();
m.size();

因为map中无重复元素,因此其count()计算结果只有0和1,而multimap会有多个值。

3、获取头尾部元素

和其他容器一样,映射也提供了begin()与end()两个函数分别用于获取头部与尾部元素,其函数调用如下所示:

m.begin();  //返回容器中首元素的迭代器
m.end();   //返回容器中最后一个元素之后的迭代器

这两个函数的调用与其他容器方式相同,这里就不再赘述。

4、插入和删除元素

map和multimap的成员函数insert()用于插入元素,其函数调用有三种形式,如下所示:

m.insert(elem);    //在容器中插入元素elem
m.insert(pos, elem); //在pos位置插入元素elem
m.insert(begin, end); //在容器中插入[begin, end)区间的值

因为映射中存储的是键值对,因此其插入函数与其他容器稍有不同,要每次插入一对元素,参数中的elem指的是一对元素,接下来我们详细讲解如何用insert()函数将一对元素插入容器中。

(1)使用pair<>构建键值对对象

在插入元素时使用pair<>语句来标识插入的键值对,代码如下所示:

map<int, float> m; //也适用于multimap容器
m.insert(pair<int, float>(10,2.3));

在上述语句中,是用10,2.3构造了一个pair对象,即一个元素对,然后将这个元素对作为insert()函数的参数插入到容器中。

(2)使用make_pair()函数构建键值对对象

我们知道,pair对象的创建可以调用其构造函数,也可以调用make_pair()函数,因此insert()还可以与make_pair()函数结合使用将键值对插入到容器中,如下代码所示:

map<int, float> m; //也适用于multimap容器
m.insert(make_pair(10,2.3));

同样,使用make_pair()函数构造了一个pair对象,然后将这个对象作为参数插入到了容器中。

(3)使用value_type标志

value_type是容器中内部定义的typedef,标识着容器元素类型,因此insert()与value_type结合使用也可以将数据插入到容器中,代码如下所示:

map<int, float> m;  //也适用于multimap容器
m.insert(map<int,float>::value_type(10,2.3));

value_type是容器中自定义的数据类型,它可以将传入的10与2.3自动与容器类型匹配,从而将数据插入到容器中。

这三种方式都是用insert()第一种实现方式讲解,对于另外两种insert()实现方式同样适用。

除了insert()函数,map容器还可以用下标方式插入元素,此时可以将map容器视为关联数组,调用形式如下所示:

m[key] = value; //m只能是map容器,不适用于multimap

m[key]返回一个引用,该引用指向键值为key的元素,如果该元素尚未存在,则插入该元素,如果该元素已存在,则新插入的元素会覆盖原有的元素。

m[key]中的索引值“key”不一定是整型,它与容器中的键类型对应,例如:

map<char,string> m;
m1['a'] = "abc";

此时,key为char类型。但需要注意的是,下标法只适用于map容器,因为multimap容器中允许重复元素,因此无法用下标法插入元素。

与插入元素相对应,map与multimap也提供了erase()函数用于删除容器中的元素,该函数调用也有三种形式,如下所示:

m.erase(pos);  //删除位置pos上的元素,返回下一个元素的迭代器
m.erase(begin, end); //删除[begin, end)范围内的元素,返回下一个元素的迭代器
m.erase(key); //删除键为key的元素对

学习了map与multimap常用的几个操作函数,接下来我们通过一个案例来演示其用法,具体如例1所示。

例1

 1    #include <iostream>
 2    #include <map>
 3    #include <functional>
 4    #include <string>
 5    using namespace std;
 6    //定义printm()函数输出map容器元素
 7    void printm(map<char, double> mymap)
 8    {
 9        pair<char, double> p;  //创建pair对象,map中元素是成对的,也要成对输出
 10        map<char, double>::iterator it; //定义迭代器
 11        for (it = mymap.begin(); it != mymap.end(); it++)
 12        {
 13            p = (pair<char, double>)*it; //将迭代器指向的一对元素存放到p中
 14            cout << p.first << "->" << p.second << endl; //输出一对元素
 15        }
 16    }
 17    
 18    //定义printmt()函数输出multimap容器
 19    void printmt(multimap<int, string> mymul)
 20    {
 21        pair<int, string> p;
 22        multimap<int, string>::iterator it;
 23        for (it = mymul.begin(); it != mymul.end(); it++)
 24        {
 25            p = (pair<int, string>)*it;
 26            cout << p.first << "->" << p.second << endl;
 27        }
 28    }
 29    
 30    int main()
 31    {
 32        map<char, double> m;   //创建一个map容器
 33        //向容器m中插入元素
 34        m['a'] = 1.2;
 35        m['b'] = 3.6;
 36        m['c'] = 6.4;
 37        m['d'] = 0.8;
 38        m['e'] = 5.3;
 39        m['f'] = 3.6;
 40    
 41        cout << "map: " << endl;
 42        printm(m);
 43        cout << "map中key = a的值: " << m.at('a') << endl;
 44        cout << "map中key = f的元素出现次数: " << m.count('f') << endl;
 45        
 46        multimap<int, string> mt;  //创建一个multimap容器
 47        //向容器mt中插入元素
 48        mt.insert(pair<int, string>(1, "chuan"));
 49        mt.insert(make_pair(1, "zhi"));
 50        mt.insert(multimap<int, string>::value_type(3, "bo"));
 51        mt.insert(multimap<int, string>::value_type(4, "ke"));
 52    
 53        cout <<endl<< "multimap: " << endl;
 54        printmt(mt);
 55        cout << "multimap头部元素: ";
 56        pair<int, string> p;
 57        p = (pair<int, string>)*mt.begin();
 58        cout << p.first << "->" << p.second << endl;
 59        cout << "multimap尾部元素: ";
 60        p = (pair<int, string>)*(--mt.end());
 61        cout << p.first << "->" << p.second << endl;
 62        system("pause");
 63        return 0;
 64    }

运行结果如图1所示。

图1 例运行结果

在例1中定义了一个map容器m和一个multimap容器mt,接下来我们将本案例分为三个部分来讲解。

● 在例1开头定义了两个函数printm()与printmt(),分别用于输出map与multimap容器中的元素,两个函数实现相同,我们以print()讲解为主,因为映射中的元素都是成对的,因此第9行代码先创建了一个pair<>对象p,第10行代码定义了一个map<char,double>类型的迭代器it,接下来用一个for循环来获取容器中元素,在for循环中,第13行代码将迭代器指向的元素对存储到p中,然后第14行代码分别用pair<>的成员first与second将一对元素输出。

● 代码32行创建了一个map<char, float>容器m,代码34-39行用[]运算符向容器中插入元素,代码42行调用printm()函数输出m容器中的元素,由图8-15可知,容器中元素正确输出。代码43行调用at()函数随机访问键值为'a'的元素值,代码第44行调用count()函数统计键值为f的元素出现的次数,由图8-15可知,其出现次数为1。

● 代码第46行创建了一个multimap<int, strig>容器mt,代码48-51行向容器中插入元素,分别运用了pair<>、make_pair()与value_type三种形式向容器中插入元素。代码54行调用printmt()输出mt容器中的元素,由图8-15可知,容器中元素成功输出。代码55-58行输出容器中的头部元素,因为元素包括两个值,因此代码56行先创建了一个pair<>对象,接着57行代码调用begin()函数将头部的元素对存储到p中,58行代码调用pair中的first与second将值输出。代码59-61行输出尾部元素也是如此,只是end()函数返回的是末尾元素的下一个位置,因此end()获取的迭代器要先前移一个位置到末尾元素,再进行运算。

点击此处
隐藏目录