C++ (Standard Template Library - STL) map 容器

C++ (Standard Template Library - STL) map 容器

序列容器是管理数据的宝贵工具,序列容器不提供方便的数据访问机制。map 容器提供了一种有效的存储和访问数据的方法。

map 容器是关联容器的一种。在关联容器中,对象的位置取决于和它关联的键的值。键可以是基本类型,也可以是类类型。字符串经常被用来作为键,如果想要保存姓名和地址的记录,就可以这么使用。名称通常可能是一个或多个字符串。关联容器中的对象位置的确定取决于容器中的键的类型,而且对于特定容器类型的内部组织方式,不同的 STL 有不同的实现。

map 容器有 4 种,每一种都是由类模板定义的。所有类型的 map 容器保存的都是键值对类型的元素。map 容器的元素是 pair<const K, T> 类型的对象,这种对象封装了一个 T 类型的对象和一个与其关联的 K 类型的键。pair 元素中的键是 const,因为修改键会扰乱容器中元素的顺序。

  1. map<K, T> 容器,保存的是 pair<const K, T> 类型的元素。pair<const K, T> 封装了一对键对象,键的类型是 K,对象的类型是 T。每个键都是唯一的,所以不允许有重复的键。但可以保存重复的对象,只要它们的键不同。map 容器中的元素都是有序的,元素在容器内的顺序是通过比较键确定的。默认使用 less<K> 对象比较。

  2. multimap<K, T> 容器和 map<K, T> 容器类似,也会对元素排序。它的键必须是可比较的,元素的顺序是通过比较键确定的。和 map<K, T> 不同的是,multimap<K, T> 允许使用重复的键。一个 multimap 容器可以保存多个具有相同键值的 <const K, T> 元素。

  3. unordered_map<K, T>pair<const K, T> 元素的顺序并不是直接由键值确定的,而是由键值的哈希值决定的。哈希值是由一个叫作哈希的过程生成的整数。unordered_map<K, T> 不允许有重复的键。

  4. unordered_multimap<K, T> 可以通过键值生成的哈希值来确定对象的位置,但它允许有重复的键。

mapmutilmap 容器的模板定义在 map 头文件中,unordered_mapunordered_multimap 容器的模板定义在 unordered_map 头文件中。可以通过 map 模板类型名的前缀来识别容器的特性。

  • multi 前缀表明键不必唯一,但如果没有这个前缀,键必须唯一。
  • unordered_prefix 前缀表明容器中元素的位置是通过其键值所产生的哈希值来决定的,而不是通过比较键值决定的。如果没有该前缀,那么元素的位置就由比较键值决定。

map<K, T> 类模板定义在 map 文件头中,它定义了一个保存 T 类型对象的 map,每个 T 类型的对象都有一个关联的 K 类型的键。容器内对象的位置是通过比较键决定的。可以用适当的键值从 map 容器中检索对象。下图展示了一个用名称作为键的 map<K, T> 容器,对象是整数值,用来表示年龄。

在这里插入图片描述

为了可以在必要时生成默认的元素,容器保存的对象通常需要定义一个默认的构造函数。string 类定义了 operator<(),因而可以用默认的 less<string> 来比较。

不要因为 map 使用 less<K> 对元素排序就被误导,这些元素并没有被组织成一个简单的有序序列,STL map 容器对元素的组织方式并没有具体要求,但元素一般都会保存在一个平衡二叉树中。容器中的元素被组织成一个平衡二叉树,树的高度 - 根节点和叶节点之间的高度是最低的。如果每个节点的左子树和右子树的高度差不超过 1,那么可以说这棵二叉树就是平衡的。图 2 展示了图 1 所表示的 map 容器可能的平衡二叉树。

在这里插入图片描述

图 2 所示的树有 3 层,所以从根节点开始,找到任意的元素最多需要 3 步。这里选择的根节点可以使树的高度最小,对于每个父节点来说,它的键值大于它的左子节点,但小于它的右子节点。为了保持二叉树的平衡,当添加一个新的元素时,可能会导致根节点发生改变。显然,在添加新元素时,为了保持树的平衡,会产生一些额外的开销。作为回报,容器中的元素越多,相对于线性排列和非平衡树,平衡树组织元素的效率也越高。从包含 n 个元素的平衡二叉树中检索一个随机元素所需的时间为 O ( l o g 2 n ) O(log_{2}^{n}) ,从序列中检索元素所需的时间为 O(n)

注意,O(n) 计算时间随着参数的增加而增加。O 被认为是有序的,O(n) 表明线性执行时间在以 n 增加。 O ( l o g 2 n ) O(log_{2}^{n}) 计算时间远没有 n 增加得快,因为它是以 l o g 2 n log_{2}^{n} 计算的。

发布了509 篇原创文章 · 获赞 1824 · 访问量 110万+

猜你喜欢

转载自blog.csdn.net/chengyq116/article/details/104625304