STL容器在算法竞赛中的常见应用及方法总结
queue (队列)
常见应用场景:
- BFS (广度优先搜索)
- 模拟排队过程
- 滑动窗口问题
对应的函数方法:
push(x)
- 在队尾插入元素xpop()
- 删除队首元素front()
- 返回队首元素back()
- 返回队尾元素empty()
- 判断队列是否为空size()
- 返回队列中元素个数
应用举例:
// BFS模板
queue<int> q;
q.push(start);
while (!q.empty()) {
int current = q.front();
q.pop();
// 处理current节点
for (auto neighbor : get_neighbors(current)) {
if (!visited[neighbor]) {
visited[neighbor] = true;
q.push(neighbor);
}
}
}
priority_queue (优先队列)
常见应用场景:
- Dijkstra算法
- 哈夫曼编码
- 需要动态获取最大值/最小值的场景
对应的函数方法:
push(x)
- 插入元素xpop()
- 删除顶部元素top()
- 返回顶部元素(最大或最小)empty()
- 判断是否为空size()
- 返回元素个数
应用举例:
// 默认是大顶堆
priority_queue<int> max_heap;
// 小顶堆定义方式
priority_queue<int, vector<int>, greater<int>> min_heap;
// Dijkstra算法中的使用
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({0, start});
while (!pq.empty()) {
auto [dist, u] = pq.top();
pq.pop();
if (dist > distance[u]) continue;
// 松弛操作...
}
stack (栈)
常见应用场景:
- DFS (深度优先搜索)
- 表达式求值
- 括号匹配
- 单调栈问题
对应的函数方法:
push(x)
- 压入元素xpop()
- 弹出顶部元素top()
- 返回顶部元素empty()
- 判断是否为空size()
- 返回元素个数
应用举例:
// 括号匹配
stack<char> s;
for (char c : str) {
if (c == '(' || c == '[' || c == '{') {
s.push(c);
} else {
if (s.empty() || !is_match(s.top(), c)) return false;
s.pop();
}
}
return s.empty();
set (集合)
常见应用场景:
- 维护有序不重复元素
- 需要频繁查找/插入/删除的场景
- 需要前驱/后继操作的场景
对应的函数方法:
insert(x)
- 插入元素xerase(x)
- 删除元素xfind(x)
- 查找元素x,返回迭代器count(x)
- 返回x是否存在(0或1)lower_bound(x)
- 返回第一个≥x的迭代器upper_bound(x)
- 返回第一个>x的迭代器empty()
- 判断是否为空size()
- 返回元素个数begin()/end()
- 迭代器
应用举例:
set<int> s;
s.insert(3);
s.insert(1);
s.insert(4);
// s现在是 {1, 3, 4}
auto it = s.lower_bound(2); // 指向3
if (it != s.begin()) {
auto prev_it = prev(it); // 指向前驱1
}
map (映射)
常见应用场景:
- 键值对存储
- 需要按键排序的场景
- 频率统计
对应的函数方法:
insert({key, value})
- 插入键值对erase(key)
- 删除键为key的元素find(key)
- 查找键为key的元素count(key)
- 返回键是否存在(0或1)lower_bound(key)
- 返回第一个键≥key的迭代器upper_bound(key)
- 返回第一个键>key的迭代器empty()
- 判断是否为空size()
- 返回元素个数begin()/end()
- 迭代器operator[]
- 访问或插入元素
应用举例:
map<string, int> word_count;
word_count["apple"]++;
word_count["banana"] = 5;
// 遍历map
for (auto &[word, count] : word_count) {
cout << word << ": " << count << endl;
}
unordered_map (无序映射)
常见应用场景:
- 需要快速查找的键值对存储
- 不关心键的顺序
- 频率统计(比map更快)
对应的函数方法:
insert({key, value})
- 插入键值对erase(key)
- 删除键为key的元素find(key)
- 查找键为key的元素count(key)
- 返回键是否存在(0或1)empty()
- 判断是否为空size()
- 返回元素个数begin()/end()
- 迭代器operator[]
- 访问或插入元素
应用举例:
unordered_map<int, int> freq;
for (int num : nums) {
freq[num]++;
}
// 查找元素
if (freq.find(42) != freq.end()) {
cout << "42 appears " << freq[42] << " times" << endl;
}
unordered_set (无序集合)
常见应用场景:
- 快速查找元素是否存在
- 去重操作
- 不关心元素顺序的集合操作
对应的函数方法:
insert(x)
- 插入元素xerase(x)
- 删除元素xfind(x)
- 查找元素x,返回迭代器count(x)
- 返回x是否存在(0或1)empty()
- 判断是否为空size()
- 返回元素个数begin()/end()
- 迭代器
应用举例:
unordered_set<int> seen;
for (int num : nums) {
if (seen.count(target - num)) {
return {num, target - num};
}
seen.insert(num);
}
总结对比
容器 | 底层实现 | 时间复杂度 | 有序性 | 适用场景 |
---|---|---|---|---|
queue | 链表/数组 | O(1)插入删除 | 无 | BFS, FIFO场景 |
priority_queue | 堆 | O(logn)插入删除 | 部分 | 需要快速获取最大/最小元素 |
stack | 链表/数组 | O(1)插入删除 | 无 | DFS, LIFO场景 |
set | 红黑树 | O(logn)查找插入删除 | 有序 | 需要有序且不重复元素的集合 |
map | 红黑树 | O(logn)查找插入删除 | 有序 | 需要有序键值对 |
unordered_set | 哈希表 | 平均O(1)查找插入删除 | 无序 | 需要快速查找且不关心顺序 |
unordered_map | 哈希表 | 平均O(1)查找插入删除 | 无序 | 需要快速键值查找且不关心顺序 |
在算法竞赛中,根据具体需求选择合适的容器可以显著提高代码效率和编写速度。