C++基础知识--std::deque

std::deque(Double-Ended Queue,双端队列),它是 C++ STL(标准模板库)中的一个容器。下面详细介绍它的特性、用法及实现原理。


1. std::deque 概述

std::deque(双端队列)是一种动态数组,支持在 头部和尾部 高效插入和删除元素(O(1) 时间复杂度)。

  • 头文件#include <deque>
  • 底层结构:通常由多个固定大小的数组(块)组成,通过一个中央映射表(map)管理这些块,使其能动态扩展。
  • 特点
    • 随机访问(operator[]at())效率接近 std::vector(O(1))。
    • 在头部插入/删除(push_front/pop_front)比 std::vector 更高效(vector 是 O(n))。
    • 不保证元素在内存中连续存储(但大多数实现仍保持局部连续)。

2. std::deque 的核心操作

(1)初始化

#include <deque>
std::deque<int> dq1;                  // 空 deque
std::deque<int> dq2(5, 100);          // 5 个 100: {100, 100, 100, 100, 100}
std::deque<int> dq3(dq2.begin(), dq2.end()); // 拷贝 dq2
std::deque<int> dq4 = {1, 2, 3, 4};   // 初始化列表

(2)元素访问

方法说明示例
dq[i]访问第 i 个元素(不检查越界)int x = dq[2];
dq.at(i)访问第 i 个元素(越界抛异常)int y = dq.at(2);
dq.front()返回第一个元素int first = dq.front();
dq.back()返回最后一个元素int last = dq.back();

(3)修改操作

方法说明示例
dq.push_back(x)尾部插入 xdq.push_back(10);
dq.push_front(x)头部插入 xdq.push_front(20);
dq.pop_back()删除尾部元素dq.pop_back();
dq.pop_front()删除头部元素dq.pop_front();
dq.insert(pos, x)在 pos 位置插入 xdq.insert(dq.begin()+1, 5);
dq.erase(pos)删除 pos 位置的元素dq.erase(dq.begin());
dq.clear()清空所有元素dq.clear();

(4)容量查询

方法说明示例
dq.size()返回元素个数size_t n = dq.size();
dq.empty()判断是否为空if (dq.empty()) {...}

3. std::deque 的底层实现

(1)数据结构

std::deque 通常由多个固定大小的 块(chunks) 组成,并通过一个 中央控制表(map) 管理这些块的指针:

Map (索引表):
[0] -> [块1: |x|x|x|x|]
[1] -> [块2: |x|x|x|x|]
[2] -> [块3: |x|x|x|x|]
  • 每个块的大小固定(如 512 字节)。
  • 插入元素时,如果当前块已满,会分配新块并更新 map

(2)性能分析

操作时间复杂度说明
push_backO(1)可能触发新块分配
push_frontO(1)可能触发新块分配
pop_backO(1)可能释放空块
pop_frontO(1)可能释放空块
operator[]O(1)通过 map 计算块偏移
insertO(n)中间插入需移动元素

4. std::deque vs std::vector vs std::list

特性std::dequestd::vectorstd::list
随机访问✅ O(1)✅ O(1)❌ O(n)
头部插入/删除✅ O(1)❌ O(n)✅ O(1)
尾部插入/删除✅ O(1)✅ O(1)(均摊)✅ O(1)
中间插入/删除❌ O(n)❌ O(n)✅ O(1)(已知迭代器)
内存连续性❌(局部连续)✅(完全连续)❌(节点分散)

适用场景

  • 需要高效头尾操作 → std::deque
  • 需要快速随机访问 → std::vector
  • 需要频繁中间插入 → std::list

5. 示例代码

#include <iostream>
#include <deque>

int main() {
    std::deque<int> dq = {10, 20, 30};

    dq.push_front(5);   // 头部插入: {5, 10, 20, 30}
    dq.push_back(40);    // 尾部插入: {5, 10, 20, 30, 40}

    std::cout << "Front: " << dq.front() << "\n";  // 5
    std::cout << "Back: " << dq.back() << "\n";    // 40

    dq.pop_front();     // 移除头部: {10, 20, 30, 40}
    dq.pop_back();      // 移除尾部: {10, 20, 30}

    for (int x : dq) {  // 遍历
        std::cout << x << " ";  // 10 20 30
    }
    return 0;
}

6. 总结

  • std::deque 适合需要 频繁头尾操作 的场景(如队列 + 栈结合需求)。
  • 虽然支持随机访问,但 中间插入/删除较慢(不如 std::list)。
  • 内存占用比 std::vector 稍高(因存储 map 和分块结构)。

如果需要高性能双端操作,std::deque 是最佳选择之一! 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐怡旸--指针诗笺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值