一篇搞懂C++ STL双端队列std::deque
@TOC
前言
在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::deque
比std::vector
在前端插入和删除元素时更高效。
std::deque
与std::queue
的区别
std::queue
是一个典型的先进先出(FIFO)的数据结构,只允许在尾部插入元素,在头部删除元素。std::queue
通常是基于std::deque
或std::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
的构造函数
-
默认构造函数
创建一个空的deque
容器。std::deque<int> dq;
-
指定大小的构造函数
创建一个包含n
个默认初始化元素的deque
。std::deque<int> dq(5); // 创建一个包含5个默认值为0的元素的deque
-
指定大小和初始值的构造函数
创建一个包含n
个元素,每个元素的值为val
。std::deque<int> dq(5, 10); // 创建一个包含5个值为10的元素的deque
-
区间构造函数
创建一个deque
,初始化为迭代器范围[first, last)
内的元素。std::vector<int> vec = {1, 2, 3, 4, 5}; std::deque<int> dq(vec.begin(), vec.end()); // 用vector的元素初始化deque
-
复制构造函数
创建一个deque
,它是另一个deque
的副本。std::deque<int> dq1 = {1, 2, 3, 4, 5}; std::deque<int> dq2(dq1); // 复制dq1
-
移动构造函数
创建一个deque
,通过移动另一个deque
的内容来初始化。std::deque<int> dq1 = {1, 2, 3, 4, 5}; std::deque<int> dq2(std::move(dq1)); // 移动dq1到dq2
std::deque
的操作函数
-
push_back()
在deque
的末尾添加元素。std::deque<int> dq = {1, 2, 3}; dq.push_back(4); // dq = {1, 2, 3, 4}
-
push_front()
在deque
的开头添加元素。std::deque<int> dq = {2, 3, 4}; dq.push_front(1); // dq = {1, 2, 3, 4}
-
pop_back()
删除deque
末尾的元素。std::deque<int> dq = {1, 2, 3, 4}; dq.pop_back(); // dq = {1, 2, 3}
-
pop_front()
删除deque
开头的元素。std::deque<int> dq = {1, 2, 3, 4}; dq.pop_front(); // dq = {2, 3, 4}
-
front()
返回deque
开头的元素。std::deque<int> dq = {1, 2, 3, 4}; int frontElem = dq.front(); // frontElem = 1
-
back()
返回deque
末尾的元素。std::deque<int> dq = {1, 2, 3, 4}; int backElem = dq.back(); // backElem = 4
-
size()
返回deque
中元素的数量。std::deque<int> dq = {1, 2, 3, 4}; size_t size = dq.size(); // size = 4
-
empty()
判断deque
是否为空。std::deque<int> dq; bool isEmpty = dq.empty(); // isEmpty = true
-
clear()
清空deque
中的所有元素。std::deque<int> dq = {1, 2, 3, 4}; dq.clear(); // dq = {}
-
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::vector
和std::list
的一些优点,提供了在两端快速插入和删除元素的能力。在理解了std::deque
与std::queue
的区别后,掌握其构
- 点赞
- 收藏
- 关注作者
评论(0)