第十一章 关联容器

版权声明:转载请注明出处 https://blog.csdn.net/weixin_39918693/article/details/86564874


关联容器和顺序容器有着根本的不同。关联容器中的元素是按关键字来保存和访问的。顺序容器是按元素在容器的中的位置来保存和访问的

关联容器支持高效的关键字查找和访问。两个主要的关联容器类型是map和set。map中的元素是一些关键字-值对;关键字起到索引的作用,值表示与索引相关联的数据。set中每个元素只包含一个关键字;set支持高效的关键字查询操作——检查一个给定关键字是否在set中

对于set来说,关键字即数据*

关联容器的有序与无序的区别是体现在关键字的有序和无序上的

无序容器使用哈希函数来组织元素

类型map和multimap定义在头文件map中;set和multiset定义在头文件set中;无序容器定义在unordered_map和unordered_set中


一、使用关联容器

关联容器也是模板,为了定义一个map,我们必须指定关键字和值的类型。注意map下标运算符的使用

当从map中提取一个元素时,会得到一个pair类型的对象。其由first和second两个成员

泛型算法也适用于关联容器,但是一般不这么用,一般使用特异性算法


二、关联容器概述

注意从结构上理解关联容器和顺序容器在操作上的异同

关联容器不支持接受一个元素值和一个数量值的操作

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

每个关联容器都定义了一个默认构造函数,它创建一个指定类型的空容器,也有用来拷贝初始化的构造函数

对于有序关联容器,关键字类型必须定义元素比较的方法。默认情况下,标准库使用关键字类型的<运算符来比较两个关键字

传递给关联容器的可调用对象的参数类型必须与有序关联容器中关键字的类型一致

我们可以定义一个操作来代替关键字上的<运算符。所提供的操作必须在关键字类型上定义一个严格弱序。自己理解什么是严格弱序

*关键不是关键字的类型,关键的是为该类型定义一个满足要求的比较操作

在实际编程中,重要的是,如果一个类型定义了“行为正常”的<运算符,则它可以用作关键字类型

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

multiset<Sales_data, decltype(compareIsbn)*> bookstore(compareIsbn);

pair类型,是一个模板,定义在头文件utility中。其两个成员都是public的

pair的操作:

  • 1、pair<T1, T2> p;
  • 2、pair<T1, T2> p(v1, v2);
  • 3、pair<T1, T2> p = (v1, v2);
  • 4、make_pair(v1, v2):返回一个用v1和v2初始化的pair,pair类型从初始值推断

pair的关系运算是利用元素的关系符来实现的

返回pair对象的函数的返回值的书写:好几种方法

这个地方需要例子**


三、关联容器操作

关联容器定义的类型别名:

  • 1、key_type:此容器类型的关键字类型
  • 2、mapped_type:每个关键字关联的类型,只适用于map
  • 3、value_type:对于set,与key_type相同,对于map,为pair<const key_type, mapped_type>

当解引用一个关联容器迭代器时,我们会得到一个类型为容器的value_type的对象的引用

我们无法通过set的迭代器来改变其关键字,因为通过迭代器得到的set的关键字是const的(肯定是顶层const)

当使用一个迭代器遍历一个map、multimap、set或multiset时,迭代器按关键字升序遍历元素

我们通常不对关联容器使用泛型算法,其本身定义了性能更高的特异性算法

对于不包含重复关键字的容器,插入一个包含已存在的关键字的元素对容器没有任何影响

set的insert有两个版本,分别接受一对迭代器,或是一个初始化器列表

对一个map进行insert操作时,必须记住元素类型是pair。有四种实现方式

insert(或emplace)返回的值依赖于容器类型和参数。p384

multiset和multimap的接受单个元素的insert操作返回一个指向新元素的迭代器。这里无需返回bool值,因为插入操作肯定会成功

关联容器有三个版本的erase操作:接受一个迭代器、迭代器对、关键字

下标运算符和at函数*

map和unordered_map容器提供了下标运算符和一个对应的at函数

map和unordered_map的下标运算符:如果不存在该关键字,将创建一个元素并插入容器中,进行值初始化

由于下标运算符可能插入一个新元素,我们只可以对非const的map使用下标操作

对map进行下标操作时,会获得一个mapped_type对象(左值),但解引用一个map迭代器时,会得到一个value_type对象

与vector与string不同,map的下标运算符返回的类型于解引用map迭代器得到的类型不同

在一个关联容器中查找元素的操作:

  • 1、lower_bound和upper_bound不适用于无序关联容器
  • 2、下标运算符和at操作只适用于非const的map和unordered_map
  • 3、find:
  • 4、count:
  • 5、lower_bound:不小于
  • 6、upper_bound:大于,一般是两者配合使用
  • 7、equal_bound:p389

如果一个multimap或multiset中有多个元素具有相同的关键字,则这些元素在容器中会相邻存储

如果元素不在multimap中,则lower_bound和upper_bound会返回相等的迭代器——指向一个不影响排序的给定关键字的插入点(一般来说就是尾后迭代器,也不一定)

如果lower_bound和upper_bound返回相同的迭代器,则给定关键字不在容器中

equal_range的用法类似,如果关键字不存在,则两个迭代器都指向关键字可插入的位置(相同的位置)


四、无序容器

新标准定义了4个无序关联容器。这些容器不是使用比较运算符来组织元素,而是使用一个哈希函数和关键字类型的==运算符

注意无序关联容器的操作与有序关联容器操作之间的关系

无序容器使用一个哈希函数将元素映射到桶。为了访问一个元素,容器首先计算元素的哈希值,它指出应该搜索哪个桶。容器将具有特定哈希值的所有元素都保存在同一个桶中。如果容器允许重复关键字,则具有相同关键字的元素在同一个桶中。因此,无序容器的性能依赖于哈希函数的质量和桶的数量和大小

无序容器管理操作:p395

默认情况下,无序容器使用关键字类型的==运算符来比较元素,他们还使用一个hash<key_type>类型的对象来生成每个元素(关键字)的哈希值。标准库为内置类型(包括指针)提供了hash模板。还为一些标准库类型,包括string和智能指针类型定义了hash。因此,我们可以直接定义关键字为内置类型(包括指针)、string、智能指针类型的无序容器

在无序容器中,我们可以提供函数来替代运算符和哈希值计算函数。虽然用相应的函数替代了运算符和哈希值计算函数,但是我并不知道其内部的工作机制

==运算符到底用来干吗??计算过哈希值以后还会干吗???????不懂?????

不明白具体的流程,就无法进行更改

猜你喜欢

转载自blog.csdn.net/weixin_39918693/article/details/86564874