关联容器支持高效的关键字查找和访问
两个主要的关联容器是map和set
- map中的元素是关键字-值(key-value)对:关键字起到索引的作用,值则表示与索引相关联的数据。
- set中每个元素只包含一个关键字:set支持高效的关键字查询工作——检测一个给定关键字是否在set中。
标准库提供8个关联容器
按关键字保存有序元素 | |
---|---|
map | 关联数组:保存关键字-值对 |
set | 关键字即值,即只保存关键字的容器 |
multimap | 关键字可重复出现的map |
multiset | 关键字可重复出现的set |
无序集合 | |
unordered_map | 用哈希函数组织的map |
unordered_set | 用哈希函数组织的set |
unordered_multimap | 哈希组织的map:关键字可以重复出现 |
unordered_multiset | 哈希组织的set:关键字可以重复出现 |
这八个容器体现在三个维度上
- 是map或者set
- 允不允许重复关键字
- 按顺序保存或者无序保存
map和multimap定义在头文件map中;
set和multiset定义在头文件set中;
无序容器定义在头文件under_map和under_set中
map
map类型通常被称为关联数组,关联数组与正常数组类似,不同之处在于其下标不必是整数,我们通过一个关键字而不是位置来查找值
set就是关键字的简单集合,当只想知道一个值是否存在时,set是最有用的
使用map
使用迭代器时,应该加上引用,会得到一个pair类型的对象,pair的first成员保存关键字,用second保存对应的值
map<string,int> worldcount;
string word;
while(cin>>word)
++worldcount[word];
for(const auto &W:worldcount)
cout<<W.first<<"occurs"<<W.second<<"time"<<endl;
pair是一个模板类型,保存两个名为first和second的共有数据类型。
map所使用的pair用first成员保存关键字,用second成员保存对应的值
使用 set
map<string,int> countword;
set<string> exclude={
"the","but","and"};
string word;
while(cin>>word)
if(exclude.find(word)==exclude.end())
++wordcount[word];
定义关联容器
-
set<string> exclude={"the","but","or"};
-
map<string,string>authors={ {"joyce","james"},{"Austin","Jane"}};
-
set<int> iset(ivec.begin(),ivec.cend());
pair类型
pair类型定义在头文件utility里
- pair保存两个数据成员类似容器,pair用来生成特定类型的模板
- 当创建一个pair时,我们必须提供两个类型名,pair的数据成员将具有对应的类型
pair<string,string> anon;
pair<string,vector<int>> line
pair<string,string>author{
"james","joyce"};
- pair的默认构造函数对数据成员进行初始化
- 也可以提供初始化器
pair 的两个数据成员分别是first和second
map的成员是map
int main(){
pair<string,int> p;
vector<pair<string,int>> vp;
string s;
int i;
while(cin>>s>>i){
p={
s,i};
vp.push_back(p);
}
for(int i=0;i<vp.size();i++){
cout<<vp[i].first<<vp[i].second<<endl;
}
return 0;
}
vec.push_back(std::make_pair(str, i));
vec.push_back({
str, i });
vec.push_back(std::pair<string, int>(str, i));
关联容器操作
关联容器迭代器
当解引用一个关联容器迭代器时我们会得到一个类型为容器的value_type 的值的引用。
对map而言,value_type是一个pair类型,其first成员保存const的关键字,second成员保存值。
auto map_it=wordcount.first();
cout<<map_it->first;
cout<<map_it->second;
map_it->first="new key";//错误 const类型
++map_it->second;
set的迭代器是const的
可以用一个set迭代器来读取元素的值,但是不能修改
set<int> iset={
1,2,3,4,5,6,7,8};
set<int>::iterator set_it=set.begin();
if(set!=iset.end()){
*set_it=42;//错误
cout<<*set_it<<endl;
}
遍历关联容器
map和set都支持begin和end操作
auto map_it=wordcount.begin();
while(map_it!=wordcount.end()){
cout<<*map_it->first;
++map_it;}
本程序是按字典序排列的,当使用一个迭代器遍历一个map,multimap,set,multiset时,迭代器按照关键字升序遍历元素。
添加元素
由于map和set包含不重复的关键字,因此插入一个已存在的元素对容器没有任何影响
vector<int> ivec={
2,4,6,8,2,4,6};
set<int> iset;
iset.insert(ivec.begin(),ivec.end());
iset.insert({
1,3,4,5,7,3,7});
insert有两个版本,分别接受一对迭代器,或是一个初始化器列表。
删除元素
auto cnt=authors.erase(“barth,jhon”);
erase返回1或者0,返回0表示想要删除的元素不在容器中
map的下标操作
访问元素