🥕关联容器
2022-5-20
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property

 
关联容器支持高效的关键字查找和访问操作,2个主要的关联容器(associative-container)类型是 mapset
  • map 中的元素是一些键值对(key-value):关键字起索引作用,值表示与索引相关联的数据。
  • set 中每个元素只包含一个关键字,支持高效的关键字查询操作:检查一个给定关键字是否在 set 中。
 
标准库提供了8个关联容器,它们之间的不同体现在三个方面:
  • map 还是 set 类型
  • 是否允许保存重复的关键字
  • 是否按顺序保存元素
 
允许重复保存关键字的容器名字都包含单词 multi,无序保存元素的容器名字都以单词 unordered 开头:
  • mapmultimap 类型定义在头文件 map
  • setmultiset 类型定义在头文件 set
  • 无序容器定义在头文件 unordered_mapunordered_set
notion image
 
关联容器(有/无序)都支持通用的容器操作
关联容器不支持顺序容器特有的与位置相关的操作,如 push_front 或 back 。原因是——关联容器中元素是根据关键字存储的,所以这些操作对关联容器没有意义。而且,关联容器也不支持构造函数或插入操作这些接受一个元素值和一个数量值的操作。
除了支持与顺序容器一样的通用操作之外,关联容器还提供另外一些操作和类型别名,并且无序关联容器还提供了对 hash 性能进行调优的操作。
关联容器的迭代器是双向迭代器的(bidirectional)。
 

定义关联容器

定义 map 时,必须指定关键字类型和值类型;定义set 时,只需指定关键字类型,因为set中没有值。
每个关联容器都定义了一个默认构造函数,其将创建一个指定类型的空容器。可以将关联容器初始化为另外一个相同类型容器的副本,或者以一系列值进行初始化,只要这些值可以转为容器的类型。在新标准下可以用列表初始化元素。
 
初始化 map 时,必须提供关键字类型和值类型,提供的每个键值对用花括号 {} 包围,{key, value}
 

初始化 multimap 和 multiset

mapset 中的关键字必须唯一,multimapmultiset 没有此限制。
 

key类型的要求

对于有序容器——mapmultimapsetmultiset,关键字类型必须定义元素比较的方法。默认情况下,标准库使用关键字类型的 < 运算符来进行比较操作。
在集合类型中,关键字类型就是元素类型;在映射类型中,关键字类型是元素的第一部分的类型。
传递给排序算法的可调用对象必须满足与关联容器中关键字一样的类型要求。
 

有序容器的 key 类型

类似于算法提供的比较操作,我们也可以给键提供我们的比较操作用于替换 < 操作符。这个操作必须符合严格弱序(strict weak ordering)。可以认为严格弱序与“小于”等同。定义的比较函数必须有以下性质:
  • 两个 key 不能互相“小于等于”对方;如果 k1 小于等于 k2,那么 k2 决不能小于等于 k1
  • 如果 k1 小于等于 k2,并且 k2 小于等于 k3,那么 k1 必须小于等于 k3
  • 如果两个键,两个 key 都不小于对方,那么可以认为这两个键是相等的,如果 k1 == k2,并且 k2 == k3 那么,k1 必须与 k3 相等
如果两个键是相等的,容器认为这两者是一样。当用作 map 的键时,那么将只要一个元素与这两个键匹配,而其中任何一个键都可以作为 map 中的键。
在实际编程中,重要的是,如果一个类型定义了“行为正常”的 < 运算符,则它可以用作关键字类型。
 

使用关键字类型的比较函数

用来组织容器元素的操作的类型也是该容器类型的一部分。如果需要使用自定义的比较操作,则必须在定义关联容器类型时提供此操作的类型。操作类型在尖括号中紧跟着元素类型给出。
当用 decltype 来表示一个函数指针时,必须提供 *来表示我们确实需要的函数的指针,这是由于 decltype 推断出来的是函数的真实类型。当将 compareIsbn 指针作为构造函数实参时,可以直接使用其名字,而不必用 &compareIsbn的形式,这是由于用于参数的函数名字会隐式转为函数指针。
 

使用 map

map 类型通常被称为关联数组(associative array),关联数组类似于常规数组,不同之处在于其可以用非整数(integer)作为下标。map 中的值使用键进行查找而不是位置。
map 中提取一个元素时,会得到一个pair类型的对象。pair 是一个模板类型,保存两个名为 firstsecond 的公有数据成员。map 所使用的 pairfirst 成员保存关键字,用 second 成员保存对应的值。
 

使用 set

set 类型的 find 成员返回一个迭代器。如果给定关键字在 set 中,则迭代器指向该关键字,否则返回的是尾后迭代器。
 
与别的容器一样,set是模板。想要定义一个set ,需要指定元素的类型,在上面的例子就是string。与顺序容器一样,可以用列表初始化关联容器的元素。
 
为了检查键是否存在,可以调用setfind函数:
find 函数返回一个迭代器,如果键在 set 中,那么将返回指向那个键的迭代器。如果元素没有找到,find将返回尾后迭代器
 
 

pair类型

pair 定义在头文件 utility 中。一个 pair 可以保存两个数据成员,分别命名为 firstsecond。与容器一样,pair是模板。在创建 pair 时必须提供两个类型名字用于表示数据成员的类型。对于两个类型是否相同没有要求:
pair 的默认构造函数对数据成员进行值初始化。因此,anon是一个包含两个空 stringpairline 保存一个空string和一个空vectorword_count中的size_t成员值为0,而string成员被初始化为空
 
可以给每个成员提供初始值:
 
pair 支持的操作:
notion image
 

创建 pair对象的函数

C++11中,如果函数需要返回 pair,可以对返回值进行列表初始化。早期C++版本中必须显式构造返回值。
  • C++
  • 容器适配器关联容器操作
    目录