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

deque 的 push_front 和 push_back 性能真的都 O(1) 吗?
是的,push_front 和 push_back 平均时间复杂度都是 O(1),但背后依赖分段连续内存结构。实际中,当当前段满时,deque 会分配新段并更新控制数组,这个过程不触发元素拷贝(区别于 vector 的扩容),所以摊还代价稳定。
容易踩的坑:
- 频繁在首尾交替插入(比如模拟滑动窗口不断
push_front又pop_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 + 手动维护双端逻辑。











