常用数据结构和函数
C++标准库机考高频工具速查:示例与复杂度指南
在机考中,熟练运用C++标准库工具能大幅提升编码效率。本文整理了高频算法函数、数据结构及实用技巧,附简洁示例和复杂度分析,方便快速查阅。
一、核心算法函数(为主)
1. 全排列生成:next_permutation / prev_permutation
功能:生成字典序下一个/上一个全排列(原地修改,无则返回false)
复杂度:O(n)
示例:
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1, 2, 3};
// 生成所有全排列(需先排序初始状态)
sort(v.begin(), v.end());
do {
for (int x : v) cout << x << " ";
cout << endl;
} while (next_permutation(v.begin(), v.end()));
return 0;
}
应用:全排列枚举、字典序问题
2. 排序:sort
功能:对区间排序(默认升序,可自定义比较器)
复杂度:O(n log n)
示例:
#include <algorithm>
#include <vector>
// 降序排序
sort(v.begin(), v.end(), greater<int>());
// 自定义结构体排序
struct Node { int x, y; };
sort(v.begin(), v.end(), [](const Node& a, const Node& b) {
return a.x < b.x; // 按x升序
});
应用:预处理排序(二分前必备)、结果排序
3. 反转:reverse
功能:反转区间元素顺序
复杂度:O(n)
示例:
#include <algorithm>
string s = "abcde";
reverse(s.begin(), s.end()); // s变为"edcba"
vector<int> v = {1,2,3};
reverse(v.begin(), v.end()); // v变为{3,2,1}
应用:回文判断、反转字符串/数组
4. 去重:unique + erase
功能:移除相邻重复元素(需先排序)
复杂度:O(n)(整体,排序占O(n log n))
示例:
#include <algorithm>
vector<int> v = {2, 1, 2, 3, 3, 3};
sort(v.begin(), v.end()); // 先排序:{1,2,2,3,3,3}
// unique移走重复元素,返回新尾后迭代器
auto last = unique(v.begin(), v.end());
v.erase(last, v.end()); // 擦除冗余:v变为{1,2,3}
应用:统计不同元素数量、去重处理
5. 二分查找:lower_bound / upper_bound
功能:在有序区间找第一个≥目标/第一个>目标的位置
复杂度:O(log n)
示例:
#include <algorithm>
vector<int> v = {1, 3, 3, 5, 7}; // 必须有序
// 找第一个≥4的位置(返回5的迭代器,索引3)
auto it1 = lower_bound(v.begin(), v.end(), 4);
// 找第一个>3的位置(返回5的迭代器,索引3)
auto it2 = upper_bound(v.begin(), v.end(), 3);
// 统计[2,4)范围内的元素数量
int cnt = upper_bound(v.begin(), v.end(), 3) - lower_bound(v.begin(), v.end(), 2);
应用:插入位置计算、范围查询、计数
6. 累加:accumulate
功能:聚合区间元素(求和、积等)
复杂度:O(n)
示例:
#include <numeric>
vector<int> v = {1, 2, 3, 4};
// 求和(初始值0)
int sum = accumulate(v.begin(), v.end(), 0);
// 求积(初始值1)
int product = accumulate(v.begin(), v.end(), 1, [](int a, int b) {
return a * b;
});
// 拼接字符串
vector<string> strs = {"a", "b", "c"};
string s = accumulate(strs.begin(), strs.end(), string(""));
应用:快速求和/积、字符串拼接
7. 批量判断:all_of / any_of / none_of
功能:检查区间元素是否全满足/至少一个满足/全不满足条件
复杂度:O(n)
示例:
#include <algorithm>
vector<int> v = {2,4,6,8};
// 是否全为偶数
bool all_even = all_of(v.begin(), v.end(), [](int x) { return x%2 == 0; });
// 是否存在>5的元素
bool has_large = any_of(v.begin(), v.end(), [](int x) { return x > 5; });
// 是否全不为负数
bool no_negative = none_of(v.begin(), v.end(), [](int x) { return x < 0; });
应用:批量校验(如输入合法性检查)
8. 其他实用函数
| 函数 | 示例 | 复杂度 | 应用场景 |
|---|---|---|---|
swap_ranges |
swap_ranges(a.begin(), a.end(), b.begin()) |
O(n) | 交换两个等长区间 |
find |
find(v.begin(), v.end(), 5) != v.end() |
O(n) | 无序区间查找元素 |
count |
count(v.begin(), v.end(), 3) |
O(n) | 统计元素出现次数 |
max_element |
*max_element(v.begin(), v.end()) |
O(n) | 找最大值(min_element类似) |
nth_element |
nth_element(v.begin(), v.begin()+k, v.end()) |
O(n)(平均) | 找第k小元素(0-based) |
二、高频数据结构及特性
1. vector(动态数组)
特性:随机访问快,尾部增删高效
复杂度:尾部增删O(1),中间增删O(n),查找O(n)
示例:
#include <vector>
vector<int> v;
v.push_back(1); // 尾部插入
v.emplace_back(2); // 更高效的尾部插入
int x = v[0]; // 随机访问
v.erase(v.begin() + 1); // 删除中间元素(O(n))
应用:存储序列、模拟数组、临时缓存
2. queue(队列)
特性:FIFO(先进先出),仅访问头尾
复杂度:入队/出队O(1)
示例:
#include <queue>
queue<int> q;
q.push(1); // 入队
q.pop(); // 出队(首元素)
int front = q.front(); // 访问队首
应用:BFS、层次遍历、滑动窗口辅助
3. stack(栈)
特性:LIFO(后进先出),仅访问栈顶
复杂度:入栈/出栈O(1)
示例:
#include <stack>
stack<int> s;
s.push(1); // 入栈
s.pop(); // 出栈(栈顶)
int top = s.top(); // 访问栈顶
应用:括号匹配、单调栈(找前后更大元素)
4. priority_queue(优先队列)
特性:默认大根堆(可改为小根堆),每次弹出极值
复杂度:插入/弹出O(log n),查顶O(1)
示例:
#include <queue>
// 大根堆(默认)
priority_queue<int> max_heap;
// 小根堆(需指定容器和比较器)
priority_queue<int, vector<int>, greater<int>> min_heap;
max_heap.push(3);
max_heap.push(1);
max_heap.push(2);
while (!max_heap.empty()) {
cout << max_heap.top() << " "; // 输出3 2 1
max_heap.pop();
}
应用:TopK问题、堆排序、贪心算法
5. 哈希容器:unordered_map / unordered_set
特性:无序,哈希表实现,键/元素唯一
复杂度:增删查O(1)(平均),O(n)(最坏)
示例:
#include <unordered_map>
#include <unordered_set>
// 统计频率
unordered_map<int, int> freq;
freq[3]++; // 键3的频率+1
// 去重/存在性判断
unordered_set<int> s;
s.insert(5);
if (s.count(5)) { /* 存在5 */ }
应用:频率统计、快速去重、哈希映射
6. 有序容器:map / set
特性:红黑树实现,自动排序(默认升序)
复杂度:增删查O(log n)
示例:
#include <map>
#include <set>
// 有序映射(按键排序)
map<int, string> m;
m[2] = "b";
m[1] = "a"; // 自动按key升序:{1:"a", 2:"b"}
// 有序集合(元素排序)
set<int> s = {3,1,2}; // 自动排序为{1,2,3}
// 找第一个≥2的元素
auto it = s.lower_bound(2);
应用:有序映射、范围查询、二分查找
7. string(字符串)
特性:动态字符数组,支持丰富操作
示例:
#include <string>
string s = "hello";
s += " world"; // 拼接:"hello world"
string sub = s.substr(6, 5); // 从索引6取5个字符:"world"
size_t pos = s.find("llo"); // 查找子串,返回2(未找到返回string::npos)
应用:所有字符串处理场景(分割、匹配、替换)
8. deque(双端队列)
特性:双端增删高效,支持随机访问
复杂度:两端增删O(1),中间O(n)
示例:
#include <deque>
deque<int> dq;
dq.push_back(1); // 尾插
dq.push_front(0); // 头插
dq.pop_back(); // 尾删
dq.pop_front(); // 头删
应用:实现队列/栈、滑动窗口(需两端操作)
三、机考额外实用技巧
1. 字符串处理
#include <cctype>
char c = 'a';
bool is_digit = isdigit(c); // 是否数字
char upper_c = toupper(c); // 转大写('A')
string s = "abc123";
// 截取子串:pos=3,长度3 → "123"
string num = s.substr(3, 3);
// 查找子串,从pos=0开始
size_t pos = s.find("bc", 0);
2. 位运算工具:bitset
功能:固定大小位集合,高效位运算
复杂度:O(N/64)(按机器字长优化)
示例:
#include <bitset>
bitset<10> bs; // 10位的位集合(初始全0)
bs.set(2); // 第2位置1
bs.reset(2); // 第2位置0
bool is_set = bs.test(2); // 检查第2位是否为1
bitset<10> bs2 = bs << 1; // 左移1位
应用:状态压缩(如表示集合、二进制状态)
3. pair / tuple
#include <utility>
#include <tuple>
// 存储坐标
pair<int, int> pos = {3, 4};
int x = pos.first, y = pos.second;
// 存储多值
tuple<int, string, double> data = {1, "a", 3.14};
int id = get<0>(data);
string name = get<1>(data);
4. 自定义比较器
// 排序降序
sort(v.begin(), v.end(), greater<int>());
// 优先队列小根堆
priority_queue<int, vector<int>, greater<int>> min_heap;
// 自定义结构体比较
struct Node { int x, y; };
sort(v.begin(), v.end(), [](const Node& a, const Node& b) {
return a.x != b.x ? a.x < b.x : a.y > b.y; // 按x升序,x相同则y降序
});
5. 边界处理
#include <climits>
int max_val = INT_MAX; // 最大整数(2^31-1)
int min_val = INT_MIN; // 最小整数(-2^31)
// 初始化最小值时用INT_MIN,避免溢出
int res = INT_MIN;
总结
机考中优先使用标准库工具(优化充分、bug少),复杂场景再手动实现。熟练掌握上述工具,能显著减少编码量,提升解题效率。建议结合实际题目多练习,形成肌肉记忆。
浙公网安备 33010602011771号