1. 什么是容器
C++容器是标准模板库(STL)的核心组件,本质上是预定义的、类型安全的"数据盒子"。它们以模板类的形式提供了一套即插即用的数据结构(如动态数组、链表、树等),通过自动管理内存和提供通用操作接口(增删查改),简化了数据集合的存储与处理流程。
2. 容器分类
C++容器分类及常用容器如下:
2.1. 顺序容器
顺序容器中的顺序两个字儿指的是元素插入序列的顺序,和元素的值没有关系。
vector:动态数组,变长数组,容量不够时会自动扩容,在尾部增加或删除元素的效率最高(O(1) 常数阶),在其它位置插入或删除元素效率较差(O(n) 线性阶)。deque:双端队列,和 vector 非常相似,区别在于使用该容器不仅尾部插入和删除元素高效,在头部插入或删除元素也同样高效,时间复杂度都是 O(1) 常数阶,但是在容器中某一位置处插入或删除元素,时间复杂度为 O(n) 线性阶。list:双向链表,可以在序列的任意位置高效地增加或删除元素(O(1)),但访问容器中任意元素的速度要比前三种容器慢,这是因为链表这种东西必须从第一个元素或最后一个元素开始访问,需要沿着链表移动,直到到达想要的元素。forward_list:单向链表,以单链表的形式组织元素,内部的元素只能从第一个元素开始访问,比链表容器快、更节省内存。array:基于数组,大小固定。
2.2. 关联容器
分为有序和无序两种,分配基于红黑树和哈希表实现。
2.2.1. 有序关联容器
底层为红黑树,,排序容器中的元素是按序插入的(默认按键的升序排列),所以有序关联容器在查找时具有非常好的性能。
set:唯一键集合map:键值对映射multiset:允许重复键的集合multimap:允许重复键的映射
2.2.2. 无序关联容器
底层为哈希表,和有序关联容器不同,哈希容器中的元素是未排序的,元素的位置由哈希函数确定。
unordered_set:哈希集合unordered_map:哈希映射unordered_multiset:允许重复键的哈希集合unordered_multimap:允许重复键的哈希映射
2.3. 容器适配器
封装基础容器来提供特定的功能。
stack:后进先出(LIFO)栈queue:先进先出(FIFO)队列priority_queue:优先级队列(默认最大堆)
2.4. 其他特殊容器
- string(常作为独立容器使用)
3. 容器的访问与遍历
3.1. 容器迭代器
使用迭代器访问或便利 容器中的元素,指定容器中的一段区间,用于遍历容器中的元素。STL 标准库为每一种标准容器定义了一种迭代器类型,这意味着,不同容器的迭代器也不同,其功能强弱也有所不同。
3.2. 常用迭代器
下面展示容器的常见成员函数,这些成员函数返回一个特定的迭代器。
|
|
|
|
|
|
|
|
3.3. 迭代器分类
可以理解为对于指针的封装,常用的迭代器可以分为分为输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器 5 种。其中输入迭代器和输出迭代器比较特殊,它们不是把数组或容器当做操作对象,而是把输入流/输出流作为操作对象。
-
前向迭代器(forward iterator)
支持的操作:++、*(可以被复制或赋值)、使用 == 和 != 运算符进行比较。此外,两个前向迭代器可以互相赋值。 -
双向迭代器(bidirectional iterator)
支持的操作: 前向迭代器的全部功能,以及--。 -
随机访问迭代器(random access iterator)
随机访问迭代器具有双向迭代器的全部功能。除此之外,还支持随机访问操作p[i]、+或者-一个整数、两个随机访问迭代器相减。
3.4. 不同容器支持的迭代器类型
| 容器 | 迭代器类型 |
|---|---|
| array | 随机访问迭代器 |
| vector | 随机访问迭代器 |
| deque | 随机访问迭代器 |
| list | 双向迭代器 |
| set / multiset | 双向迭代器 |
| map / multimap | 双向迭代器 |
| forward_list | 前向迭代器 |
| unordered_map / unordered_multimap | 前向迭代器 |
| unordered_set / unordered_multiset | 前向迭代器 |
| stack | 不支持迭代器 |
| queue | 不支持迭代器 |
不是所有的容器都支持迭代器,支持迭代器的容器称为range。容器适配器 stack 和 queue 就没有迭代器,但是它们包含有一些成员函数,可以用来对元素进行访问。