📚 C++ STL中的deque详解
deque (double-ended queue) - 双端队列,STL中最灵活的顺序容器之一
🎯 什么是deque?
deque(读作"deck")是双端队列(double-ended queue)的缩写,是C++ STL提供的一种顺序容器。它允许在头部和尾部都能进行高效的插入和删除操作。
🏗️ deque的内部结构
📦 分块存储原理
不同于vector的连续内存存储,deque采用分块存储的方式:
🔄 迭代器结构
classDiagram
class DequeIterator {
-T* current
-T* first
-T* last
-MapPointer node
+operator++()
+operator--()
+operator[](n)
+jump_to_next_block()
+jump_to_prev_block()
}
class MapArray {
-T** map_start
-T** map_finish
-size_t map_size
}
DequeIterator --> MapArray : uses
note for DequeIterator "current: 当前元素指针\nfirst: 当前块首元素\nlast: 当前块末元素\nnode: 指向map中的块指针"
⚡ deque vs vector vs list
📊 性能对比
🎯 选择指南

🛠️ deque的基本操作
📝 构造和初始化
#include <deque>
#include <iostream>
// 基本构造方式
std::deque<int> dq1; // 空deque
std::deque<int> dq2(5); // 5个默认值元素
std::deque<int> dq3(5, 10); // 5个值为10的元素
std::deque<int> dq4{1, 2, 3, 4, 5}; // 初始化列表
std::deque<int> dq5(dq4); // 拷贝构造
🔄 基本操作流程
💻 常用操作详解
🔧 元素访问

➕ 插入操作

➖ 删除操作
// 删除操作示例
std::deque<int> dq{1, 2, 3, 4, 5};
dq.pop_front(); // 删除首元素: {2, 3, 4, 5}
dq.pop_back(); // 删除尾元素: {2, 3, 4}
dq.erase(dq.begin()); // 删除指定位置: {3, 4}
dq.clear(); // 清空所有元素: {}
🧮 实际应用场景
🎮 场景1:游戏中的动作队列
📊 场景2:滑动窗口算法

🌊 场景3:生产者消费者模式

⚠️ 使用注意事项
🚨 常见陷阱

✅ 最佳实践

📈 性能分析
⏱️ 时间复杂度总结
| 操作类型 | 时间复杂度 | 说明 |
|---|---|---|
push_front() | O(1) | 头部插入,摊销常数时间 |
push_back() | O(1) | 尾部插入,摊销常数时间 |
pop_front() | O(1) | 头部删除 |
pop_back() | O(1) | 尾部删除 |
insert() | O(n) | 中间插入,需要移动元素 |
erase() | O(n) | 中间删除,需要移动元素 |
operator[] | O(1) | 随机访问 |
at() | O(1) | 带边界检查的访问 |
💾 空间复杂度
🔧 实战代码示例
📋 滑动窗口最大值实现
#include <deque>
#include <vector>
#include <iostream>
class SlidingWindowMaximum {
private:
std::deque<int> dq; // 存储数组索引
public:
std::vector<int> maxSlidingWindow(std::vector<int>& nums, int k) {
std::vector<int> result;
for (int i = 0; i < nums.size(); i++) {
// 移除超出窗口范围的元素
while (!dq.empty() && dq.front() < i - k + 1) {
dq.pop_front();
}
// 移除比当前元素小的元素(保持递减队列)
while (!dq.empty() && nums[dq.back()] < nums[i]) {
dq.pop_back();
}
dq.push_back(i);
// 窗口形成后开始记录结果
if (i >= k - 1) {
result.push_back(nums[dq.front()]);
}
}
return result;
}
};
🔄 双端队列应用 - 回文检查
#include <deque>
#include <string>
#include <algorithm>
bool isPalindrome(const std::string& str) {
std::deque<char> dq;
// 只添加字母数字字符(转小写)
for (char c : str) {
if (std::isalnum(c)) {
dq.push_back(std::tolower(c));
}
}
// 从两端比较
while (dq.size() > 1) {
if (dq.front() != dq.back()) {
return false;
}
dq.pop_front();
dq.pop_back();
}
return true;
}
📚 总结

🎯 选择deque的时机
✅ 适合使用deque:
- 需要频繁的头尾插入删除操作
- 需要随机访问元素
- 实现双端队列、滑动窗口等算法
- 作为其他数据结构的底层容器
❌ 不适合使用deque:
- 只需要尾部操作(用vector更好)
- 需要频繁的中间插入删除(用list更好)
- 需要传递给C风格API(vector更合适)
- 对内存局部性要求很高的场景
💡 记住:deque是在vector和list之间的平衡选择,它结合了两者的优点,是实现队列和双端队列的理想容器!
掌握deque的特性和使用技巧,将大大提升你的C++编程能力! 🚀

2万+

被折叠的 条评论
为什么被折叠?



