设计师网站有哪些wordpress安装多说
目录
一、deque的基本概念
主要特点:
二、deque的底层实现原理
1、底层结构
2、内存布局示例
3、扩容机制
三、deque的迭代器设计
四、deque的优缺点分析
优点(相比其他容器):
缺点:
五、deque的应用场景
为什么不是vector或list?
六、deque 的基本操作
1、创建和初始化 deque
2、元素访问
3、修改 deque
4、容量操作
七、deque 的迭代器
八、deque 的性能分析
九、示例:使用 deque 实现滑动窗口最大值
十、总结
一、deque的基本概念

deque(双端队列,全称 double-ended queue)是一种双开口的"连续"空间数据结构,是 C++ STL 中的一个独立容器,而不是容器适配器。它允许在队列的前端和后端高效地进行插入和删除操作,时间复杂度为O(1)。

与 vector 相比,deque 在头部插入和删除元素时性能更好;与 list 相比,deque 支持随机访问,但在中间位置插入和删除元素效率较低。
主要特点:
-  
双端操作:支持push_front、push_back、pop_front、pop_back,可以在头部和尾部高效地插入和删除元素
 -  
假象的连续空间:实际由多个分段连续的小空间组成
 -  
动态扩展:不需要像vector那样搬移大量元素,可以根据需要自动扩展和收缩
 -  
较高空间利用率:相比list不需要存储额外指针字段
 -  
随机访问:支持通过下标直接访问元素
 -  
不连续存储:元素并非存储在连续的内存块中(与 vector 不同)
 -  
迭代器支持:提供随机访问迭代器
 
二、deque的底层实现原理
deque 通常实现为一系列固定大小的数组(称为块或缓冲区),这些数组的指针被存储在一个中央控制结构中(通常是数组)。这种实现方式使得:
-  
在两端扩展和收缩都很高效
 -  
随机访问需要先计算元素所在的块,然后再计算块内的偏移
 -  
内存使用比 vector 更分散,但比 list 更紧凑
 
1、底层结构

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,deque的底层实现类似于一个动态的二维数组,但更为复杂。它由以下几个关键部分组成:
-  
map(中控器):一个指针数组,每个元素指向一块连续的内存块(称为缓冲区或节点)
 -  
缓冲区(node):实际存储数据的连续内存块
 -  
迭代器:包含四个指针:
-  
cur:当前元素指针
 -  
first:当前缓冲区的起始位置
 -  
last:当前缓冲区的结束位置
 -  
node:指向map中对应的指针

 
 -  
 
2、内存布局示例

当执行以下操作时:
deque<int> deq;
deq.push_back(0);
deq.push_back(1);
deq.push_back(2); 
内存可能布局为:

3、扩容机制
当map使用率满载时,会执行reallocate_map():
-  
找一块更大的空间
 -  
将原有指针复制到新map的中间位置
 -  
释放旧map
 
这种策略保持了deque两端的高效扩展能力。
三、deque的迭代器设计

deque的迭代器比普通迭代器复杂,因为它需要维护"假象连续"的特性:
-  
当迭代器到达当前缓冲区边界时,需要跳转到下一个/上一个缓冲区
 -  
迭代器需要知道当前缓冲区的位置和边界
 
四、deque的优缺点分析
优点(相比其他容器):
-  
vs vector:
-  
头部操作高效(O(1) vs O(n))
 -  
扩容时不需要搬移大量元素
 
 -  
 -  
vs list:
-  
更高的空间利用率(不需要存储指针)
 -  
更好的缓存局部性(数据局部连续)
 
 -  
 
缺点:
-  
随机访问性能不如vector(需要计算缓冲区位置)
 -  
遍历效率低(频繁检查边界)
 -  
中间插入/删除效率低(需要移动元素)
 
五、deque的应用场景
虽然deque本身应用不多,但它是STL中stack和queue的理想底层容器,因为:
-  
stack和queue不需要遍历:避开了deque遍历效率低的缺陷
 -  
高效的双端操作:正好满足stack和queue的操作需求,需要频繁在两端添加或删除元素
 -  
内存效率高:比list更适合作为基础容器
 -  
扩展高效:比vector在频繁push/pop时性能更好
 -  
需要随机访问,但不需要频繁在中间插入/删除
 -  
实现队列或双端队列数据结构
 -  
