目录
如需咨询请添加个人微信:a15135158368
欢迎叨扰,多多交流
deque
(双端队列,Double-Ended Queue)是 C++ 标准模板库(STL)中的一种顺序容器,它允许在序列的两端(头部和尾部)快速插入和删除元素。
与 vector
类似,deque
也是一个动态数组,但它的内存分配和管理方式使得它在两端操作上更加高效。
deque
的特点
-
双端操作
deque
支持在容器的头部和尾部进行快速的插入和删除操作复杂度为 O(1)
-
动态大小
deque
会根据需要自动调整其大小,动态分配和释放内存。 -
随机访问
deque
支持随机访问,类似于vector
,可以通过下标操作符[]
或者at()
方法访问元素。 -
内存分配
与
vector
不同,deque
通常会在不同的内存块中存储元素,因此不会像vector
那样需要一次性分配一大片连续的内存。
deque
的常用操作
1. 初始化
#include <iostream>
#include <deque>
int main()
{
std::deque<int> d1; // 默认构造函数
std::deque<int> d2(5, 10); // 构造一个包含 5 个值为 10 的元素的 deque
std::deque<int> d3 = {1, 2, 3, 4, 5}; // 列表初始化
}
2. 元素访问
#include <iostream>
#include <deque>
int main() {
std::deque<int> d = {1, 2, 3, 4, 5};
// 随机访问
std::cout << "索引2中的元素 : " << d[2] << std::endl; // 使用下标操作符
std::cout << "索引3处的元素 : " << d.at(3) << std::endl; // 使用 at() 方法
// 访问首尾元素
std::cout << "前部元件 : " << d.front() << std::endl; // 访问第一个元素
std::cout << "尾部元素 : " << d.back() << std::endl; // 访问最后一个元素
}
3. 插入和删除操作
#include <iostream>
#include <deque>
int main()
{
std::deque<int> d;
// 在头部和尾部插入元素
d.push_back(1); // 在尾部插入元素 1
d.push_front(2); // 在头部插入元素 2
// 输出 deque 的内容
std::cout << "Deque : ";
for (const auto& elem : d)
{
std::cout << elem << " ";
}
std::cout << std::endl;
// 在头部和尾部删除元素
d.pop_back(); // 删除尾部元素
d.pop_front(); // 删除头部元素
std::cout << "删除后的双端队列 : ";
for (const auto& elem : d)
{
std::cout << elem << " ";
}
std::cout << std::endl;
}
4. 大小管理
#include <iostream>
#include <deque>
int main()
{
std::deque<int> d = {1, 2, 3, 4, 5};
std::cout << "双端队列的大小 : " << d.size() << std::endl; // 获取元素个数
d.resize(3); // 调整大小为 3,超出的元素将被删除
std::cout << "调整大小后的Deque : ";
for (const auto& elem : d)
{
std::cout << elem << " ";
}
std::cout << std::endl;
}
5. 迭代器
#include <iostream>
#include <deque>
int main() {
std::deque<int> d = {1, 2, 3, 4, 5};
// 使用迭代器遍历 deque
std::cout << "双端队列中的元素为 : ";
for (auto it = d.begin(); it != d.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 逆向遍历
std::cout << "双端队列中的元素(反向) : ";
for (auto it = d.rbegin(); it != d.rend(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
deque
与 vector
的比较
-
插入和删除
-
deque
在两端插入和删除元素的操作比vector
更加高效,因为vector
只擅长在尾部进行插入和删除操作。
-
-
内存分配
-
deque
的内存分配策略使得它在头部和尾部的插入删除操作非常高效,但它的内存布局较vector
复杂,可能在某些场景下导致缓存性能不如vector
。
-
-
访问速度
-
vector
在连续内存块中存储数据,通常在遍历和访问元素时性能更好,因为它利用了 CPU 缓存的局部性。而
deque
由于分块存储,可能在访问时稍慢。
-
6.成员函数总结
代码 | 含义 |
---|---|
q.front() | 返回队首元素 |
q.back() | 返回队尾元素 |
q.push_back() | 在尾部插入元素 |
q.push_front() | 在头部插入元素 |
q.pop_back() | 删除尾部元素 |
q.pop_front | 删除头部元素 |
q.size() | 获取元素的个数 |
q.resize() | 调整队列元素个数,超出的元素将删除 |
q.empty() | 判断队列是否为空 |
q.erase() | 删除双端队列中的某一个元素 |
q.clear() | 清空队列 |
总结改编自作者: 行码棋
链接: C++ STL总结 | 行码棋
7.deque
成员函数使用实例
使用以上成员函数编写的一个deque
的简单实例:
#include <iostream>
#include <deque>
int main() {
// 创建一个空的双端队列
std::deque<int> q;
// 使用 push_back() 在队列的末尾添加元素
q.push_back(10);
q.push_back(20);
q.push_back(30);
// 使用 push_front() 在队列的前面添加元素
q.push_front(5);
q.push_front(1);
// 显示队列的内容
std::cout << "队列内容: ";
for(int n : q) {
std::cout << n << " ";
}
std::cout << std::endl;
// 使用 front() 和 back() 访问队列的第一个和最后一个元素
std::cout << "队列前面的元素 : " << q.front() << std::endl;
std::cout << "队列后面的元素 : " << q.back() << std::endl;
// 使用 pop_front() 移除队列前面的元素
q.pop_front();
std::cout << "移除前面元素后的队列内容 : ";
for(int n : q) {
std::cout << n << " ";
}
std::cout << std::endl;
// 使用 pop_back() 移除队列后面的元素
q.pop_back();
std::cout << "移除后面元素后的队列内容 : ";
for(int n : q) {
std::cout << n << " ";
}
std::cout << std::endl;
// 查看队列的大小
std::cout << "队列大小 : " << q.size() << std::endl;
// 使用 resize() 调整队列的大小
q.resize(3); // 将队列大小调整为3,如果原大小大于3,则多余的元素被删除
std::cout << "调整大小后的队列内容: ";
for(int n : q) {
std::cout << n << " ";
}
std::cout << std::endl;
// 检查队列是否为空
if(q.empty()) {
std::cout << "队列为空" << std::endl;
} else {
std::cout << "队列不为空" << std::endl;
}
return 0;
}
运行结果:
队列内容: 1 5 10 20 30
队列前面的元素: 1
队列后面的元素: 30
移除前面元素后的队列内容: 5 10 20 30
移除后面元素后的队列内容: 5 10 20
队列大小: 3
调整大小后的队列内容: 5 10 20
队列不为空