关联容器详解(map,set)

本篇文章转自博客:https://blog.csdn.net/qq_25722767/article/details/52311349

和顺序容器不同,关联容器是通过键值对的方式存储数据的,可以通过键来读取数据。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容器可通过使用下标的方式获取值,和顺序容器不同,它的下标是键。考虑如下代码:

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

 在看下面的一段代码:

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

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

①、判断map1是否存在one的键,得出不存在。

②、新建一个pair<string,int>对象。

③、将新建的对象插入map1中。

④、修改map1中one对应的值为1。

如果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);

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

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

猜你喜欢

转载自blog.csdn.net/qq_40707370/article/details/82284731