常用数据结构和函数

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少),复杂场景再手动实现。熟练掌握上述工具,能显著减少编码量,提升解题效率。建议结合实际题目多练习,形成肌肉记忆。

posted @ 2025-09-07 01:47  .N1nEmAn  阅读(26)  评论(0)    收藏  举报