C++关联容器之map
1.map简介
map中的元素是关键字-值对:关键字起到索引的作用,值表示与索引相关的数据。我们常用的字典就是很好的map的实例,单词作为索引,其中文含义代表其值。map类型通常被称为关联数组,其和数组很相似,只不过其下标不是整数而是关键
字,我们通过关键字来查找值而不是位置。比如电话簿也是一个map的例子,姓名作为关键字其对应的值就为该人的电话号码。map类型定义在头文件map中。
注意:map是有序的且不允许重复关键字的关联容器!其有序的实现是依靠关键字类型中的"<"来实现的。
2.map的定义与初始化
2.1 创建空map
map<key_type,value_type> tempMap;//创建空map
2.2 列表初始化map
map<key_type,value_type> tempMap{
{key1,value1},
{key2,value2},
......};
2.3 使用已有的map复制构造
map<key_type,value_type> tempMap(existMap);//注意关键字类型与值类型匹配
2.4 指定已有map的迭代器返回进行构造
map<key_type,value_type> tempMap(b,e);//b,e为已有map对象的迭代器范围
3.map的赋值操作
我们可以将一个已有的map赋值给另一个map:
map1=map2;
map也支持列表赋值:
map<key_type,value_type> tempMap={
{key1,value1},
{key2,value2},
......};
4.关联容器额外的类型别名
除了之前的容器操作具有的类型,map有自己独特的类型别名:
类型别名 |
说明 |
key_type |
关键字类型 |
mapped_type |
关键字关联的类型 |
value_type |
pair<const key_type,mapped_type> |
举例
map<int ,string> myMap;
myMap::value_type v1;//v1为pair<const int ,string>类型
myMap::key_type v2;//v2为int类型
myMap::mapped_type v3;//v3为string类型
5. 新的数据类型 pair类型
pair标准类型定义在头文件utility中,一个pair保存两个数据成员,pair是用来生成特定类型的模板,当创建一个pair对象时必须要提供两个类型名,
pair<string string> A;//保存两个string
pair<string ,size_t> B;//保存一个string,一个size_t
pair<int ,vector<int>> C;//保存一个int和vector<int>
上面的代码都是执行了默认构造函数来对数据成员进行初始化,我们也可以初始化器:
pair<string,string> thePair{"Hello","World"};
pair的数据成员是public的,并且成员命名为first和second,我们可以使用普通的成员访问符“.”来进行访问。
我们可以在pair上的操作如下:
操作 |
说明 |
pair<T1,T2> P; |
p的成员数据类型分别为T1,T2,并执行默认初始化 |
pair<T1,T2> p(v1,v2); |
P的成员数据类型分别为T1,T2,并且使用v1,v2分别初始化 |
pair<T1,T2> p={v1,v2}; |
等价于上式 |
make_pair(v1,v2); |
返回一个v1和v2初始化的pair,其类型由v1和v2推断而来 |
p.first |
返回p的first成员 |
p.second |
返回p的second成员 |
p1 relop p2 |
执行关系运算(>,<,<=,>=),利用数据类型中的关系运算 |
p1==p2 |
相等性判断,必须first和second同时满足要求 |
p1!=p2 |
不等于判断 |
5.1 创建使用pair对象的函数
pair<int ,string> do_something(vecotr<string> &v)
{
if(!v.empty())
{
return {v.back().size(),v.back()};
}
else
{
return pair<int ,string>();
}
}
有些较早版本的编译器不支持花括号返回,那我们可以先构造pair对象再返回
pair<int ,string> do_something(vecotr<string> &v)
{
if(!v.empty())
{
return pair<int ,string>(v.back().size(),v.back());//也可使用make_pair来生成pair对象
}
else
{
return pair<int ,string>();
}
}
6.map的迭代器
当我们对map的迭代器进行解引用的时候我们得到的是value_type类型,也就是一个pair类型,要注意的是其first成员是const的,second成员是非常量成员,很明显我们不能改变map关键字,但我们可以改变关键字所关联的值,我们可以使用迭代器来遍历我们的map对象
auto map_iter=myMap.cbegin();
while(map_iter!=myMap.cend())
{
cout<<"key: "<<map_iter->first<<"value: "<<map_iter->second<<endl;
++map_iter;
}
注意:由于map中的关键字是const,我们一般不对map使用泛型算法!
7.向map添加元素
我们使用insert对map进行元素添加操作,我们必须要记住的一点就是map的元素是pair类型的,下面列举常用的insert方法:
myMap.insert({k1,v1});
myMap.insert(make_pair(k2,v2));
myMap.insert(pair<key_type,value_type>(k3,v3));
myMap.insert(map<key_type,value_type>::value_type(k4,v4));
下面列举其他的一些添加元素的方式:
操作 |
说明 |
c.insert(v) |
v为value_type对象,返回一个pair包含一个迭代器和是否成功插入的bool值,关键词不存在才插入 |
c.emplace(args) |
args用来构造元素,返回一个pair包含一个迭代器和是否成功插入的bool值,关键词不在才插入 |
c.insert(b,e) |
b和e是迭代器,指定多个元素插入,返回void |
c.insert(il) |
il花括号列表形式,返回void |
c.insert(p.v) |
和insert(v)类似,p是迭代器,指定从哪里开始搜索新元素应该存储的位置,返回值为一个迭代器,指出具有给定关键字的元素 |
c.emplace(p,args) |
和c.emplace(args)类似,p是迭代器,指定从哪里开始搜索新元素应该存储的位置,返回值为一个迭代器,指出具有给定关键字的元素 |
7.1 检测insert的返回值
添加单一元素的insert和emplace返回值一个pair,告诉我们插入是否成功,pair的first是一个迭代器,指向具有给定关键字的元素,second是一个bool型,如果插入成功为true,否则为false。如果关键字已经在map中那么insert和emplace什么也不做。
8.删除元素
使用erase函数来执行map的删除操作:
操作 |
说明 |
c.erase(k) |
删除c中关键词为k的元素,返回值为size_type类型,指出删除元素的数目,因为map中不允许重复,返回值为0或者1 |
c.erase(p) |
从c中删除迭代器p指定的元素,p必须指向一个真实存在的元素,返回值指向p之后元素的迭代器,如果p指向c的微元素,那么将返回c.end() |
c.erase(b,e) |
删除迭代器对b和e所表示返回的元素,返回值迭代器e |
9. map的下标操作
map提供了下标操作和at函数操作。我们对map使用下标操作要注意下标是关键字,还要注意的是对不存在map中的关键字使用了下标操作,会添加一个具有该关键字的元素到map中。
操作 |
说明 |
c[k] |
返回关键字为k的元素,如果k不在c中,添加一个关键字为k的元素,对其进行初始化 |
c.at(k) |
访问关键字为k的元素,带参数检查,如果k不在c中,则返回out_of_range异常 |
9.1使用下标操作的返回值
当我们对一个map进行下标操作的时候,会获得mapped_type对象,但当解引用map的迭代器时,会得到一个value_type对象,如果关键字不存在map中,下标运算依然会添加一个具有该关键字的新元素。在我们不确定一个元素是否在map中,且不想在map中进行添加就不能使用下标操作。
10.访问元素
当我们要确定一个元素是否存在map中,使用find是最佳的选择,对于不允许重复关键字的map来说,使用count函数返回的关键字计数只能为0和1。对于map元素的访问还有如下的操作:
操作 |
说明 |
c.find(k) |
返回一个迭代器,指向第一个关键字为k的元素,如果不在map中,则返回尾后迭代器c.end() |
c.count(k) |
返回关键字等于k的元素数量,对于map返回值只能为0和1 |
c.lower_bound(k) |
返回一个迭代器,指向第一个关键字不小于k的元素 |
c.upper_bound(k) |
返回一个迭代器,指向第一个关键字大于k的元素 |
c.equal_range(k) |
返回一个迭代器pair,表示关键字等于k元素的范围,如果k不存在,则pair的数据成员全是c.end() |
备注:如果使用lower_bound和upper_bound匹配关键字k,返回了相同的迭代器,那么关键字k不在map中。
posted on 2017-09-02 17:55 CodeBeauty 阅读(5288) 评论(0) 编辑 收藏 举报