时间: 2019 年 9 月 20 日 19:13
1. 头文件组成
C++ 标准中 STL 主要包含以下头文件(共 13 个):
<algorithm>, <functional>, <iterator>, <vector>, <list>, <map>, <queue>, <set>, <memory>, <numeric>, <utility> 等。
2. 算法部分
主要由以下头文件组成:
<algorithm><numeric><functional>
常用功能:
比较、交换、查找、遍历、复制、修改、移除、反转、排序、合并等。
3. 容器部分
主要由 <vector>, <list>, <deque>, <set>, <map>, <stack>, <queue> 等组成。具体特性如下表所示:
| 容器名称 | 英文标识 | 数据结构/特性描述 |
|---|---|---|
| 向量 | vector |
连续存储的元素 |
| 列表 | list |
由结点组成的双向链表,每个节点包含一个元素 |
| 双队列 | deque |
连续存储的指向不同元素的指针所组成的数组 |
| 集合 | set |
红黑树结构。结点间按谓词排列,无重复元素 |
| 多重集合 | multiset |
允许存在两个次序相等的元素的集合 |
| 栈 | stack |
LIFO (Last In First Out,后进先出) |
| 队列 | queue |
FIFO (First In First Out,先进先出) |
| 优先队列 | priority_queue |
元素的次序由作用于所储存值对上的某种谓词决定 |
| 映射 | map |
由 {key, value} 对组成的集合,按作用于 key 上的谓词排列 |
| 多重映射 | multimap |
允许键对由相等次序的映射 |
STL 容器使用手册
vector容器
vector 是 C++ STL 中的动态数组容器,在内存中连续存储元素。
- 支持随机访问,时间复杂度 O(1)
- 尾部插入/删除效率高,平均 O(1)
- 头部/中间插入删除效率低,O(n)
- 容量不足时自动扩容
头文件
#include <vector>
构造函数
vector<int> a; // 默认构造,空向量
vector<int> b(5, -1); // 5 个元素,初始值均为 -1
vector<int> c(b); // 拷贝构造
vector<int> d(b.begin(), b.begin() + 3); // 区间构造 [begin, end)
vector<int> e{1, 2, 3, 4, 5}; // 初始化列表构造 (C++11)
常用成员函数
元素访问
| 函数 | 说明 | 时间复杂度 |
|---|---|---|
at(idx) |
访问索引 idx 处元素,越界抛出异常 | O(1) |
operator[] |
访问索引 idx 处元素,不检查越界 | O(1) |
front() |
返回首元素引用 | O(1) |
back() |
返回尾元素引用 | O(1) |
data() |
返回底层数组指针 | O(1) |
迭代器
| 函数 | 说明 |
|---|---|
begin() / end() |
正向迭代器起始/末尾 |
rbegin() / rend() |
反向迭代器起始/末尾 |
cbegin() / cend() |
常量正向迭代器 |
容量管理
| 函数 | 说明 |
|---|---|
size() |
返回当前元素个数 |
capacity() |
返回当前分配的总容量 |
empty() |
判断是否为空 |
max_size() |
返回最大可容纳元素数 |
reserve(n) |
预分配容量,避免频繁扩容 |
resize(n) |
调整元素个数,新增元素默认初始化 |
resize(n, val) |
调整元素个数,新增元素用 val 初始化 |
修改操作
| 函数 | 说明 |
|---|---|
push_back(elem) |
尾部插入元素 |
pop_back() |
删除尾部元素 |
insert(pos, elem) |
在 pos 位置插入元素 |
insert(pos, n, elem) |
在 pos 位置插入 n 个 elem |
insert(pos, first, last) |
在 pos 位置插入区间元素 |
erase(pos) |
删除 pos 位置元素 |
erase(first, last) |
删除区间 [first, last) 元素 |
clear() |
清空所有元素 |
assign(first, last) |
用区间元素替换当前内容 |
assign(n, elem) |
用 n 个 elem 替换当前内容 |
swap(other) |
与另一个 vector 交换内容 |
使用案例
#include <vector>
#include <iostream>
using namespace std;
int main() {
// 创建与初始化
vector<int> vec(3, 10); // [10, 10, 10]
// 尾部操作
vec.push_back(20); // [10, 10, 10, 20]
vec.pop_back(); // [10, 10, 10]
// 访问元素
cout << vec[0] << endl; // 10,不检查越界
cout << vec.at(0) << endl; // 10,检查越界
// 遍历
for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " ";
}
// 范围遍历 (C++11)
for (const auto& val : vec) {
cout << val << " ";
}
return 0;
}
注意事项
- 区间操作统一采用左闭右开 [first, last) 规范
- 扩容时所有迭代器、指针、引用可能失效
- 在中间插入/删除元素会导致后续元素移动,效率较低
- 指针访问需使用 -> 操作符,如
ptr->at(0)而非ptr[0] - 优先使用栈对象,避免手动 new/delete
list容器
list 是双向链表容器,元素在内存中非连续存储。
- 支持双向遍历
- 任意位置插入/删除效率高,O(1)(已知位置)
- 不支持随机访问,访问元素需遍历,O(n)
- 插入删除操作不会使其他元素的迭代器失效
头文件
#include <list>
构造函数
list<int> a; // 默认构造,空链表
list<int> b(5, -1); // 5 个元素,初始值均为 -1
list<int> c(b); // 拷贝构造
list<int> d(b.begin(), b.begin() + 3); // 区间构造
list<int> e{1, 2, 3, 4, 5}; // 初始化列表构造
常用成员函数
元素访问
| 函数 | 说明 |
|---|---|
front() |
返回首元素引用 |
back() |
返回尾元素引用 |
迭代器
| 函数 | 说明 |
|---|---|
begin() / end() |
正向迭代器 |
rbegin() / rend() |
反向迭代器 |
容量管理
| 函数 | 说明 |
|---|---|
size() |
返回元素个数 |
empty() |
判断是否为空 |
max_size() |
返回最大可容纳元素数 |
resize(n) |
调整元素个数 |
resize(n, val) |
调整元素个数,新增元素用 val 初始化 |
修改操作
| 函数 | 说明 |
|---|---|
push_front(elem) |
头部插入元素 |
push_back(elem) |
尾部插入元素 |
pop_front() |
删除头部元素 |
pop_back() |
删除尾部元素 |
insert(pos, elem) |
在 pos 位置插入元素 |
erase(pos) |
删除 pos 位置元素 |
erase(first, last) |
删除区间元素 |
clear() |
清空所有元素 |
assign(first, last) |
用区间元素替换内容 |
assign(n, elem) |
用 n 个 elem 替换内容 |
remove(val) |
删除所有值为 val 的元素 |
remove_if(pred) |
删除满足谓词的元素 |
unique() |
删除相邻重复元素 |
merge(other) |
合并另一个有序链表 |
sort() |
对链表排序 |
reverse() |
反转链表 |
swap(other) |
交换内容 |
使用案例
#include <list>
#include <iostream>
using namespace std;
int main() {
list<int> lst;
// 头尾插入
lst.push_back(10);
lst.push_front(5); // [5, 10]
// 遍历
for (auto it = lst.begin(); it != lst.end(); ++it) {
cout << *it << " ";
}
// 删除指定值
lst.remove(10); // [5]
// 排序
lst.push_back(3);
lst.push_back(8); // [5, 3, 8]
lst.sort(); // [3, 5, 8]
// 反转
lst.reverse(); // [8, 5, 3]
return 0;
}
注意事项
- list 不支持随机访问,不能使用
operator[]或at() - 插入/删除操作不会使其他元素的迭代器失效(被删除元素除外)
- sort() 和 merge() 要求元素可比较,merge() 要求两个链表均已排序
- 内存开销较大,每个元素需额外存储前后指针
deque容器
deque(double-ended queue)是双端队列容器,支持两端高效插入删除。
- 支持随机访问,时间复杂度 O(1)
- 头部/尾部插入删除效率高,平均 O(1)
- 内存分段连续存储,非完全连续
- 中间插入删除效率较低,O(n)
头文件
#include <deque>
构造函数
deque<int> a; // 默认构造
deque<int> b(5, -1); // 5 个元素,初始值 -1
deque<int> c(b); // 拷贝构造
deque<int> d(b.begin(), b.begin() + 3); // 区间构造
deque<int> e{1, 2, 3, 4, 5}; // 初始化列表
常用成员函数
元素访问
| 函数 | 说明 |
|---|---|
at(idx) |
访问索引 idx 处元素,检查越界 |
operator[] |
访问索引 idx 处元素,不检查越界 |
front() |
返回首元素引用 |
back() |
返回尾元素引用 |
迭代器
| 函数 | 说明 |
|---|---|
begin() / end() |
正向迭代器 |
rbegin() / rend() |
反向迭代器 |
容量管理
| 函数 | 说明 |
|---|---|
size() |
返回元素个数 |
empty() |
判断是否为空 |
max_size() |
返回最大可容纳元素数 |
resize(n) |
调整元素个数 |
resize(n, val) |
调整元素个数,新增元素用 val 初始化 |
修改操作
| 函数 | 说明 |
|---|---|
push_front(elem) |
头部插入元素 |
push_back(elem) |
尾部插入元素 |
pop_front() |
删除头部元素 |
pop_back() |
删除尾部元素 |
insert(pos, elem) |
在 pos 位置插入元素 |
erase(pos) |
删除 pos 位置元素 |
erase(first, last) |
删除区间元素 |
clear() |
清空所有元素 |
assign(first, last) |
用区间元素替换内容 |
assign(n, elem) |
用 n 个 elem 替换内容 |
使用案例
#include <deque>
#include <iostream>
using namespace std;
int main() {
deque<int> dq;
// 两端插入
dq.push_back(10);
dq.push_front(5); // [5, 10]
// 随机访问
cout << dq[0] << endl; // 5
cout << dq.at(1) << endl; // 10
// 两端删除
dq.pop_front(); // [10]
dq.pop_back(); // []
return 0;
}
注意事项
- deque 支持随机访问,但迭代器失效规则比 vector 复杂
- 在中间插入/删除元素可能导致分段内存重新分配
- 不需要随机访问且只需两端操作时,deque 比 vector 更合适
set容器
set 是基于红黑树实现的有序集合容器。
- 元素自动排序,默认升序
- 元素唯一,不允许重复
- 插入/删除/查找时间复杂度 O(log n)
- 迭代器为双向迭代器,不支持随机访问
头文件
#include <set>
构造函数
set<int> a; // 默认构造
set<int> b{3, 1, 4, 1, 5}; // 初始化列表,自动去重排序 [1, 3, 4, 5]
set<int> c(b); // 拷贝构造
set<int> d(b.begin(), b.end()); // 区间构造
// 自定义比较函数(降序)
struct Compare {
bool operator()(int a, int b) const { return a > b; }
};
set<int, Compare> e; // 降序集合
常用成员函数
元素访问与查找
| 函数 | 说明 | 时间复杂度 |
|---|---|---|
find(val) |
查找值为 val 的元素,返回迭代器 | O(log n) |
count(val) |
返回值为 val 的元素个数(0 或 1) | O(log n) |
lower_bound(val) |
返回第一个 >= val 的元素迭代器 | O(log n) |
upper_bound(val) |
返回第一个 > val 的元素迭代器 | O(log n) |
equal_range(val) |
返回 [lower_bound, upper_bound) 范围 | O(log n) |
迭代器
| 函数 | 说明 |
|---|---|
begin() / end() |
正向迭代器(按排序顺序) |
rbegin() / rend() |
反向迭代器 |
容量管理
| 函数 | 说明 |
|---|---|
size() |
返回元素个数 |
empty() |
判断是否为空 |
max_size() |
返回最大可容纳元素数 |
修改操作
| 函数 | 说明 |
|---|---|
insert(val) |
插入元素,返回 pair |
insert(first, last) |
插入区间元素 |
erase(val) |
删除值为 val 的元素,返回删除个数 |
erase(pos) |
删除 pos 位置元素 |
erase(first, last) |
删除区间元素 |
clear() |
清空所有元素 |
swap(other) |
交换内容 |
使用案例
#include <set>
#include <iostream>
using namespace std;
int main() {
set<int> s;
// 插入(自动排序去重)
s.insert(30);
s.insert(10);
s.insert(20);
s.insert(10); // 重复,不会插入
// 遍历(有序输出:10 20 30)
for (const auto& val : s) {
cout << val << " ";
}
// 查找
if (s.find(20) != s.end()) {
cout << "Found 20" << endl;
}
// 删除
s.erase(10); // 删除值为 10 的元素
s.count(10); // 返回 0
return 0;
}
注意事项
- set 中的元素为常量,不能通过迭代器修改元素值
- 元素类型必须支持比较操作(默认使用 < 运算符)
- 需要自定义排序时,可通过模板参数传入比较函数或函数对象
- 迭代器在元素删除后可能失效,需谨慎使用
multiset容器
multiset 是基于红黑树实现的有序多重集合容器。
- 元素自动排序,默认升序
- 允许重复元素
- 插入/删除/查找时间复杂度 O(log n)
- 迭代器为双向迭代器,不支持随机访问
头文件
#include <set>
构造函数
multiset<int> a; // 默认构造
multiset<int> b{3, 1, 4, 1, 5}; // [1, 1, 3, 4, 5],允许重复
multiset<int> c(b); // 拷贝构造
multiset<int> d(b.begin(), b.end()); // 区间构造
常用成员函数
元素访问与查找
| 函数 | 说明 | 时间复杂度 |
|---|---|---|
find(val) |
查找值为 val 的元素,返回任意一个匹配迭代器 | O(log n) |
count(val) |
返回值为 val 的元素个数 | O(log n + k),k 为匹配数 |
lower_bound(val) |
返回第一个 >= val 的元素迭代器 | O(log n) |
upper_bound(val) |
返回第一个 > val 的元素迭代器 | O(log n) |
equal_range(val) |
返回所有值为 val 的元素范围 [first, last) | O(log n + k) |
迭代器
| 函数 | 说明 |
|---|---|
begin() / end() |
正向迭代器 |
rbegin() / rend() |
反向迭代器 |
容量管理
| 函数 | 说明 |
|---|---|
size() |
返回元素个数(含重复) |
empty() |
判断是否为空 |
max_size() |
返回最大可容纳元素数 |
修改操作
| 函数 | 说明 |
|---|---|
insert(val) |
插入元素,返回指向新元素的迭代器 |
insert(first, last) |
插入区间元素 |
erase(val) |
删除所有值为 val 的元素,返回删除个数 |
erase(pos) |
删除 pos 位置单个元素 |
erase(first, last) |
删除区间元素 |
clear() |
清空所有元素 |
使用案例
#include <set>
#include <iostream>
using namespace std;
int main() {
multiset<int> ms;
// 插入(允许重复)
ms.insert(10);
ms.insert(20);
ms.insert(10); // 重复,正常插入
// 遍历(输出:10 10 20)
for (const auto& val : ms) {
cout << val << " ";
}
// 统计个数
cout << ms.count(10); // 输出 2
// 获取所有相同值的范围
auto range = ms.equal_range(10);
for (auto it = range.first; it != range.second; ++it) {
cout << *it << " "; // 输出两个 10
}
// 删除指定值的所有元素
ms.erase(10); // 删除所有 10
return 0;
}
注意事项
- multiset 中的元素为常量,不能通过迭代器修改元素值
- count() 可能返回大于 1 的值,表示重复元素个数
- erase(val) 会删除所有匹配元素,erase(pos) 只删除单个元素
- 需要精确控制删除单个重复元素时,应使用迭代器版本
stack容器
stack 是适配器容器,基于其他容器(默认 deque)实现后进先出(LIFO)结构。
- 只能访问/操作栈顶元素
- 插入删除均在栈顶,时间复杂度 O(1)
- 不支持遍历,不提供迭代器
头文件
#include <stack>
构造函数
stack<int> a; // 默认构造,底层使用 deque
stack<int, vector<int>> b; // 指定底层容器为 vector
stack<int, list<int>> c; // 指定底层容器为 list
// 用现有容器初始化
vector<int> vec{1, 2, 3};
stack<int> d(vec); // 栈顶为 3
常用成员函数
| 函数 | 说明 | 时间复杂度 |
|---|---|---|
push(elem) |
元素入栈 | O(1) |
pop() |
栈顶元素出栈,无返回值 | O(1) |
top() |
返回栈顶元素引用 | O(1) |
empty() |
判断栈是否为空 | O(1) |
size() |
返回元素个数 | O(1) |
使用案例
#include <stack>
#include <iostream>
using namespace std;
int main() {
stack<int> s;
// 入栈
s.push(10);
s.push(20);
s.push(30); // 栈顶为 30
// 访问栈顶
cout << s.top() << endl; // 30
// 出栈
s.pop(); // 移除 30
cout << s.top() << endl; // 20
// 遍历栈(会破坏栈结构)
while (!s.empty()) {
cout << s.top() << " ";
s.pop();
}
// 输出:20 10
return 0;
}
注意事项
- stack 是容器适配器,不提供迭代器,无法遍历
- pop() 不返回元素值,需先调用 top() 获取
- 底层容器可自定义,需支持 back()/push_back()/pop_back() 操作
- 默认使用 deque 作为底层容器,兼顾两端操作效率
queue容器
queue 是适配器容器,基于其他容器(默认 deque)实现先进先出(FIFO)结构。
- 只能访问队首/队尾元素
- 插入在队尾,删除在队首,时间复杂度 O(1)
- 不支持随机访问,不提供迭代器
头文件
#include <queue>
构造函数
queue<int> a; // 默认构造,底层使用 deque
queue<int, list<int>> b; // 指定底层容器为 list
// 用现有容器初始化
list<int> lst{1, 2, 3};
queue<int> c(lst); // 队首为 1,队尾为 3
常用成员函数
| 函数 | 说明 | 时间复杂度 |
|---|---|---|
push(elem) |
元素入队(队尾) | O(1) |
pop() |
队首元素出队,无返回值 | O(1) |
front() |
返回队首元素引用 | O(1) |
back() |
返回队尾元素引用 | O(1) |
empty() |
判断队列是否为空 | O(1) |
size() |
返回元素个数 | O(1) |
使用案例
#include <queue>
#include <iostream>
using namespace std;
int main() {
queue<int> q;
// 入队
q.push(10);
q.push(20);
q.push(30); // 队首 10,队尾 30
// 访问
cout << q.front() << endl; // 10
cout << q.back() << endl; // 30
// 出队
q.pop(); // 移除 10
cout << q.front() << endl; // 20
// 遍历队列(会破坏队列结构)
while (!q.empty()) {
cout << q.front() << " ";
q.pop();
}
// 输出:20 30
return 0;
}
注意事项
- queue 是容器适配器,不提供迭代器,无法遍历
- pop() 不返回元素值,需先调用 front() 获取
- 底层容器需支持 front()/back()/push_back()/pop_front() 操作
- 默认使用 deque,list 也可作为底层容器
priority_queue容器
priority_queue 是适配器容器,基于堆结构实现的优先队列。
- 元素按优先级排列,默认大顶堆(最大值在顶部)
- 只能访问优先级最高的元素(队首)
- 插入/删除时间复杂度 O(log n),访问队首 O(1)
- 不支持遍历,不提供迭代器
头文件
#include <queue>
构造函数
// 默认构造,大顶堆(使用 less,最大值优先)
priority_queue<int> a;
// 小顶堆(使用 greater,最小值优先)
priority_queue<int, vector<int>, greater<int>> b;
// 自定义比较函数
struct Compare {
bool operator()(int a, int b) const { return a > b; } // 小顶堆
};
priority_queue<int, vector<int>, Compare> c;
// 用区间初始化
vector<int> vec{3, 1, 4, 1, 5};
priority_queue<int> d(vec.begin(), vec.end());
常用成员函数
| 函数 | 说明 | 时间复杂度 |
|---|---|---|
push(elem) |
元素入队 | O(log n) |
pop() |
移除队首元素,无返回值 | O(log n) |
top() |
返回队首元素引用(优先级最高) | O(1) |
empty() |
判断是否为空 | O(1) |
size() |
返回元素个数 | O(1) |
使用案例
#include <queue>
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 大顶堆(默认)
priority_queue<int> max_heap;
max_heap.push(10);
max_heap.push(30);
max_heap.push(20);
cout << max_heap.top() << endl; // 30
max_heap.pop();
cout << max_heap.top() << endl; // 20
// 小顶堆
priority_queue<int, vector<int>, greater<int>> min_heap;
min_heap.push(10);
min_heap.push(30);
min_heap.push(20);
cout << min_heap.top() << endl; // 10
// 遍历优先队列(会破坏结构)
while (!max_heap.empty()) {
cout << max_heap.top() << " ";
max_heap.pop();
}
// 输出:30 20 10(降序)
return 0;
}
注意事项
- priority_queue 是容器适配器,底层默认使用 vector
- 比较函数定义的是"优先级低"的条件:less 表示 a<b 时 a 优先级低(大顶堆)
- 不支持修改已入队元素的优先级,需重新插入
- 无法遍历或访问非队首元素
map容器
map 是基于红黑树实现的有序关联容器,存储键值对 (key-value)。
- 元素按 key 自动排序,默认升序
- key 唯一,不允许重复
- 插入/删除/查找时间复杂度 O(log n)
- 迭代器为双向迭代器,指向 pair<const Key, Value>
头文件
#include <map>
构造函数
map<string, int> a; // 默认构造
map<string, int> b{{"a", 1}, {"b", 2}}; // 初始化列表
map<string, int> c(b); // 拷贝构造
map<string, int> d(b.begin(), b.end()); // 区间构造
// 自定义比较函数(按 key 降序)
struct Compare {
bool operator()(const string& a, const string& b) const {
return a > b;
}
};
map<string, int, Compare> e;
常用成员函数
元素访问与查找
| 函数 | 说明 | 时间复杂度 |
|---|---|---|
operator[](key) |
访问或插入 key,返回 value 引用 | O(log n) |
at(key) |
访问 key 对应的 value,越界抛出异常 | O(log n) |
find(key) |
查找 key,返回迭代器 | O(log n) |
count(key) |
返回 key 的个数(0 或 1) | O(log n) |
lower_bound(key) |
返回第一个 key >= 给定值的迭代器 | O(log n) |
upper_bound(key) |
返回第一个 key > 给定值的迭代器 | O(log n) |
迭代器
| 函数 | 说明 |
|---|---|
begin() / end() |
正向迭代器(按 key 排序) |
rbegin() / rend() |
反向迭代器 |
容量管理
| 函数 | 说明 |
|---|---|
size() |
返回元素个数 |
empty() |
判断是否为空 |
max_size() |
返回最大可容纳元素数 |
修改操作
| 函数 | 说明 |
|---|---|
insert(pair) |
插入键值对,返回 pair |
insert_or_assign(key, val) |
插入或更新,C++17 |
erase(key) |
删除指定 key,返回删除个数 |
erase(pos) |
删除 pos 位置元素 |
erase(first, last) |
删除区间元素 |
clear() |
清空所有元素 |
使用案例
#include <map>
#include <iostream>
#include <string>
using namespace std;
int main() {
map<string, int> score;
// 插入元素
score["Alice"] = 90;
score["Bob"] = 85;
score.insert({"Charlie", 95});
// 访问元素
cout << score["Alice"] << endl; // 90,不存在时会自动插入
cout << score.at("Bob") << endl; // 85,不存在时抛出异常
// 遍历(按 key 升序)
for (const auto& pair : score) {
cout << pair.first << ": " << pair.second << endl;
}
// 查找
auto it = score.find("Bob");
if (it != score.end()) {
cout << "Found: " << it->second << endl;
}
// 删除
score.erase("Alice"); // 按 key 删除
score.erase(score.begin()); // 按迭代器删除
return 0;
}
注意事项
- operator[] 在 key 不存在时会自动插入默认值,注意副作用
- 访问不存在的 key 时,at() 抛出异常,operator[] 插入默认值
- map 的 value 可通过迭代器修改,但 key 为 const,不可修改
- 需要频繁查找且不要求有序时,可考虑使用 unordered_map
multimap容器
multimap 是基于红黑树实现的有序多重关联容器,存储键值对。
- 元素按 key 自动排序,默认升序
- 允许重复的 key
- 插入/删除/查找时间复杂度 O(log n)
- 迭代器为双向迭代器,指向 pair<const Key, Value>
头文件
#include <map>
构造函数
multimap<string, int> a; // 默认构造
multimap<string, int> b{{"a", 1}, {"a", 2}, {"b", 3}}; // 允许重复 key
multimap<string, int> c(b); // 拷贝构造
multimap<string, int> d(b.begin(), b.end()); // 区间构造
常用成员函数
元素访问与查找
| 函数 | 说明 | 时间复杂度 |
|---|---|---|
find(key) |
查找 key,返回任意一个匹配迭代器 | O(log n) |
count(key) |
返回 key 的个数(可能 >1) | O(log n + k) |
lower_bound(key) |
返回第一个 key >= 给定值的迭代器 | O(log n) |
upper_bound(key) |
返回第一个 key > 给定值的迭代器 | O(log n) |
equal_range(key) |
返回所有匹配 key 的范围 [first, last) | O(log n + k) |
迭代器
| 函数 | 说明 |
|---|---|
begin() / end() |
正向迭代器 |
rbegin() / rend() |
反向迭代器 |
容量管理
| 函数 | 说明 |
|---|---|
size() |
返回元素个数(含重复 key) |
empty() |
判断是否为空 |
max_size() |
返回最大可容纳元素数 |
修改操作
| 函数 | 说明 |
|---|---|
insert(pair) |
插入键值对,返回指向新元素的迭代器 |
erase(key) |
删除所有匹配 key 的元素,返回删除个数 |
erase(pos) |
删除 pos 位置单个元素 |
erase(first, last) |
删除区间元素 |
clear() |
清空所有元素 |
使用案例
#include <map>
#include <iostream>
#include <string>
using namespace std;
int main() {
multimap<string, int> mm;
// 插入(允许重复 key)
mm.insert({"Alice", 90});
mm.insert({"Alice", 95}); // 相同 key,不同 value
mm.insert({"Bob", 85});
// 遍历(按 key 排序,相同 key 按插入顺序)
for (const auto& pair : mm) {
cout << pair.first << ": " << pair.second << endl;
}
// 输出:
// Alice: 90
// Alice: 95
// Bob: 85
// 统计相同 key 的个数
cout << mm.count("Alice") << endl; // 2
// 获取所有相同 key 的范围
auto range = mm.equal_range("Alice");
for (auto it = range.first; it != range.second; ++it) {
cout << it->second << " "; // 90 95
}
// 删除指定 key 的所有元素
mm.erase("Alice"); // 删除所有 Alice 的记录
return 0;
}
注意事项
- multimap 不支持 operator[] 和 at(),因为 key 可能对应多个 value
- count() 可能返回大于 1 的值,表示相同 key 的元素个数
- erase(key) 会删除所有匹配元素,erase(pos) 只删除单个元素
- 需要精确控制删除单个重复 key 时,应使用迭代器版本
通用注意事项
- 区间规范:STL 中区间操作统一采用左闭右开 [first, last) 原则
- 迭代器失效:
- vector:扩容、中间插入删除可能导致迭代器失效
- list:仅被删除元素的迭代器失效
- 关联容器:仅被删除元素的迭代器失效
- 内存管理:优先使用栈对象,避免手动 new/delete;必要时使用智能指针
- 异常安全:at() 等函数可能抛出异常,需根据场景选择使用
- 性能考量:
- 频繁随机访问:vector/deque
- 频繁中间插入删除:list
- 频繁查找/要求有序:set/map
- 频繁查找/不要求有序:unordered_set/unordered_map(C++11)
注:本手册基于 C++98/03 标准,C++11 及以后版本新增了更多特性(如初始化列表、auto、范围遍历等),建议结合最新标准使用。