Loading

11关联容器

关联容器

两个主要的关联容器是mapset.

map中的元素是一些key-value对。

set中每个元素只包含一个关键字。

 

三个维度划分8个关联容器:

 

  • 或者是一个set,或者是一个map
  • 或者要求不重复关键字,或者要求允许重复关键字
  • 按顺序保存,无序保存

 

 

 

 


 

 

 


 


 

11.1 使用关联容器

map类型常称为关联数组(associative array)

set就是关键字的简单集合。 当只是想知道一个值是否存在时,set是最有用的。

使用map举例:

  

map<string,size_t> word_count; //
string word;
while(cin >> word)
    ++word_count[word]; //提取word的计数器并+

 

 

 

类似顺序容器,关联容器也是模板。为定义一个map,我们必须指定关键字和值的类型。

set中的元素是const

map中的元素是pair,其第一个成员是const的。

  • map:map中的元素是关键字-值(key-value)对。关键字起到索引作用,值则表示与索引相关联的数据。

  • set:set中每个元素只包含一个关键字,set支持高效的关键字查询操作-检查一个给定关键字是否存在set中。

 

允许重复的关键字的容器名字中都有multi。 无序保存的容器都以单词unordered开头。 无序容器采用哈希函数来组织非、元素。

  • map和multimap定义在头文件map中。
  • set和multiset定义在头文件set中。
  • 无序容器定义在unordered_map中和unordered_set中。

map是键值相互对应的,称为关联数组。名字-电话组合。可以使用一个人的名字来作为下标获取此人的电话号码。 set是关键字的简单集合。一个企业中开空头支票的人。

关键字类型


对于有序容器-map/multimap/set/multiset/,关键字类型必须定义元素比较的方法。

默认情况下,标准库使用关键字类型的< 运算符来比较两个关键字。

map<vector<int>::iterator,int>m1;//有效 vector迭代器支持比较操作
map<list<int>::iteratro,int>m2;//无效、list的元素不是连续存储,迭代器不支持比较操作。

在集合类型中,关键字类型就是元素类型;在映射类型中,关键字类型就是元素的第一部分的类型。

用来组织一个容器中元素的操作的类型也是该容器类型的一部分,为了使用自定义的类型,必须在定义关联容器时提供此操作的类型。

bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs){
    return lhs.isbn() < rhs.isbn();
};  //此函数在Sales_data对象的ISBN成员上定义了一个严格弱序。

//用尖括号指出要定义哪种类型,自定义的操作类型必须在尖括号中紧跟着元素类型指出。
multiset<Sales_data,decltype(compareIsbn)*>
    bookstore(compareIsbn); 
// 用compareIsbn来初始化bookstore对象,这表示我们向bookstore中添加元素时,通过调用compareIsbn来为这些元素排序。

在定义multiset时我们必须提供两个类型:关键字类型Sales_data以及比较操作类型——应该是一种函数指针类型。我们使用decltype来指出自定义操作的类型。

当使用decltype来获得一个函数指针类型时,必须加上一个*来指出我们要使用的一个给定函数类型的指针。


关联容器操作

  • key_type : 容器类型的关键字类型
  • mapped_type: 只要map才定义 每个关键字关联的类型
  • value_type:  对于set,与key_type相同。对于map,为pair<const key_value,mapped_value>

关联容器迭代器

auto map_it = word_count.begin();    *map_it指向一个pair<const string,size_t>对象的引用
cout << map_it->first;
cout << map_ir->second;
map_it->first = "new key" //错误 因为关键字是constmap_it->second++; //正确 我们可以通过迭代器改变元素的值。

set<int>::iterator set_it =iset.begin() //关联容器迭代器 均只允许访问元素,而不允许修改元素的值。


关联容器添加元素

由于set和map包含不重复的关键字,所以插入一个已存在的元素对容器没有任何影响。 set容器添加元素
insert有两个版本:接受一对迭代器或是一个初始化列表。

set2.insert(ivec.cbegin(),ivec.cend());
set2.insert({12,1,23,4});


map容器添加元素
插入的元素类型必须是pair

map<string,size_t> word_count;
word_count.insert({word,1});
word_count.insert(make_pair(word,1));
word_count.insert(pair<string,size_t>(word,1));
word_count.insert(map<string,size_t>::value_type{word,1});

insert返回值

对于不包含重复关键字的迭代器,添加单一元素的insert和emplace版本返回一个pair.

map<string,vector<int>>;类型的容器返回类型是 pair<map<string,vector<int>>::iterator,bool>;

pair的first的成员是一个迭代器,指向具有给定关键字的元素。
second元素是一个bool值,如果容器中已经存在,second元素为false,如果不在,则插入成功,返回true.

auto ret = word_count.insert({word,1});
if(!ret.second)
    ++ret.first->second;
    
    //ret是insert的返回值,是一个pair.
    ret.first:是pair的第一个成员,是一个map迭代器,指向具有给定关键字的元素。
    ret.first->:解引用此迭代器,提取map的元素,元素也是一个pair.
    ret.first->second:map中元素的值部分。
    ++ret.first->second:递增值。

向mulitmap或multiset添加元素

作者和他写的书籍。

对于允许重复的容器,接受单个元素插入,返回指向新元素的迭代器。

families.insert({family,child});


关联容器删除元素

  • 顺序容器的erase(见erase目录)操作。
  • erase(key_type):返回实际删除元素的数量。不重复容器:返回0或1.0代表容器中没有该元素。

map的下标操作

  • 只适用于map和unordered_map
  • 适用不在容器内的关键字,会添加一个具有该关键字的map。
  • 返回mapped_type对象,若对map迭代器解引用,则得到value_type对象。

posted @ 2019-11-15 15:08  三只猫-  阅读(187)  评论(0编辑  收藏  举报