STL 是什么:竞赛选手的"军火库"
上一篇我们用数组手撸了栈、队列和链表。实际竞赛里,没人这么干——因为 C++ 标准库 STL 已经把这些结构都实现好了,而且是经过千锤百炼的优化版。你只要 `#include` 一下,就能直接用。
STL = Standard Template Library,标准模板库。它是 C++ 自带的一套"工具包",里面有各种常用容器和算法。竞赛里 80% 的数据结构需求,STL 都能直接满足。
会用 STL,竞赛代码量直接减半。
- vector动态数组,自动扩容。
- stack/queue现成的栈和队列。
- sort一行排序,比手写快十倍。
- pair把两个数打包成一个。
vector:会自动扩容的动态数组
普通数组大小固定,开小了不够用,开大了浪费内存。vector 解决了这个问题:你只管 `push_back` 加元素,它自己会扩容。
#include <vector>
using namespace std;
int main() {
vector<int> v;
v.push_back(3);
v.push_back(7);
v.push_back(1);
for (int i = 0; i < v.size(); i++) {
cout << v[i] << " ";
}
return 0;
}
常用操作:`push_back` 末尾加、`pop_back` 末尾删、`size()` 长度、`v[i]` 访问第 i 个元素、`v.clear()` 清空。
竞赛里 vector 几乎替代了普通数组。只有需要开很大数组(超过 100 万)时,才用全局数组,因为 vector 在函数内开大数组会栈溢出。
stack 与 queue:直接调包不用手写
#include <stack>
#include <queue>
stack<int> st;
st.push(10);
st.push(20);
cout << st.top() << endl; // 输出 20
st.pop();
queue<int> q;
q.push(1);
q.push(2);
cout << q.front() << endl; // 输出 1
q.pop();
对比上一篇手写的版本,STL 版只有三五行代码,而且内部实现经过优化,不会出现数组越界、指针错误。竞赛里直接用就好。
sort:一行代码排好一万个数
上一篇写冒泡排序写了 8 行,而且慢。STL 的 sort 函数一行搞定,而且是 O(n log n) 的快速排序,比冒泡快几十倍。
#include <algorithm>
#include <vector>
int main() {
vector<int> v = {5, 2, 9, 1, 5, 6};
sort(v.begin(), v.end());
// 现在 v 是 {1, 2, 5, 5, 6, 9}
return 0;
}
默认从小到大排。想从大到小排?加一句:
sort(v.begin(), v.end(), greater<int>());
10 万个数 sort 只要千分之一秒。这就是为什么竞赛里没人手写排序。
pair 与自定义排序:让 sort 按规则排
竞赛里经常要排"有两个关键字"的数据:比如按分数从高到低排,分数相同按学号从小到大排。这时候用 pair。
#include <utility>
pair<int,int> students[105];
// first 存分数, second 存学号
students[0] = {95, 1001};
students[1] = {88, 1002};
students[2] = {95, 1003};
sort(students, students + 3);
pair 默认先按 first 排,first 相同再按 second 排。正好满足"分数高在前,同分学号小在前"。如果要分数从高到低,就存 `-分数`,或者写一个自定义比较函数。
- vector动态数组。
- sort一行排序。
- pair两个关键字打包。
- greater降序排列。
实战:用 STL 解决一道经典竞赛题
题目:给定 n 个学生的分数,去掉最高分和最低分,求平均分。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> v(n);
for (int i = 0; i < n; i++) cin >> v[i];
sort(v.begin(), v.end());
double sum = 0;
for (int i = 1; i < n - 1; i++) sum += v[i];
printf("%.2f", sum / (n - 2));
return 0;
}
就这么短。如果不用 STL,你要手写输入循环、手写找最大最小、手写求和。STL 让你把精力放在"题目到底要什么"上,而不是"怎么实现数组操作"。
STL 之外:什么时候还得自己写
STL 很强,但不是万能的。以下情况还得自己写:
- 题目要求:有些题明确要求"不能用 STL",考的就是你的手写能力。
- 性能极致:有些极端题,STL 的通用实现不够快,需要手写优化。
- 特殊结构:线段树、树状数组、Trie 树这些高级结构,STL 没有现成的。
- 理解底层:面试和学习时,要能说出 STL 内部是怎么实现的。
学习路径:先会用 STL 解题拿分,再回头手写底层理解原理。不要一开始就死磕手写,那样会打击信心。
STL 是竞赛选手的拐杖,先用它跑起来,再学会自己走。