11-4 无序容器
- 11.4.0 基本介绍
- 11.4.1 使用无序容器
- 管理桶
- 无序容器对关键字类型的要求
- 说明
- 举例
11.4.0 基本介绍
共有四种无序容器:
- unorder_set
- unorder_map
- unorder_multiset
- unorder_multimap
有序容器用比较运算符组织元素;无序容器用hash函数和关键字类型的==组织元素
何时使用:
如果关键字本身是无序的,且发现问题可以转换为用hash技术解决,就应该采用无序容器。
11.4.1 使用无序容器
无序容器的操作与有序容器完全一致,只不过加上了hash管理操作
管理桶
无序容器在存储上组织为一组桶,每个桶保存零个或多个元素。
无序容器使用一个哈希函数将元素映射到桶。
为了访问一个元素,容器首先计算元素的哈希值,它指出应该搜索哪个桶。容器将具有一个特定哈希值的所有元素都保存在相同的桶中。如果容器允许重复关键字,所有具有相同关键字的元素也都会在同一个桶中。因此,无序容器的性能依赖于哈希函数的质量和桶的数量和大小。
对于相同的参数,哈希函数必须总是产生相同的结果。
理想情况下,哈希函数还能将每个特定的值映射到唯一的桶。但是,将不同关键字的元素映射到相同的桶也是允许的。当一个桶保存多个元素时,需要顺序搜索这些元素来查找我们想要的那个。计算一个元素的哈希值和在桶中搜索通常都是很快的操作。但是,如果一个桶中保存了很多元素,那么查找一个特定元素就需要大量比较操作。
无序容器提供了一组管理桶的函数,如表11.8所示。这些成员函数允许我们查询容器的状态以及在必要时强制容器进行重组。
无序容器对关键字类型的要求
说明
默认情况下,无序容器使用关键字类型的==运算符来比较元素,它们还使用一个hash
标准库为内置类型(包括指针)提供了hash模板。还为一些标准库类型,包括string 和我们将要在第12章介绍的智能指针类型定义了hash。因此,我们可以直接定义关键字是内置类型(包括指针类型)、string还是智能指针类型的无序容器。
但是,我们不能直接定义关键字类型为自定义类类型的无序容器。与容器不同,不能直接使用哈希模板,而必须提供我们自己的hash模板版本。我们将在16.5节(第626页)中介绍如何做到这一点。
举例
定义==
,和hash函数
:
size_t hasher(const Sale_data &sd){
return hash()(sd.isbn());
}
bool eqOp(const Sale_data &lhs, const Sale_data &rhs){[
return lhs.isbn() == rhs.isbn();
]}
用上述函数定义multiset:
using SD_multiset = unorder_multiset;
SD_multiset bookstore(42, hasher, eqOp);
如果一个类类型已经定义了==
,只需要重载hash函数:
unorder_set fooset()