一篇搞懂C++ STL双端队列std::deque


前言

在C++标准模板库(STL)中,std::deque 是一种常用的容器,它代表了双端队列(Double-ended Queue)。与std::vector相比,std::deque允许高效地在容器的两端插入和删除元素,而std::vector只能高效地在尾部进行这些操作。本篇文章将深入探讨std::deque的定义、与std::queue的区别,并详细介绍std::deque的构造函数和操作函数,帮助你全面掌握这一重要的容器。


什么是std::deque

std::deque(双端队列)是一种动态数组,支持在两端快速插入和删除元素。这意味着无论是在队列的前端还是后端,都可以在常数时间内完成元素的插入和删除操作。std::deque内部实现通常使用了一系列连续的内存块,来实现这一特性。这也使得std::dequestd::vector在前端插入和删除元素时更高效。

std::dequestd::queue的区别

std::queue 是一个典型的先进先出(FIFO)的数据结构,只允许在尾部插入元素,在头部删除元素。std::queue通常是基于std::dequestd::list实现的,但它对用户隐藏了底层的实现细节。相比之下,std::deque 则是一个更通用的容器,它不仅支持std::queue的所有操作,还允许在队列的两端进行操作。

通过一个简单的字符串图可以更清晰地理解这两者的区别:

// std::deque(双端队列)
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
^               ^
|               |
front()         back()

// std::queue(单端队列)
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
^               ^
|               |
front()         push_back()

如图所示,std::deque 允许在前端和后端进行操作,而std::queue 只能在尾部插入,在头部删除。

std::deque的构造函数

  1. 默认构造函数
    创建一个空的deque容器。

    std::deque<int> dq;
    
  2. 指定大小的构造函数
    创建一个包含n个默认初始化元素的deque

    std::deque<int> dq(5);  // 创建一个包含5个默认值为0的元素的deque
    
  3. 指定大小和初始值的构造函数
    创建一个包含n个元素,每个元素的值为val

    std::deque<int> dq(5, 10);  // 创建一个包含5个值为10的元素的deque
    
  4. 区间构造函数
    创建一个deque,初始化为迭代器范围[first, last)内的元素。

    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::deque<int> dq(vec.begin(), vec.end());  // 用vector的元素初始化deque
    
  5. 复制构造函数
    创建一个deque,它是另一个deque的副本。

    std::deque<int> dq1 = {1, 2, 3, 4, 5};
    std::deque<int> dq2(dq1);  // 复制dq1
    
  6. 移动构造函数
    创建一个deque,通过移动另一个deque的内容来初始化。

    std::deque<int> dq1 = {1, 2, 3, 4, 5};
    std::deque<int> dq2(std::move(dq1));  // 移动dq1到dq2
    

std::deque的操作函数

  1. push_back()
    deque的末尾添加元素。

    std::deque<int> dq = {1, 2, 3};
    dq.push_back(4);  // dq = {1, 2, 3, 4}
    
  2. push_front()
    deque的开头添加元素。

    std::deque<int> dq = {2, 3, 4};
    dq.push_front(1);  // dq = {1, 2, 3, 4}
    
  3. pop_back()
    删除deque末尾的元素。

    std::deque<int> dq = {1, 2, 3, 4};
    dq.pop_back();  // dq = {1, 2, 3}
    
  4. pop_front()
    删除deque开头的元素。

    std::deque<int> dq = {1, 2, 3, 4};
    dq.pop_front();  // dq = {2, 3, 4}
    
  5. front()
    返回deque开头的元素。

    std::deque<int> dq = {1, 2, 3, 4};
    int frontElem = dq.front();  // frontElem = 1
    
  6. back()
    返回deque末尾的元素。

    std::deque<int> dq = {1, 2, 3, 4};
    int backElem = dq.back();  // backElem = 4
    
  7. size()
    返回deque中元素的数量。

    std::deque<int> dq = {1, 2, 3, 4};
    size_t size = dq.size();  // size = 4
    
  8. empty()
    判断deque是否为空。

    std::deque<int> dq;
    bool isEmpty = dq.empty();  // isEmpty = true
    
  9. clear()
    清空deque中的所有元素。

    std::deque<int> dq = {1, 2, 3, 4};
    dq.clear();  // dq = {}
    
  10. operator[]at()
    访问deque中指定位置的元素。

    std::deque<int> dq = {1, 2, 3, 4};
    int elem1 = dq[1];     // elem1 = 2
    int elem2 = dq.at(1);  // elem2 = 2
    

示例代码

#include <iostream>
#include <deque>

int main() {
    // 创建一个双端队列
    std::deque<int> dq = {1, 2, 3, 4};

    // 在末尾添加元素
    dq.push_back(5);  // dq = {1, 2, 3, 4, 5}

    // 在开头添加元素
    dq.push_front(0);  // dq = {0, 1, 2, 3, 4, 5}

    // 删除末尾的元素
    dq.pop_back();  // dq = {0, 1, 2, 3, 4}

    // 删除开头的元素
    dq.pop_front();  // dq = {1, 2, 3, 4}

    // 访问第一个和最后一个元素
    std::cout << "Front: " << dq.front() << ", Back: " << dq.back() << std::endl;  // Front: 1, Back: 4

    // 访问指定位置的元素
    std::cout << "Element at index 2: " << dq[2] << std::endl;  // Element at index 2: 3

    // 输出队列中的所有元素
    std::cout << "Elements in deque: ";
    for (int elem : dq) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 清空队列
    dq.clear();
    std::cout << "Deque size after clearing: " << dq.size() << std::endl;  // Deque size after clearing: 0

    return 0;
}

总结

std::deque 是一个功能强大且灵活的容器,它结合了std::vectorstd::list的一些优点,提供了在两端快速插入和删除元素的能力。在理解了std::dequestd::queue的区别后,掌握其构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

人才程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值