文章目录
STL在C++中起到非常重要的作用,最大的好处就是将常见的数据结构进行了封装,使得我们不需要从底层一步步去实现,使用起来非常方便。C++知识小屋🏠的STL系列旨在将常见STL库的常见函数进行小结,以函数+示例+结果展示的方式作为文章的整体结构。希望能够在用到这些库的时候能够快速上手,熟练地使用它们来解决一些常见的问题。
什么是map?
- 现在设想一个问题,我们想要编写一个程序统计一个班级每个同学的成绩,比如叉烧同学是90分,大雄同学是100分,那么一种方法就是创建一个数组A,然后给每个同学编号,比如叉烧是1号,然后我们另A[1]=90,以此来达到存储的目的。
- 但是当我们查询成绩的时候,这个方法会显得比较复杂,因为我们还需要根据数组的下标找到是哪一位同学,这样子就不够便捷,那么有没有一种方法,能够把同学的名字跟其分数直接对应起来呢?map正好解决了这个问题。
- 我们可以创建一个map A< string,double >,表示这是一个从string类型映射到double类型的存储类型,然后我们令A[“叉烧”] = 90,A[“大雄”] = 100,这样子就能把每个同学直接跟其成绩直接储存在了A里面,这就是map的一个很常见的应用。你可能没看懂上面为什么要写< string,double >,没关系,下面正式来介绍map的用法。
map的用法
map的创建
-
当我们想要使用需要在程序前面加上下面的库:
#include <map>
-
map能够将任意两种类型构成一种映射关系,比如上面我们将同学的名字跟分数构成了映射关系,同学的名字是string类型,分数是double类型(可能有小数嘛),这样子当我们想要用map来储存这些映射关系的时候,就需要构造从string -> int 的映射,在代码中体现出来就是:
map<string,int> A; //创建一个名字为A的map,映射关系为string->int
-
需要注意的是,map是一对一的映射关系,比如上面的每个同学只有一个分数,如果我们对一个同学构造两个映射关系,则后面的会取代前面的。
map插入元素
- 好了,上面我们创建了一个名字为A的map,下面我们想要往里面插入元素,要怎么做呢?下面介绍三种方法:
A["叉烧"] = 90;
这是最简单也是最常用的一种方法,通过“[]”符号直接输入数据,比如我们想要把叉烧的分数是90分这条信息插入到A里面去,就在中括号里面写上叉烧,然后等号右边写上90分即可。你可能会问,为什么90分要写到等号右边呢?能不能把它们换个位置?这是不行的,因为map的定义就是从创建的时候左边的类型(string)映射到右边的类型(int),这个记住就好了。A.insert(pair<string,double>("胖虎",60));
A.insert(make_pair("大雄",100));
这里面用到了两个额外的知识点:pair与make_pair.什么是pair
- 当我们想要在函数里面返回两个值的时候,就可以使用pair,它表示将两个数据组合成了一个数据。我们可以简单理解为pair就是一种包含两个东西的特殊类型就好了。
- 关于pair的创建,跟map很相似,需要指定两个数据各自的类型,比如上面的胖虎是string类型,分数是double类型,然后我们就能直接创建pair对象
pair<string,double>("胖虎",60)
。 - 对于map的insert函数,由于需要传进去的是一个pair类型的对象,因此我们采用构造pair的方式传进去,进而达到我们的目的。
什么是make_pair
- 上面我们看到了pair对组的构造方法,我们需要指明两个数据的类型各自是什么。那么有没有办法更简单地创建pair对组呢?make_pair就是。
- 从上面的第三种方法中我们make_pair不需要指明两种变量类型是什么,直接将我们的大雄和100分放进去即可,这样子可以说比普通的pair更简洁。
map常见信息查看
A.size() //查看map里面的元素个数
A.empty() //查看A是否为空
A["大雄"] //查看大雄对应的分数
查看map中是否包含某个key(count和find函数)
比如我们现在想看看A中是否包含叉烧这个变量,可以用下面的两种方法:
- 第一种使用count函数,里面写上我们要找的学生的名字,如果存在,则返回1,不存在则返回0
- 第二种是使用find函数,如果存在,返回的是一个迭代器,如果不存在,则返回map的end(),因此我们可以通过返回值是否为end()判断是否存在该元素。
cout << A.count("叉烧") << endl; //方法一:使用count函数,找不到则返回0
if(A.find("叉烧")!=A.end()){ //方法二:使用find函数,找不到则返回A.end()
cout << 1 << endl;
}
查看map中某个value对应的key
比如现在我们想要看分数为90分的是谁,可以遍历一遍map,然后找出是谁。
- 注意:对于下面map的迭代器it,it->first表示的是key的值(学生名字),it->second表示的是value的值(学生的分数)
//寻找value对应的key
for(map<string,int>::iterator it = A.begin();it!=A.end();it++){
if(it->second == 90){
cout << "分数为90分的同学有:" << it->first << endl;
}
map完整程序
#include <iostream>
#include <map>
using namespace std;
int main(){
//构造对象A (后面的两个'>'中间一定要有空格,否则会报错)
map<string,int> A;
A["叉烧"] = 90;
A.insert(make_pair("大雄",100));
A.insert(pair<string,int>("胖虎",60));
cout << "A中的元素个数为: " << A.size() << endl;
cout << "A中是否为空: " << A.empty() << endl;
cout << "大雄的分数为" << A["大雄"] << endl;
for(map<string,int>::iterator it = A.begin();it!=A.end();it++){
cout << it->first << " - > " << it->second << endl;
}
//查看A中是否包含叉烧的两种方法
cout << "是否包含大雄: " << A.count("大雄") << endl << "是否包含叉烧: ";
if(A.find("叉烧")!=A.end()){
cout << 1 << endl;
}
//寻找value对应的key
for(map<string,int>::iterator it = A.begin();it!=A.end();it++){
if(it->second == 90){
cout << "分数为90分的同学有:" << it->first << endl;
}
}
return 0;
}
multimap
- 上面说的map只能表示1对1的映射,如果我们想要表示一对多的映射,则可以使用multimap,比如一个学生可以有多个成绩。
- 与map一样,当我们想要使用需要在程序前面加上下面的库:
#include <map>
- 与map不一样的是,multimap不能使用“[]”的方式访问,也就是说当我们插入新元素的时候,不能够像map一样使用
A["叉烧"] = 90;
的方法,只能使用insert的方式进行插入,同理当我们想要查看某位同学的分数,也不能像上面的A["大雄"] //查看大雄对应的分数
一样,而是要使用迭代器的方式进行查看。 - 当我们想要查看一位同学有几个分数的时候,可以使用count()函数进行查看,返回的值表示该同学一共在map中出现过多少次。
- 当我们想要在map中删除某一位同学的信息的时候,可以使用erase(“同学的名字”).
程序演示
- 下面的程序跟map的完整程序基本一样,不同之处如下:
- 创建的时候由map变成了multimap
- 删除了原先用"[]"访问的方法
- 插入了两个叉烧同学的分数,并且在调用count函数的时候发现叉烧的值返回为2,表示叉烧在map中出现过两次。
- 通过erase函数删除了叉烧同学的信息,然后输出发现叉烧同学的两个成绩都消失了,只剩下了胖虎的成绩。
#include <iostream>
#include <map>
using namespace std;
int main(){
//构造multimap对象A (后面的两个'>'中间一定要有空格,否则会报错)
multimap<string,int> A;
A.insert(make_pair("叉烧",90));
A.insert(make_pair("叉烧",100));
A.insert(pair<string,int>("胖虎",60));
cout << "A中的元素个数为: " << A.size() << endl;
cout << "A中是否为空: " << A.empty() << endl;
for(map<string,int>::iterator it = A.begin();it!=A.end();it++){
cout << it->first << " - > " << it->second << endl;
}
//查看A中是否包含叉烧的两种方法
cout << "是否包含叉烧: " << A.count("叉烧") << endl << "是否包含叉烧: ";
if(A.find("叉烧")!=A.end()){
cout << 1 << endl;
}
//寻找value对应的key
for(map<string,int>::iterator it = A.begin();it!=A.end();it++){
if(it->second == 90){
cout << "分数为90分的同学有:" << it->first << endl;
}
}
A.erase("叉烧");
cout << "删除叉烧后的map的信息为:" << endl;
for(map<string,int>::iterator it = A.begin();it!=A.end();it++){
cout << it->first << " - > " << it->second << endl;
}
return 0;
}