当前位置: 首页 > news >正文

C++笔记——STL deque

1. deque 基本概念

什么是deque?

双端队列:可以在头部和尾部进行高效插入删除的动态数组

核心特性(与vector对比):

特性vectordeque
随机访问✅ O(1)✅ O(1)
尾部操作✅ O(1)✅ O(1)
头部操作❌ O(n)✅ O(1)
中间操作❌ O(n)❌ O(n)
内存布局单块连续多块连续(分段数组)

2. deque 的基本使用

头文件和声明:

cpp

#include <deque>
using namespace std;// 各种创建方式(与vector几乎相同)
deque<int> dq1;                    // 空deque
deque<int> dq2(10);               // 10个元素,默认值0
deque<int> dq3(5, 100);           // 5个元素,每个都是100
deque<int> dq4 = {1, 2, 3, 4, 5}; // 初始化列表
deque<int> dq5(dq4);              // 拷贝构造

3. deque 的特有操作 - 头部操作

这是与vector最大的区别!

cpp

void deque_special_operations() {deque<int> dq = {2, 3, 4};// 头部操作 - vector没有这些!dq.push_front(1);        // 头部插入: {1,2,3,4}dq.pop_front();          // 头部删除: {2,3,4}dq.emplace_front(0);     // 头部原地构造: {0,2,3,4}// 尾部操作(与vector相同)dq.push_back(5);         // 尾部插入: {0,2,3,4,5}dq.pop_back();           // 尾部删除: {0,2,3,4}cout << "头部元素: " << dq.front() << endl;  // 0cout << "尾部元素: " << dq.back() << endl;   // 4
}

4. deque 的容量管理

与vector的重要区别:

cpp

void deque_capacity() {deque<int> dq = {1, 2, 3, 4, 5};// 这些与vector相同:cout << "大小: " << dq.size() << endl;        // 5cout << "是否为空: " << dq.empty() << endl;   // false// 这些与vector不同:// dq.capacity();     // ❌ deque没有capacity()方法!// dq.reserve(100);   // ❌ deque没有reserve()方法!// dq.shrink_to_fit();// ❌ deque没有shrink_to_fit()方法!// 但有resize(与vector相同)dq.resize(10);         // 扩容到10个元素,新增元素默认初始化dq.resize(3);          // 缩容到3个元素
}

关键理解: deque的内存管理是自动的,不需要手动控制容量。


5. deque 的元素访问

访问方式与vector完全相同:

cpp

void deque_access() {deque<int> dq = {10, 20, 30, 40, 50};// 所有访问方式都与vector一样cout << dq[2] << endl;        // 30 - 下标访问cout << dq.at(2) << endl;     // 30 - 安全访问cout << dq.front() << endl;   // 10 - 头部元素cout << dq.back() << endl;    // 50 - 尾部元素// 数据指针(但用处不大,因为内存不连续)// int* data = dq.data();    // ❌ deque没有data()方法!
}

6. deque 的修改操作

与vector相同的操作:

cpp

void deque_modifications() {deque<int> dq = {1, 2, 3, 4, 5};// 这些与vector相同:dq.insert(dq.begin() + 2, 99);    // 中间插入: {1,2,99,3,4,5}dq.erase(dq.begin() + 1);         // 删除指定位置: {1,99,3,4,5}dq.clear();                       // 清空所有元素// emplace系列也相同dq.emplace(dq.begin(), 100);      // 中间原地构造dq.emplace_back(200);             // 尾部原地构造dq.emplace_front(300);            // 头部原地构造
}

7. deque 的迭代器

使用方式与vector相同,但实现原理不同:

cpp

void deque_iterators() {deque<int> dq = {10, 20, 30, 40, 50};// 迭代器用法与vector完全一样for (auto it = dq.begin(); it != dq.end(); ++it) {cout << *it << " ";  // 正向遍历}for (auto rit = dq.rbegin(); rit != dq.rend(); ++rit) {cout << *rit << " "; // 反向遍历}// 随机访问迭代器(与vector相同)auto it = dq.begin();cout << it[2] << endl;    // 30 - 支持随机访问it = it + 3;              // 支持算术运算
}

8. deque 的内部实现原理

这才是deque与vector的根本区别!

vector的内存布局:

text

vector: [元素1][元素2][元素3][元素4][元素5]...↑单块连续内存
deque的内存布局(分段数组):

text

deque: 
[指针1] → [元素1][元素2][元素3]   ← 第一个内存块
[指针2] → [元素4][元素5][元素6]   ← 第二个内存块  
[指针3] → [元素7][元素8][元素9]   ← 第三个内存块↑中控器(指针数组)

这种设计的优势:

cpp

void deque_advantages() {deque<int> dq;// 1. 头部插入不会导致元素大范围移动for (int i = 0; i < 1000; i++) {dq.push_front(i);  // 高效!只在当前内存块操作// vector的push_front需要移动所有元素!}// 2. 不需要大块连续内存// vector需要找到足够大的连续内存块// deque可以分散在多块较小的内存中
}

9. 性能对比测试

头部操作性能对比:

cpp

