C++ 序列容器和关联容器

2024 年 08 月 29 日 | 阅读 9 分钟

C++ 中的容器是一个存储额外信息集合的对象。这些包可以存储任何数据类型,特别是用户定义的数据类型,因为它们是以类模板的形式实现的。在 C++ 中,有三种类型的容器:顺序容器、关联容器无序(关联)容器

顺序容器

C++ 中同一种数据的有序分组,其中每个元素都保留在指定位置,称为顺序容器。元素的位置由其插入的位置和时间决定。顺序容器有时也称为序列容器。顺序容器有 3 种类型:

1. 数组

数组是具有固定大小的容器。它们包含有限数量的元素。这些元素以紧密的线性顺序排列。我们可以通过提供索引直接访问数组元素,因此无需遍历整个数组。

示例

让我们用一个 C++ 示例来说明数组在顺序容器中的用法

输出

The array is: 11 16 19 10 14 
The Size of the array given array is: 5

说明

在此程序中,我们使用了数组标准库来构建一个名为 a 的数组。之后,我们使用了许多数组库指定的函数。begin()end() 方法返回指向数组开头和末尾元素的指针。size() 函数返回数组的大小。

2. 向量

向量是大小可变的数组容器。向量,类似于数组,使用连续的内存区域来存储其元素。但是,与数组不同,向量的数据大小可以不断变化,并且存储由包含它的容器有效处理。

示例

让我们用一个 C++ 示例来说明向量在顺序容器中的用法

输出

The output with vect.begin() and vect.end(): 1 2 4 8 16 32 
The output with vect.rbegin() and vect.rend(): 32 16 8 4 2 1 

说明

在这个例子中,我们构建了一个名为 vect 的向量。我们使用 push_back() 方法向该向量添加了元素。之后,我们使用了 begin()end() 操作,以及 rbegin()rend() 函数,来生成向量从左到右和从右到左的打印输出。

3. 双端队列

Dequedouble-ended queue(双端队列)的缩写。双端队列是一种在两端都可以动态改变大小的容器。我们可以使用随机访问迭代器(能够读取、写入和提供容器随机访问的通用指针)来访问双端队列的单个元素。

示例

让我们用一个 C++ 示例来说明双端队列在顺序容器中的用法

输出

The dequeue is: 40 20 10 30 
The size deq.size(): 4
The Deque after using pop_front() is: 20 10 30 

关联容器

关联容器是指其中元素的位置由其值决定的容器。元素插入的顺序对元素的位置没有影响。键,有时称为搜索键,用于访问关联容器中的元素。

关联容器有 4 种不同类型:

1. 集合

集合 (set) 是一个要求每个元素(或键)唯一的容器。元素一旦添加到集合中,就不能更改。但是,可以从集合中删除该元素。集合的元素以排序的方式存储,以便于存储和检索。

示例

让我们用一个 C++ 示例来说明集合在关联容器中的用法

输出

The set ss1 is -> 50 70 80 90 
Set ss1 after the using of s1.erase(50) method-> 70 80 90 

说明

在这个例子中,我们试图将数字 50 添加两次到集合中。然而,50 只被添加了一次,因为集合中的每个元素都必须是唯一的。之后,使用 erase() 方法删除了集合元素。

2. 多重集合

多重集合 (multiset) 是与集合类似的容器,但它允许重复的元素(键)。多重集合中的单个元素的值一旦保存就不能更改,尽管可以从集合容器中删除该元素。

示例

让我们用一个 C++ 示例来说明多重集合在关联容器中的用法

输出

The multiset ms1 is: 
30 30 40 60 80 

The multiset after the removal of values< 40: 
40 60 80 

说明

在这个例子中,我们能够在给定的应用程序中将元素 30 添加两次,因为多重集合允许元素重复。我们还使用了 erase() 方法来删除多重集合中所有小于 40 的元素。如果 40 没有包含在集合中,erase 函数本可以删除整个多重集合。

3. 映射

映射 (map) 是一个以键值对形式存储数据的容器。映射容器的变量必须是唯一的,并且每个键只能关联一个值。构成键及其关联值的元素的数据类型可以不同。映射的元素是相对于键存储的。任何元素都可以添加删除

示例

让我们用一个 C++ 示例来说明映射在关联容器中的用法

输出

The map map1 contains: 
KEY -> VALUE
 1 -> c
 2 -> k
 3 -> h
 4 -> i
 5 -> c

After running m1.erase(4), the map is: 
KEY -> VALUE
 1 -> c
 2 -> k
 3 -> h
 5 -> c

说明

在这个例子中,我们创建了一个映射,并使用 insert() 方法向其中添加条目。之后,使用 erase() 方法删除了键为 4 的元素。

4. 多重映射

多重映射 (multimap) 容器与映射容器相似,但它们允许将多个键存储在容器中。因此,键值对存在一对多的关系。在多重映射中,键的数据类型可能与其对应的值的不同。

示例

让我们用一个 C++ 示例来说明多重映射在关联容器中的用法

输出

The multimap m1 ha elements: 
KEY -> VALUE
 31 -> 3
 34 -> 1
 35 -> 4
 61 -> 6
 90 -> 9

The multimap mmap1 after removing the key values up to (31 KEY -> VALUE
 31 -> 3
 34 -> 1
 35 -> 4
 61 -> 6
 90 -> 9

说明

在这个例子中,我们构建了一个 multimap。之后,我们可以在 multimap 中两次使用相同的键,因为它允许重复的键值。我们使用 erase() 方法删除了所有键号小于 31 的条目。

C++ 中顺序容器和关联容器的主要区别

以下是 C++ 中顺序容器和关联容器的区别:

方面顺序容器关联容器
顺序按正确顺序存储元素。不保证顺序;元素可以使用键进行排序。
性能查找速度较慢(对于列表等线性结构为 O(n),对于向量为 O(log n))。平均查找速度较快(对于平衡二叉树为 O(log n),对于哈希数组为 O(1))。
访问可以使用迭代器、索引和基于范围的循环访问。每个元素关联的唯一键允许访问。
存储结构常见的实现是数组、链表或动态数组。使用树(map、multimap、set、multiset)或哈希(unordered_map、unordered_set)。
重复项允许重复;元素可能出现一次以上。键必须是唯一的;每个键只能映射到一个值。