stl之关联容器学习笔记1

来源:互联网 发布:卫青和平阳公主 知乎 编辑:程序博客网 时间:2024/05/26 14:10

概述

stl定义了另一种容器,名曰关联容器,关联容器和顺序容器的本质区别在于:关联容器通过键key来存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。关联容器的大部分行为与顺序容器相同,但其独特之处在于支持键的使用。

 

stl提供了两个基本的关联容器

1、map:容器中以键值的形式来组织数据。键key代表了数据在容器中的索引,而值则是表示所存储和读取的数据。

2、set:仅包含一个键,一般用于查询某个键是否存在。

举个例子:

字典是map的典型应用,字典中的字就是键,而字对应的内容解释就是值。

在某些文字处理中,set用作关键字的集合,程序决定这些关键字是否屏蔽。

 

set和map所包含的元素都具有不同的键,换句话说,一个相同的键不能在容器内出现两次(一个键无法对应多个值)。为了解决这个问题,标准库引入了multimapmultiset类型,这两种容器允许多个元素拥有相同的键。

举个例子:

在电话本的应用中,一个人名(键)可能对应多个号码(值),这时选用multimap较为合适。

 

pair类型

在讨论关联容器前,必须先引入一个与之关系密切的stl类型,pair类型。

pair类型是单个的键值对,说明白点,map中的单个元素就是一个pair类型元素,通过map迭代器进行解引用,得到的就是pair类型对象。

pair定义在utility头文件中。

pair类型提供的操作有:

1、pair<T1,T2> p1:创建一个空的pair对象,它的两个元素类型分别为T1,T2,采用值初始化(如string则初始化为"").

2、pair<T1,T2> p1(v1,v2):创建一个pair对象,它的两个元素类型分别为T1,T2,其中第一个成员初始化为v1,第二个成员初始化为v2.

3、make_pair(v1,v2):以v1和v2的值创建一个新的pair对象,起元素类型分别为v1和v2的类型.

4、p1<p2:两个pair之间的小于判断。采用字典次序比较,先比较p1.first和p2.first,如相等,则比较p1.second和p2.second.

5、p1==p2:如果两个pair对象的first和second元素依次相等,则返回真。该运算使用其元素的==运算(也就是元素类型必须提供==操作).

6、p.first:返回p中第一个的数据成员。

7、p.second:返回p中第二个数据成员。

技巧:pair类型的使用比较繁琐,因此,如果需要定义多个相同的pair类型,可以使用以下形式

typedef pair<string,string> name;

name shen("haha","hehe");

name wang("hoho","xixi");

 

map容器

在使用map前,必须包含map的头文件。

在定义map的时候,必须指明map的键值类型。

如:map<string,string> phone_book;//键为string类型,值为string类型

构造函数:

1、map<k,v> m:创建一个名为m的空map,键值类型分别为k和v。

2、map<k,v> m(m2):创建m2的副本m,m与m2必须有相同的键类型和值类型。

3、map<k,v> m(b,e):创建map类型的对象m,存储迭代器b和e标记范围内所有元素的副本(左闭合区间),元素类型必须能转换为pair<const k,v>。

 

注意:使用关联容器时,键的类型必须要有<操作符(比较操作符中的小于)。因为在向关联容器中增加元素时,是按照严格弱排序来排列的,即小的在大的前面,所以要实现这种排序,必须定义<操作符。

 

定义的类型:

map<k,v>::key_type:在map容器中,用作索引的键的类型。

map<k,v>::mapped_type:在map容器中,键所关联的值的类型。

map<k,v>::value_type:map容器中一个元素的类型,实际是一个pair类型,它的first是 map<k,v>::key_type类型,second是map<k,v>::mapped_type类型。

 

注意:对map迭代器进行解引用时,得到的是一个pair对象。那么,完全可以对map迭代器做->操作,这样比较简洁,看下面的例子:

map<int,int> ii_map;

...//插入元素

map<int,int>::iterator ii_iter=ii_map.begin();

cout <<ii_iter->first;

cout <<(*ii_iter).first;

 

map的操作

添加元素:

最常规的方法就是和顺序容器一样,使用map::insert成员函数插入元素。有以下三个版本:

1、m.insert(e):e是一个value_type类型(pair)。如果e.first不在m中,则插入一个值为e.second的新元素。反之,则保持m不变

注意:该函数返回一个pair类型对象,这个对象的first是指向键为e.first的元素的map迭代器,second是一个bool类型的对象,表示是否插入了该元素。

2、m.insert(beg,end):beg和end是标志着元素范围的迭代器(左闭合区间)。迭代器指向的元素,必须为value_type类型。对于范围内的所有元素,如果它的键在m中不存在,则将该键及其关联的值插入到m中。返回void。

3、m.insert(iter,e):e是待插入的元素,类型必须为value_type(pair)。如果e.first不在m中,则创建新元素,并以迭代器iter为起点搜索新元素存储的位置。返回一个迭代器,指向键为e.first的元素。

 

除了以上三种成员函数,还可以使用下标来实现添加元素。考虑以下的例子:

map<string,int> si_map;

si_map["haha"]=1;

以上示例执行了这些操作:

1、在si_map中搜索键为haha的元素,没找到。

2、将一个新的键值对插入si_map中,其中键位const string类型对象,保存了haha.值为int的初始化值,为0。

3、读取新插入的元素,并将它的值赋为1。

4、如果si_map中已经有haha这个键了,则将haha对应的值设置为1。

可见,map的下标即是元素的键。使用下标进行赋值时,如map中不存在给定的键,则添加这个键值。

查询操作

提供两个函数

1、m.count(k):返回m中键为k的元素出现的次数(对于map来说,只可能是0或1

2、m.find(k):搜索m中键为k的元素,如搜索到,则返回指向这个元素的迭代器。否则,返回超出末端的迭代器。

 

删除元素

1、m.erase(k):删除m中键为k的元素。返回size_type类型的值,表示删除的元素个数。(对于map来说,只可能是0或者1

2、m.erase(p):从m中删除迭代器p所指向的值。p必须指向m中确实存在的元素,当然不能等于m.end()。返回void。

3、m.erase(b,e):从m中删除一段范围内的元素(左闭合区间)。b和e必须标记m中的一段有效范围。b和e要么相等(删除范围为空),要么b所指的元素必须在e所指的元素之前。返回void。

原创粉丝点击