#include <chrono>
using namespace std::chrono;void performance_comparison() {const int COUNT = 100000;// vector头部插入auto start1 = high_resolution_clock::now();vector<int> vec;for (int i = 0; i < COUNT; i++) {vec.insert(vec.begin(), i);  // 每次都要移动所有元素!}auto end1 = high_resolution_clock::now();// deque头部插入auto start2 = high_resolution_clock::now();deque<int> dq;for (int i = 0; i < COUNT; i++) {dq.push_front(i);  // 高效头部插入}auto end2 = high_resolution_clock::now();auto vec_time = duration_cast<milliseconds>(end1 - start1);auto deque_time = duration_cast<milliseconds>(end2 - start2);cout << "vector头部插入时间: " << vec_time.count() << "ms" << endl;cout << "deque头部插入时间: " << deque_time.count() << "ms" << endl;
}

结果: deque的头部操作比vector快几个数量级!


10. deque 的典型应用场景

适合使用deque的场景:

1. 滑动窗口问题

cpp

void sliding_window(const vector<int>& nums, int k) {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) {cout << "窗口最大值: " << nums[dq.front()] << endl;}}
}
2. 任务队列

cpp

class TaskQueue {
private:deque<function<void()>> tasks;mutex mtx;public:// 高优先级任务插到头部void addHighPriorityTask(function<void()> task) {lock_guard<mutex> lock(mtx);tasks.push_front(move(task));}// 普通任务放到尾部void addTask(function<void()> task) {lock_guard<mutex> lock(mtx);tasks.push_back(move(task));}// 从头部取任务执行void executeNext() {lock_guard<mutex> lock(mtx);if (!tasks.empty()) {auto task = move(tasks.front());tasks.pop_front();task();}}
};
3. 撤销操作栈

cpp

class UndoRedoSystem {
private:deque<string> history;size_t max_size;public:UndoRedoSystem(size_t max = 100) : max_size(max) {}void addAction(const string& action) {history.push_back(action);// 保持历史记录不超过最大大小if (history.size() > max_size) {history.pop_front();  // 移除最旧的操作}}string undo() {if (history.empty()) return "";string action = history.back();history.pop_back();return action;}
};

11. deque 的注意事项

1. 内存局部性比vector差

cpp

void memory_locality() {vector<int> vec(1000);deque<int> dq(1000);// vector的内存访问更连续,缓存命中率更高for (int i = 0; i < 1000; i++) {vec[i] = i;  // 连续内存访问,缓存友好}for (int i = 0; i < 1000; i++) {dq[i] = i;   // 可能跨越不同内存块,缓存不友好}
}

2. 迭代器比vector复杂

cpp

void iterator_complexity() {deque<int> dq = {1, 2, 3, 4, 5};auto it = dq.begin();// 虽然接口相同,但内部实现更复杂it++;           // 可能需要检查是否跨越内存块边界it = it + 10;   // 计算更复杂,需要确定目标内存块
}


12. 总结

选择指南:deque vs vector

使用 deque 当:

  • ✅ 需要频繁在头部和尾部插入删除

  • ✅ 作为队列或双端队列使用

  • ✅ 内存碎片化严重,找不到大块连续内存

使用 vector 当:

  • ✅ 主要进行尾部操作

  • ✅ 需要最高性能的随机访问

  • ✅ 重视缓存局部性

  • ✅ 需要手动控制内存分配

性能对比总结:

操作vectordeque
尾部插入删除⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
头部插入删除⭐⭐⭐⭐⭐
随机访问⭐⭐⭐⭐⭐⭐⭐⭐⭐
内存效率⭐⭐⭐⭐⭐⭐⭐⭐

一句话总结:

deque = vector的随机访问 + list的高效头尾操作 - 连续内存的优势

deque在特定场景下是非常有用的工具,理解它的内部原理有助于在合适的时候选择它!

http://www.dtcms.com/a/578769.html

相关文章:

  • 什么样的国家自然科学基金能够中标?
  • 算法322. 零钱兑换
  • 8818网站建设江门关键词优化排名
  • 网站可以个人备案吗弄美团网站的一般一个做赚多少钱
  • 自己做的网站和ie不兼容衡阳县住房和城乡建设局网站
  • 外贸推广网站建设公司装修设计
  • 免费网页设计作业素材搜索引擎优化应注意什么
  • seo站点山东省建设业协会网站
  • 化妆品网站建设描述wordpress数据爬虫
  • 如何修改网站后台密码免费软件下载平台
  • 【八股】更新
  • 数据统计网站精准客户截流软件
  • Facebook 私域运营体系构建指南:从引流到转化的系统化方法
  • 成都门户网站壹六八信息科技网站建设
  • 餐厅网站源码wordpress 阿里云虚拟主机
  • 对话式深度学习基础入门-机器学习 vs 深度学习
  • 沧州市网站企业推广方式有哪些
  • 网站开发的方法有哪些手机做直播官方网站
  • 10.29 JS学习13
  • 网站建设中英文表述手机小说网站源码
  • 建行官网网站综合网站有哪些
  • 360云盘做服务器建设网站开源软件开发平台
  • 免费的网站模版下载360指数官网
  • 没网站域名可以做备案吗免费搭网站
  • 成都百度网站排名优化系统管理下载
  • 十三、系统集成springsecurity
  • cms网站访问人数汕头企业网站建设流程
  • 微信小程序开发——第二章:微信小程序开发环境搭建
  • 一个企业网站需要多少钱公司做网站需要哪些
  • 达妙电机卖断货openarm需求强劲-背后关键技术解析