首页 > 学院 > 开发设计 > 正文

map和set的简单使用

2019-11-08 02:06:02
字体:
来源:转载
供稿:网友

做编程题的时候我们经常会苦于无法建立合适的索引快速找到数据,比如这样的场景:要求我们建立学号和成绩对应的数据库,并且查询指定学生的成绩。在学生学号均由较短的数字构成时,数组或许可以满足需求,而一个学生的学号可能包含字母,或者要求数据库实现一些其他更复杂的操作时,数组就不那么好用了,这时map和set就有了用武之地。

map的概念与python中的字典有点相似,而set又类似于集合。这里我们重点介绍关键词有序保存元素且关联词不可重复出现的关联容器类型map和set,关键词可以重复出现的multimap和multiset以及用哈希函数组织的无序集合不在本文讨论之列。

一、关联容器的创建 创建map和set前,需要添加头文件:

//map和set的头文件#include<map>#include<set>//方便叙述添加的#include<iostream>using namespace std;

map是关键词-值对的集合,而set只包含一个关键词。 例如:

map<string, int> stu_info; //例1set<string> stu_set; //例2

例1建立了名为stu_info的map,它的关键词是string,值是int,而例2建立的stu_set仅有一个关键词string。map和set的关键词不能重复出现。 map和set的关键词类型不是任意选取的,我们可以用string,int甚至double作为关键词,但是一个自己定义的结构体就做不到。核心在于关键词的类型必须支持比较操作,也就是说,如果我们想要让自己定义的类型充当map和set的关键词,那么我们就要定义自己的操作充当<运算符的功能。(这其实暗示了我们一个信息,map和set的关键词是有顺序的。) 我们可以对map和set进行列表初始化,初始化的方法是,对每一个关键词-值对,用{}括起来:

map<string,int> stu_info={{"Sally",90},{"Jimmy",92},{"Amy",85}};set<string> stu_set={"Sally","Jimmy","Amy"};

map的关键词-值对事实上是pair类型

二、向关联容器添加元素 1. 用insert添加 insert既可以批量添加也可以逐个添加,这里我们仅用C++ PRimer第五版第384页的代码举例: 逐个添加:

set<int> set2;set2.insert({5}); //{}加不加都可以

批量添加:

vector<int> ivec ={2,4,5,8,2,4,6,8};set<int> set2;set2.insert(ivec.cbegin(),ivec.cend()); //set2中有4个元素set2.insert({1,2,5,7,1,3,5,7}); //set2中有8个元素

批量添加既可以把元素的字面值放在大括号中添加,也可以用迭代器添加。从中我们也可以发现:对set添加其中已有的元素,对它是没有影响的。 map与set类似,不同的是map中元素的基本单位是pair,其他都与set大同小异。 2. 用下标添加 map可以用下标添加,set不可以。用下标添加形式上和数组的赋值差不多,比如:

stu_info["Sally"]=92;stu_info["John"]=90;

这种添加方式可以修改map中已有关键词对应的值,如果关键词在map中不存在,也会添加关键词,添加后会对值进行初始化,对于这一例子会初始化为0。

三、查询或遍历关联容器中的元素 1. 用下标查询

cout<<stu_info["Sally"];

显然,对于map可以用下标查询,用set不可以。但是用下标查询有一个副作用,那就是它有可能插入新的元素,在确认查询的值一定存在于map中时,可以用这种方法,但是如果想判断关键词在不在map中,这是不太合适的。 2. 用find查询

set2.find(3);stu_info.find("Sally");

find会返回一个迭代器,如果查找的关键词在关联容器中,会返回指向关键词的迭代器,如果不在关联容器中,会返回尾后迭代器,因此,用find判断关键词在不在关联容器中的方法是:

if(set2.find(3)==set2.cend()) cout<<"The number doesn't exist!";

如果要取出迭代器对应的元素,对map:

auto iter=stu_info.find("Sally");cout<<iter->first<<endl<<iter->second;

first取出的是关键词,second取出的是值。 对set:(一般没有必要这样取出set的值)

auto iter2=set2.find(3);cout<<*iter2<<endl;

可以对迭代器进行递增递减操作,因此可以通过这种方式逐个遍历关联容器:

for(auto iter3=stu_info.cbegin();iter3!=stu_info.cend();++iter3) cout<<iter3->first<<" "<<iter3->second<<endl;

四、删除元素 删除元素和插入元素中的insert一样,只要给出关键词或是迭代器,就可以逐个或是批量删除,只要将insert换成erase就可以了。 例如:

stu_info.erase("Sally");stu_info.erase(iter);

如果给erase传递的参数是关键词,那么返回的回事一个size_type的值,指出删除元素的数量。如果给erase传递的参数是迭代器,无论是传递用一个参数指向要删除的元素的迭代器还是用两个参数指示删除范围的迭代器,返回值都是迭代器,前者返回stu_info.cend(),后者返回迭代器的尾元素(即传递的第二个参数)。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表