C++ 标准库(STL,Standard Template Library)提供了一系列容器,这些容器被划分为三大类:顺序容器、有序容器(关联容器)和无序容器(散列容器)。
一、顺序容器
顺序容器用于线性存储数据,主要包含连续存储和链式存储两种方式。
1. 连续存储容器
这些容器在内存中是连续排列的,支持快速随机访问,但插入和删除操作效率较低。
-
array
(静态数组)
特点:- 长度固定,无法动态扩展。
- 存储在栈中,开销低。
- 支持随机访问,查找效率高。
示例代码:
#include <array> #include <iostream> using namespace std; int main() { array<int, 5> arr = {1, 2, 3, 4, 5}; for (int i = 0; i < arr.size(); ++i) { cout << arr[i] << " "; } return 0; }
-
vector
(动态数组)
特点:- 支持动态扩展,必要时自动重新分配内存。
- 插入元素通常只能在尾部(
push_back
),中间插入效率低。 - 动态扩展时会有重新分配内存的开销。
示例代码:
#include <vector> #include <iostream> using namespace std; int main() { vector<int> vec = {1, 2, 3}; vec.push_back(4); // 在尾部插入 for (int v : vec) { cout << v << " "; } return 0; }
-
deque
(双端队列)
特点:- 支持在头部和尾部高效插入和删除操作。
- 动态扩展,不需要像
vector
一样频繁拷贝内存。
示例代码:
#include <deque> #include <iostream> using namespace std; int main() { deque<int> dq = {1, 2, 3}; dq.push_front(0); // 在头部插入 dq.push_back(4); // 在尾部插入 for (int v : dq) { cout << v << " "; } return 0; }
2. 链式存储容器
这些容器使用指针连接元素,存储位置不连续,插入和删除效率高,但查找效率低。
-
list
(双向链表)
特点:- 任意位置插入和删除效率高。
- 不支持随机访问,需要遍历。
示例代码:
#include <list> #include <iostream> using namespace std; int main() { list<int> lst = {1, 2, 3}; lst.push_back(4); // 在尾部插入 lst.push_front(0); // 在头部插入 for (int v : lst) { cout << v << " "; } return 0; }
-
forward_list
(单向链表)
特点:- 单向遍历,只能从头到尾。
- 更适合占用内存较小的场景。
二、关联容器
关联容器基于红黑树结构实现,分为有序容器和无序容器。关联容器中的元素有键值对的概念,操作时需定义比较函数或散列函数。
1. 有序容器
有序容器会对键值自动排序,插入和删除的代价较高,但查找效率较高(对数时间复杂度)。
-
set
/multiset
(集合)
特点:set
中元素不能重复,multiset
中允许重复元素。- 元素会自动排序。
示例代码:
#include <set> #include <iostream> using namespace std; int main() { set<int> s = {3, 1, 4}; s.insert(2); // 插入元素 for (int v : s) { cout << v << " "; // 输出为:1 2 3 4 } return 0; }
-
map
/multimap
(关联数组/字典)
特点:map
中键值唯一,multimap
中键值可以重复。- 按键排序,支持高效查找。
示例代码:
#include <map> #include <iostream> using namespace std; int main() { map<string, int> m; m["apple"] = 3; m["banana"] = 5; for (auto &[key, value] : m) { cout << key << ": " << value << endl; } return 0; }
2. 无序容器
无序容器基于**散列表(哈希表)**实现,支持高效的插入和查找操作(常数时间复杂度)。
-
unordered_set
/unordered_multiset
示例代码:#include <unordered_set> #include <iostream> using namespace std; int main() { unordered_set<int> us = {1, 2, 3}; us.insert(4); // 插入元素 for (int v : us) { cout << v << " "; // 输出顺序可能是随机的 } return 0; }
-
unordered_map
/unordered_multimap
示例代码:#include <unordered_map> #include <iostream> using namespace std; int main() { unordered_map<string, int> um; um["apple"] = 3; um["banana"] = 5; for (auto &[key, value] : um) { cout << key << ": " << value << endl; // 顺序可能是随机的 } return 0; }
三、容器选择建议
-
优先选择
array
和vector
:- 速度快,内存开销低。
-
插入和删除频繁时,选择
list
或deque
。 -
需要排序的场景:选择
set
或map
。 -
无需排序且查找频繁:选择
unordered_set
或unordered_map
。
四、注意事项
-
自定义比较函数:
对于有序容器,需要定义比较规则。例如:set<int, greater<int>> s = {1, 2, 3}; // 降序排列
-
散列函数:
对于无序容器,可自定义哈希函数。例如:struct MyHash { size_t operator()(const int &key) const { return key % 10; } }; unordered_map<int, string, MyHash> um;