关联容器的细节以及使用要点



和顺序容器不同,关联容器是通过键值对的方式存储数据的,可以通过键来读取数据。C++中主要的关联容器是map和set两种,它们都只能为一个键添加一个值,如果希望添加多个值,应该使用multimap和multiset。在了解签名提到的几个关联容器之前,我们需要先了解C++另一个简单的关联容器,它是所有关联容器中最简单的表达方式。



1.pair类型


pair类型是C++标准库提供的一个简单的关联容器,它包含在utility头文件中,它的主要方法如下:





1.1创建pair类型对象


考虑下面三条语句:

pair<string,int> pair1;
pair<string,int> pair2("one",1);
pair<string,int> = make_pair("two",2);


上面的三个方法都可以用于创建一个pair对象,pair1和pair2的区别在于,pair1用的是默认值进行初始化,pair2是指定了值得对象的。同时,也可以通过调用make_pair方法创建一个pair对象。

因为pair的声明比较长,如果需要多次用到,可以使用别名:

typedef pair<string,int> Book;
Book book1;
Book book2;


1.2访问pair的元素内容


pair提供了两个公开的成员对象,first和second,通过成员操作符就可以使用他们。如下:

cout<<pair.first<<pair.second;




2.map类型

map类型是键值对的集合,也是一种关联容器,也可以说它是pair类型的集合。访问它的元素的时候,是通过键来获取数据的而不是根据存储的位置读取的。下面了解它的特征:



2.1 map类型的定义


和大部分容器一样,map也提供基本的构造函数,如下:



使用如下:

map<int ,string> map1;
map<int,string> map2(map1);

map<int,string> map3(map1.begin(),map1.end());


在这里最主要的是提醒大家,可以作为key的数据类型,必须是可以进行比较的,这样map容器才能判断key是否是相同的从而达到一个容器只有唯一key的目的。即作为key的数据类型必须支持<比较操作符。



2.2访问map容器的元素


在map容器中,包含着三种类型的对象,分别是key_type,mapped_type,value_type,分别表示,键的数据类型,值得数据类型,map数据元素的数据类型。如图:





注意的一点是,键的值是不可以修改的。


map<int,string> map1;

map<int,string>::iterator iter=map1.begin();//等同于引用了map的首个数据类型为pair<const int,string>对象。

//可以通过first,second成员访问键和值
cout<<iter->first;
cout<iter->second+1;

上述的iter->first得到的是一个map<int,string>::key_type对象,这个对象不可更改,iter->second得到的是map<int,string>::mapped_type类型。




2.3使用下标访问和添加元素


map容器可通过使用下标的方式获取值,和顺序容器不同,它的下标是键。考虑如下代码:


map<string,int> map1;
map1["one"]=1;

上述代码会发生如下步骤:

①、判断map1是否存在one的键,得出不存在。
②、新建一个pair<string,int>对象。
③、将新建的对象插入map1中。
④、修改map1中one对应的值为1。


在看下面的一段代码:

string key;
while(cin>>key)
{
     ++map1[key];
}


如果key不存在,就会发生上面所说的情况,并且还会将值+1。如果key存在,则直接获取该值,然后+1。同时要记得,map1[ky]对应的类型是map<string,int>::mapped_type。



2.4通过insert添加元素



map提供了insert操作用于添加元素,它的好处在于,相对于下标,它不用通过值初始化,而是直接赋值。insert主要有三个版本:如下:




考虑一下代码:

map<string ,int> map1;

map1.insert(map<string,int>value_type("one",1));

//因为map<string,int>::value_type等同于pair<const string,int>

map1.insert(make_pair("two",2);

//也可以使用别名简略写法

typedef map<string,int>::value_type mapType;

map1.insert(mapType("threee",3));


此insert版本的实参是一个value_type类型,会返回一个包含当前插入元素的迭代器以及一个bool值得valueType类型。

pair<map<string,int>::iterator,bool> pair1=map1.insert(make_pair("one",1));

//通过bool判断是否插入成功
if(!(pair1->second)//表示已经存在该元素
{
cout<<pair1.first->second;
}

上述操纵向map1插入一个键值对,如果map1存在key对应的键,则插入失败,否则就插入成功。可通过bool进行判断。iterator是一个指向插入的键的元素的迭代器对象。可通过它来访问该值。




2.5通过find,count查找元素



用下标查找元素的时候,如果该key的元素不存在,会往map插入元素。但是有时候我们只是想查找元素,不存在的时候并不需要添加。这个时候怎么办呢?标准库提供了如下两个方法:





使用如下:

map<string,int> map1;

if(map1.count("one")==1)
   cout<<map1["one"];

map<string,int>::iterator iter=map1.find("one");

if(iter!=map1.end())
  cout<<iter->second;


count方法会返回key出现的次数。在map中,改返回结果只能是0或者1。find()方法返回的是一个迭代器对象,可以直接读取元素值。如果指定的key不存在,返回map容器最后一个元素的下一元素的迭代器,否则返回key指向的元素的迭代器。



3.set容器

set严格意义上来说,它不能算一个关联容器,但是它却经常和关联容器一起工作。它的主要作用是保存key。在set中,每个key都是唯一的。

考虑一下代码:


vector<int> vect;

for(vector<int>::size_type i=0;i<9;i++)
{
    vect.push_back(i);
    vect.push_back(i);
}

set<int> set1(vect.begin(),vect.end());

cout<<vect.size()<<endl;
cout<<set1.size()<<endl;


会发现,vect存在20个元素而set只有10个元素。原因在于set遇到相同的值只保存一个。


同样的,大部门map支持的操作,set也支持。比如count,find......



4.multimap和multiset的使用


由于map和set中每个键只能对应一个值,因此就出现了multimap和multiset,它们的每个键都可以对应多个实例。由于一个键对应多个实例,因此,不能使用下标反问他们的元素,除此之外,其他操作和mapset没有任何不同。


4.1添加元素

由于multi版本的map.set可以重复添加实例,所以添加操作总是成功的。

multimap<string,int> map1;
map1.insert(make_pair("one",1));
map1.insert(make_pair("one",2));

上述操作是可以成功的。


4.2 读取元素


虽然不可以用下标读取元素,但是可以使用find和count结合读取元素。

typedef map<string,int>::size_type mapType;
mapType sum=map1.count("one");
map<string,int>::iterator iter=map1.begin();
for(mapType i=0;i<sum;i++,iter++)
{
cout<<iter->second<<endl;
}


4.3删除元素


删除元素可以调用erase方法。

map1.erase("one")

map<string,int>::iterator iter=map1.begin();

map1.arase(iter);


如果是直接传递键的方式,将会删除所有的元素,并返回被删除的个数。如果是迭代器版本的,只删除指定的对象。




上述关联容器就这么多了,还有很多其他的操作都是和顺序容器一样的,读者需要多实践。



---------文章写自:HyHarden---------

--------博客地址:http://blog.csdn.net/qq_25722767-----------




  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值