和顺序容器不同,关联容器是通过键值对的方式存储数据的,可以通过键来读取数据。C++中主要的关联容器是map和set两种,它们都只能为一个键添加一个值,如果希望添加多个值,应该使用multimap和multiset。在了解签名提到的几个关联容器之前,我们需要先了解C++另一个简单的关联容器,它是所有关联容器中最简单的表达方式。
1.pair类型
pair类型是C++标准库提供的一个简单的关联容器,它包含在utility头文件中,它的主要方法如下:
1.1创建pair类型对象
考虑下面三条语句:
pair pair1;
pair pair2("one",1);
pair = make_pair("two",2);
上面的三个方法都可以用于创建一个pair对象,pair1和pair2的区别在于,pair1用的是默认值进行初始化,pair2是指定了值得对象的。同时,也可以通过调用make_pair方法创建一个pair对象。
因为pair的声明比较长,如果需要多次用到,可以使用别名:
typedef pair Book;
Book book1;
Book book2;
1.2访问pair的元素内容
pair提供了两个公开的成员对象,first和second,通过成员操作符就可以使用他们。如下:
cout<
2.map类型
map类型是键值对的集合,也是一种关联容器,也可以说它是pair类型的集合。访问它的元素的时候,是通过键来获取数据的而不是根据存储的位置读取的。下面了解它的特征:
2.1 map类型的定义
和大部分容器一样,map也提供基本的构造函数,如下:
使用如下:
map map1;
map map2(map1);
map map3(map1.begin(),map1.end());
在这里最主要的是提醒大家,可以作为key的数据类型,必须是可以进行比较的,这样map容器才能判断key是否是相同的从而达到一个容器只有唯一key的目的。即作为key的数据类型必须支持<比较操作符。
2.2访问map容器的元素
在map容器中,包含着三种类型的对象,分别是key_type,mapped_type,value_type,分别表示,键的数据类型,值得数据类型,map数据元素的数据类型。如图:
注意的一点是,键的值是不可以修改的。
map map1;
map::iterator iter=map1.begin();//等同于引用了map的首个数据类型为pair对象。
//可以通过first,second成员访问键和值
cout<first;
coutsecond+1;
上述的iter->first得到的是一个map
::key_type对象,这个对象不可更改,iter->second得到的是map::mapped_type类型。
2.3使用下标访问和添加元素
map容器可通过使用下标的方式获取值,和顺序容器不同,它的下标是键。考虑如下代码:
map map1;
map1["one"]=1;
上述代码会发生如下步骤:
①、判断map1是否存在one的键,得出不存在。
②、新建一个pair对象。
③、将新建的对象插入map1中。
④、修改map1中one对应的值为1。
在看下面的一段代码:
string key;
while(cin>>key)
{
++map1[key];
}
如果key不存在,就会发生上面所说的情况,并且还会将值+1。如果key存在,则直接获取该值,然后+1。同时要记得,map1[ky]对应的类型是map
::mapped_type。
2.4通过insert添加元素
map提供了insert操作用于添加元素,它的好处在于,相对于下标,它不用通过值初始化,而是直接赋值。insert主要有三个版本:如下:
考虑一下代码:
map map1;
map1.insert(mapvalue_type("one",1));
//因为map::value_type等同于pair
map1.insert(make_pair("two",2);
//也可以使用别名简略写法
typedef map::value_type mapType;
map1.insert(mapType("threee",3));
此insert版本的实参是一个value_type类型,会返回一个包含当前插入元素的迭代器以及一个bool值得valueType类型。
pair
上述操纵向map1插入一个键值对,如果map1存在key对应的键,则插入失败,否则就插入成功。可通过bool进行判断。iterator是一个指向插入的键的元素的迭代器对象。可通过它来访问该值。
2.5通过find,count查找元素
用下标查找元素的时候,如果该key的元素不存在,会往map插入元素。但是有时候我们只是想查找元素,不存在的时候并不需要添加。这个时候怎么办呢?标准库提供了如下两个方法:
使用如下:
map map1;
if(map1.count("one")==1)
cout<::iterator iter=map1.find("one");
if(iter!=map1.end())
cout<second;
count方法会返回key出现的次数。在map中,改返回结果只能是0或者1。find()方法返回的是一个迭代器对象,可以直接读取元素值。如果指定的key不存在,返回map容器最后一个元素的下一元素的迭代器,否则返回key指向的元素的迭代器。
3.set容器
set严格意义上来说,它不能算一个关联容器,但是它却经常和关联容器一起工作。它的主要作用是保存key。在set中,每个key都是唯一的。
考虑一下代码:
vector vect;
for(vector::size_type i=0;i<9;i++)
{
vect.push_back(i);
vect.push_back(i);
}
set set1(vect.begin(),vect.end());
cout<
会发现,vect存在20个元素而set只有10个元素。原因在于set遇到相同的值只保存一个。
同样的,大部门map支持的操作,set也支持。比如count,find......
4.multimap和multiset的使用
由于map和set中每个键只能对应一个值,因此就出现了multimap和multiset,它们的每个键都可以对应多个实例。由于一个键对应多个实例,因此,不能使用下标反问他们的元素,除此之外,其他操作和mapset没有任何不同。
4.1添加元素
由于multi版本的map.set可以重复添加实例,所以添加操作总是成功的。
multimap map1;
map1.insert(make_pair("one",1));
map1.insert(make_pair("one",2));
上述操作是可以成功的。
4.2 读取元素
虽然不可以用下标读取元素,但是可以使用find和count结合读取元素。
typedef map::size_type mapType;
mapType sum=map1.count("one");
map::iterator iter=map1.begin();
for(mapType i=0;isecond<
4.3删除元素
删除元素可以调用erase方法。
map1.erase("one")
map::iterator iter=map1.begin();
map1.arase(iter);
如果是直接传递键的方式,将会删除所有的元素,并返回被删除的个数。如果是迭代器版本的,只删除指定的对象。
上述关联容器就这么多了,还有很多其他的操作都是和顺序容器一样的,读者需要多实践。
---------文章写自:HyHarden---------
--------博客地址:http://blog.csdn.net/qq_25722767-----------