作为优先级队列的底层容器(std::priority_queue 默认使用 vector,但也可以指定 deque)
 
为什么不是vector或list?
-  
vector:头部操作效率低,扩容成本高
 -  
list:空间利用率低,缓存不友好
 
六、deque 的基本操作
1、创建和初始化 deque
#include <deque>
#include <iostream>int main() {// 空 dequestd::deque<int> d1;// 包含 5 个元素,每个初始化为 0std::deque<int> d2(5);// 包含 5 个元素,每个初始化为 10std::deque<int> d3(5, 10);// 通过初始化列表std::deque<int> d4 = {1, 2, 3, 4, 5};// 通过迭代器范围int arr[] = {6, 7, 8, 9, 10};std::deque<int> d5(arr, arr + 5);// 拷贝构造函数std::deque<int> d6(d5);return 0;
} 
2、元素访问
std::deque<int> d = {1, 2, 3, 4, 5};// 使用下标运算符(不检查边界)
int a = d[2];  // 3// 使用 at 方法(检查边界,越界抛出 std::out_of_range 异常)
int b = d.at(3);  // 4// 访问第一个和最后一个元素
int front = d.front();  // 1
int back = d.back();    // 5 
3、修改 deque
std::deque<int> d = {1, 2, 3};// 在尾部添加元素
d.push_back(4);  // {1, 2, 3, 4}// 在头部添加元素
d.push_front(0);  // {0, 1, 2, 3, 4}// 删除尾部元素
d.pop_back();  // {0, 1, 2, 3}// 删除头部元素
d.pop_front();  // {1, 2, 3}// 在指定位置插入元素
auto it = d.begin() + 1;
d.insert(it, 10);  // {1, 10, 2, 3}// 删除指定位置的元素
it = d.begin() + 2;
d.erase(it);  // {1, 10, 3}// 清空 deque
d.clear();  // {} 
4、容量操作
std::deque<int> d = {1, 2, 3};// 获取元素数量
size_t size = d.size();  // 3// 检查是否为空
bool empty = d.empty();  // false// 改变大小
d.resize(5);      // {1, 2, 3, 0, 0}
d.resize(2);      // {1, 2}
d.resize(4, 10);  // {1, 2, 10, 10} 
七、deque 的迭代器
deque 提供随机访问迭代器,支持所有随机访问迭代器操作:
std::deque<int> d = {1, 2, 3, 4, 5};// 使用迭代器遍历
for (auto it = d.begin(); it != d.end(); ++it) {std::cout << *it << " ";
}
std::cout << std::endl;// 使用反向迭代器
for (auto rit = d.rbegin(); rit != d.rend(); ++rit) {std::cout << *rit << " ";
}
std::cout << std::endl;// 随机访问
auto it = d.begin() + 3;
std::cout << *it << std::endl;  // 4 
八、deque 的性能分析
| 操作 | 时间复杂度 | 
|---|---|
| 随机访问 | O(1) | 
| 在头部或尾部插入/删除 | O(1) | 
| 在中间位置插入/删除 | O(n) | 
| 查找元素 | O(n) | 
九、示例:使用 deque 实现滑动窗口最大值
#include <deque>
#include <vector>
#include <iostream>std::vector<int> maxSlidingWindow(const std::vector<int>& nums, int k) {std::vector<int> result;std::deque<int> dq;  // 存储索引for (int i = 0; i < nums.size(); ++i) {// 移除超出窗口范围的元素if (!dq.empty() && dq.front() == i - k) {dq.pop_front();}// 移除所有小于当前元素的元素while (!dq.empty() && nums[dq.back()] < nums[i]) {dq.pop_back();}// 添加当前元素dq.push_back(i);// 当窗口形成时,记录最大值if (i >= k - 1) {result.push_back(nums[dq.front()]);}}return result;
}int main() {std::vector<int> nums = {1, 3, -1, -3, 5, 3, 6, 7};int k = 3;auto result = maxSlidingWindow(nums, k);for (int num : result) {std::cout << num << " ";}// 输出: 3 3 5 5 6 7return 0;
} 
十、总结
deque是一种折衷设计的数据结构,它:
-  
结合了vector和list的部分优点
 -  
通过复杂迭代器维护"假象连续"的特性
 -  
特别适合作为只需要双端操作的容器的底层实现
 -  
在实际应用中,除非特定需求,通常优先考虑vector或list
 
