[读书笔记] C++Primer (第5版) 第11章 关联容器

关联容器中的元素是按关键字来保存和访问的,顺序容器中的元素是按顺序和位置保存和访问的。

1.关联容器概述:

   map和set是两种主要的关联容器。

   map中的元素是一些关联字-值,set中每个元素质包含一个关键字。    

按关键字有序保存元素
map关联数组,保存关键字-值对
set只保存关联字的容器
multimap关键字可重复出现的map
multiset关键字可重复出现的set
无序集合
unordered_map用哈希函数组织的map
unordered_set用哈希函数组织的set
unordered_multimap哈希组织的map,关键字可重复出现
unordered_multiset哈希组织的set,关键字可重复出现

   关联容器的迭代器都是双向的。

   set的元素类型就是关键字,map的元素类型是pair类型的对象。

   一个map和set中关键字必须是唯一的。但是对于加multi前缀的,允许多个元素具有相同的关键字。

2.pair类型:

   map的元素是pair:pair的数据成员是public的,两个成员分别命名为first(关键字)和second(对应值)。

   pair<string, int>  word_count;            // 保存一个string和一个int

   可以使用make_pair(v1, v2) 返回一个用v1和v2初始化的pair。

3.关键字类型的要求:

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

   可以向一个算法提供我们自己定义的比较操作,所提供的操作必须在关键字类型上定义一个严格弱序(可看作“小于等于”)。

   为了指定使用自定义的操作,必须在定义关联容器类型时提供此操作的类型。

   bool CompareIsbn(const Sale_data &lhs, const Sale_data &rhs){

       return lhs.isdn() < rhs.isdn();

   }

   multiset<Sale_data, decltypr(CompareIsdn)*>    set;                 // 必须加上一个*,来指出要使用一个给定函数类型的指针

4.关联容器操作:

  • key_type:关键字类型
  • mapped_type:关键字关联的类型,只适用于map
  • value_type:元素的值得类型,map是paur类型。

   使用作用于运算符来提取一个类型成员,例如:map<string, int>::key_value;

   当解引用一个关联容器的迭代器时,会得到一个类型为容器的value_type的值得引用。

   map和set的关键字是const的,所以不能修改。只能修改map的关联值。

   迭代器是按照关键字升序遍历元素的。

   通常不对关联容器使用算法,可用于只读算法。但使用关联容器专用的find会比调用泛型find快得多。

   关联容器使用算法的话,要么作为源序列,要么作为目的位置。

5.添加元素:

   map和set插入一个已存在元素,对容器没有影响。

   set1.insert(ivec.cbegin(), ivec.cend());            // 还可以使用初始化列表{}插入

   向map中插入元素,要先创建一个pair。

   返回值:添加单一元素的insert和emplace返回一个pair。

   ret.first:一个map迭代器,指向具有给定关键字的元素。ret.first->first 插入的关键字。

   ret.second:一个bool值,插入成功为TRUE,已存在与列表中为FALSE。multi关联容器无需返回bool值,因为可以重复,所以总是向容器中插入。

6.删除元素:

   关联容器可根据key_value删除元素。erase(key_value);

7.下标操作:

   set没有下标操作。multi也没有下标操作,因为可以有相同的关键字。map和unordered_map可以使用at()。

   可以使用[]的下标操作,如果该关键字不在map中,会为它创建一个元素插入到容器中。

   由于下标操作可能插入元素,所以只能对非const的map使用。

   顺序容器的解引用一个迭代器和下标访问的返回值是一样的,但是map的下标访问返回mapped_type(关联的值),解引用返回的是value_type(pair类型);

8.访问元素:

  • count(key) :返回这个关键字出现的次数。
  • upper_bound(key):返回一个迭代器,指向第一个关键字大于k的元素(不适用无序)
  • lower_bound(key):返回一个迭代器,指向第一个关键字不小于k的元素(不适用无序)
  • equal_range(k):返回一个pair,两个成员为迭代器,表示关键字为k的范围,没找到的话,都是尾后迭代器。

9.无序容器:

   使用哈希函数和==运算符来组织元素(有序使用<)。

   维护元素序列的代价通常很高,不需要排序时可使用无序容器

   也可使用find和insert。

   管理桶:无序容器在存储组织为一组桶,每个桶保存零个或多个元素,使用哈希函数将元素映射到桶。

   为访问一个元素,容器先计算元素的哈希值,它指出应该搜索哪个桶。

   容器将具有同一个哈希值的元素都存放在一个桶中(不同元素也可能映射到一个桶)。如果是multi的容器,相同的关键字元素也会在一个桶中。

   无序容器的性能依赖于哈希函数的质量和桶的数量和大小。

   使用一个hash<key_value>类型的对象来生成每个元素的哈希值。

   关键字需要有hash模板。标准库为内置类型,string和智能指针提供了hash模板。自定义类型的无序容器,不能直接使用哈希模板,必须提供我们自己的hash模板版本。

   size_t hasher(const Sale_data &sd){

       return hash<string>()(sd.isdn());     // 通过isdn的hash模板来达到Sale_data的模板

   }

   bool eqOp(const Sale_data &l, const Sale_data &r){  return l.isdn() == r.isdn();   }

   unordered_multiset<Sale_data, decltyle(hasher)*, decltype(eqOp)*>  setBook;

   如果自定义类已经定义了==操作符,则可以只重载哈希函数。

 

   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值