第11章 关联容器

1、标准库提供8个关联容器。

map 关联数组;保存关键字-值对
set 只保存关键字
multimap 关键字可重复的map
multiset 关键字可重复的set
unordered_map 用哈希函数组织的map
unordered_set 用哈希函数组织的set
unordered_multimap 哈希组织的map;关键字可重复
unordered_multiset 哈希组织的set;关键字可重复
  • 关联容器不支持顺序容器的位置相关的操作,例如push_back或push_front;原因是挂念容器中元素是根据关键字存储的,这些操作对关联容器没有意义。
  • 关联容器的迭代器都是双向的。

2、关联容器定义和初始化

C c; 默认构造函数
C c1(c2) 拷贝初始化
C c1 = c2 拷贝初始化
C c{a,b,c…} 初始值列表初始化
C c = {a,b,c…} 初始值列表初始化
C c(beg,end) 迭代器初始化
  • 初始化一个map时,必须提供关键字类型和值类型:{key, value}。
  • 对于有序容器,map、multimap、set和multiset,关键字类型必须定义元素比较的方法。默认情况下,标准库使用关键字类型的 < 运算符来比较两个关键字。

3、容器关键字和值的类型;key_type,mapped_type,value_type

key_type 此容器关键字类型
mapped_type 每个关键字关联的类型;只适用与map
value_type 对于set,与key_value相同;对于map,为pair<const key_type, mapped_type>
  • 关键字决定了排序,因此不允许改变,属于const类型。
  • 一个map的value_type是一个pair,我们可以改变pair的值,但不能改变关键字成员的值。
  • set的迭代器是const,可以用一个set迭代器读取元素的值,但不能修改。

4、关联容器与算法

  • 通常不对关联容器使用泛型算法,关键字是const这一特性意味着不能将关联容器传递给修改或重排容器元素的算法,因为这类算法需要向元素写入值。
  • 关联容器可用于只读取元素的算法,但是很多这类算法都要搜索序列,由于关联容器可以通过关键字进行快速查找,因此对其使用泛型算法几乎总是个坏主意。
  • 实际编程中,如果我们真要对一个关联容器使用算法,要么是将它当作一个源序列,要么当作一个目的位置。

5、添加元素

c.insert(v) v是value_type类型的对象,args用来构造一个元素
c.emplace(args) 对于map和set,只有当元素的关键字不在c中时才插入(或构造)元素。函数返回一个pair,包含一个迭代器,指向具有指定关键字的元素,以及一个指示插入是否成功的bool值。对于multimap和multiset,总会插入(或构造)给定元素,并返回一个指向新元素的迭代器
c.insert(beg,end) beg和end是迭代器,表示一个c::value_type类型值的范围,函数返回void
c.insert(initlist) 插入初始值列表,函数返回void
c.insert(p,v) 类似insert(v),但将迭代器p作为一个提示,指示从哪里开始搜索新元素应该存储的位置,返回一个迭代器,指向具有给定关键字的元素
c.emplace(p,args) 类似emplace(v),但将迭代器p作为一个提示,指示从哪里开始搜索新元素应该存储的位置,返回一个迭代器,指向具有给定关键字的元素
  • inset(emplace)返回的值依赖于容器类型和参数,对于不包含重复关键字的容器,添加单一元素的insert(emplace)版本返回一个pair。pair的first成员是一个迭代器,指向具有给定关键字的元素,second成员是一个bool值,false表示关键字已在容器中,insert什么事情也不做;true表示关键字不存在,元素被插入容器中。

6、删除元素

c.erase(k) 从c中删除每个关键字为k的元素,返回一个size_type值,指出删除的元素的数量
c.erase§ 从c中删除迭代器p指定的元素,返回一个指向p之后元素的迭代器
c.erase(beg,end) 删除迭代器对beg,end所表示范围中的元素,返回e

7、map的下标操作

c[k] 返回关键字为k的元素;如果k不在c中,添加一个关键字为k的元素,对其进行值初始化
c.at(k) 访问关键字为k的元素,带参数检查;若k不在c中,抛出一个out_of_range异常
  • 不能对一个multimap、unordered_multimap进行下标操作,因为这些容器中可能有多个值与一个关键字相关联。
  • 对一个map使用下标操作,其行为与数组或vector上的下标操作很不相同,使用一个不在容器中的关键字作为下标,会添加一个具有此关键字的元素到map中。

8、访问元素

c.find(k) 返回一个迭代器,指向第一个关键字为k的元素,若k不在容器中,则返回尾后迭代器
count(k) 返回关键字等于k的元素的数量,对于不允许重复关键字的容器,返回值永远是0或1
c.lower_bound(k) 返回一个迭代器,指向第一个关键字不小于k的元素
c.upper_bound(k) 返回一个迭代器,指向第一个关键字大于k的元素
c.equal_range(k) 返回一个迭代器pair,表示关键字等于k的元素的范围。若k不存在,pair的两个成员均等于c.end()
  • lower_bound(k)和upper_bound(k)不适合用于无序容器。

9、无序容器

  • 新标准定义了4个无序关联容器,这些容器不是使用比较运算符来组织元素,而是使用一个哈希函数(hash function)和关键字类型的==运算符。
  • 无序容器在存储上组织为一组桶,每个桶保存零个或多个元素。无序容器使用一个哈希函数将元素映射到桶。
    无序容器管理操作
  • 默认情况下,无序容器使用关键字类型的==运算符来比较元素,它们还使用一个hash<key_type>类型的对象来生成每个元素的哈希值。
  • 标准库为内置类型(包括指针)提供了hash模板,我们可以直接定义关键字是内置类型(包括指针类型)、string还是智能指针类型的无序容器。
  • 我们不能直接定义关键字类型为自定义类类型的无序容器,不能直接使用哈希模板,而必须提供我们自己的hash模板版本。

猜你喜欢

转载自blog.csdn.net/weixin_42205011/article/details/87864205