c++中如何使用deque双端队列_c++ STL容器deque操作【精讲】

3次阅读

是的,push_front 和 push_back 平均时间复杂度都是 o(1),依赖分段连续内存结构,扩容不拷贝元素,摊还稳定;但控制数组可能持续增长,内存占用偏高,且内存不连续,不可用于要求连续内存的场景。

c++中如何使用deque双端队列_c++ STL容器deque操作【精讲】

deque 的 push_front 和 push_back 性能真的都 O(1) 吗?

是的,push_frontpush_back 平均时间复杂度都是 O(1),但背后依赖分段连续内存结构。实际中,当当前段满时,deque 会分配新段并更新控制数组,这个过程不触发元素拷贝(区别于 vector 的扩容),所以摊还代价稳定。

容易踩的坑:

  • 频繁在首尾交替插入(比如模拟滑动窗口不断 push_frontpop_back)时,控制数组可能持续增长,虽不慢,但内存占用比预期高
  • 不要假设 deque 的内存是真正连续的——&dq[0] + 1 不一定等于 &dq[1],因此不能把 dq.data() 当作 C 风格数组传给需要连续内存的函数(如某些 SIMD 接口fwrite

迭代器失效规则和 vector 有什么不同?

deque 迭代器只在对应位置被擦除(erase)或整个容器被销毁时才失效;插入操作(push_front/push_back/insert)**不会使其他迭代器失效**——这点和 vector 完全相反。

使用场景举例:你正在遍历 deque 做条件判断,同时需要把满足条件的元素加到队首,这时可以直接边 push_front 边用原迭代器继续走,完全不用担心失效。

立即学习C++免费学习笔记(深入)”;

注意点:

  • erase(iterator) 会令该迭代器及之后所有迭代器失效(但不是全部失效,仅从该位置起向后失效)
  • clear() 后所有迭代器立即失效
  • 避免对 end() 迭代器做自增(++it),虽然 deque 允许,但行为未定义,别依赖

用 deque 实现和队列,为什么比手写链表更合适?

因为 deque 提供了 push_back/pop_back(栈)和 push_back/pop_front(队列)的组合,且所有操作都是摊还 O(1),没有指针管理开销,也不像 list 那样每节点多占 2 个指针内存。

实操建议:

  • 别用 stack<int deque>></int> 显式指定底层容器——默认就是 deque,stack<int></int> 足够
  • 如果队列操作中需要随机访问第 k 个元素(比如优先级调整),deque 比 queue<int></int>(默认基于 deque)更直接,因为可写 q[k]
  • 不要为了“看起来像队列”而封装一层类再暴露 push/pop——直接用 deque 成员函数更清晰、更少出错

resize() 和 assign() 对 deque 来说意味着什么?

resize(n) 会保留前 min(n, size()) 个元素,不足补默认值,超出则截断;assign(n, val) 则清空后重新填入 n 个 val。两者都会导致原有元素被析构、新元素被构造。

关键差异:

  • resize(0) 等价于 clear(),但不保证释放内存(capacity 不变);想真正释放内存得用 deque<t>{}.swap(dq)</t>
  • assign 在参数为迭代器范围时(如 assign(v.begin(), v.end()))效率很高,内部按需分配段,不逐个 insert
  • 若元素类型有非平凡析构函数resize 缩小时会调用对应数量的析构函数——这点常被忽略,尤其在嵌套容器场景下容易引发意外性能抖动

复杂点在于:deque 的“容量”概念模糊,没有 capacity() 成员函数,也没法像 vector 那样预估内存用量。如果你真需要控制内存段数量,只能靠观察 size() 和实际分配行为,或者换用 vector + 手动维护双端逻辑。

text=ZqhQzanResources