C++中std::deque详解和实战工程代码示例

C++中std::deque详解和实战工程代码示例

std::deque(双端队列)是 C++ 标准库中的一个序列容器,与 std::vector 类似,但它支持从头部和尾部高效地插入和删除元素。它底层采用分段连续空间实现,兼具灵活性与性能。


一、基本特性

特性描述
随机访问支持下标访问(operator[]at()
快速头尾操作push_frontpush_back 效率高,优于 vector 的头部插入
分段存储结构非一块连续内存,适合频繁的插入删除场景
迭代器失效规则插入删除可能导致部分迭代器失效,需小心

二、使用注意事项(易错点)

1. vector 的差异

  • std::deque 并不保证所有元素在一块连续内存中存储,不能通过 &deque[0] 获取整个数组地址。
  • 不适合与 C 风格 API 一起使用(比如 memcpy(&deque[0], ...) 可能导致未定义行为)。

2. 迭代器失效

  • 插入或删除任意位置的元素都会使所有迭代器失效,不同于 vector 只在 reallocation 时失效。
std::deque<int> dq = {1, 2, 3, 4};
auto it = dq.begin();
dq.push_front(0); // it 现在已失效!

3. 频繁中间插入性能低

  • 插入/删除位于中间位置的元素效率低,需移动大量元素。
  • 如需频繁中间插入,建议使用 std::list

4. 容量管理

  • 没有 capacity() 函数(不像 vector),不能预留空间,使用方式略有不同。

5. 对象构造开销

  • 每次插入都可能涉及对象构造和移动,注意对象拷贝开销。

三、常用操作代码示例

示例 1:基本使用

#include <iostream>
#include <deque>int main() {std::deque<int> dq;dq.push_back(1);   // 尾部插入dq.push_front(0);  // 头部插入dq.push_back(2);for (int val : dq)std::cout << val << " ";  // 输出:0 1 2dq.pop_front();  // 删除头部dq.pop_back();   // 删除尾部std::cout << "\nFront: " << dq.front();  // 输出:1std::cout << "\nBack: " << dq.back();    // 输出:1
}

示例 2:模拟滑动窗口(典型应用)

#include <deque>
#include <vector>
#include <iostream>std::vector<int> maxSlidingWindow(const std::vector<int>& nums, int k) {std::deque<int> dq;  // 存索引std::vector<int> result;for (int i = 0; i < nums.size(); ++i) {while (!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;
}

四、实际应用场景

场景使用原因
滑动窗口算法快速删除/插入头尾元素
限长队列(日志、缓存)自动弹出旧元素,控制内存
多线程任务队列(需加锁)支持双端插入,配合 mutex 使用
状态机缓冲器记录有限长度状态序列

五、工程应用实战

下面是两个典型 std::deque 实战场景的完整示例代码,适合用于滑动窗口最大值算法和限长队列(比如日志或缓存)实现。

示例一:滑动窗口最大值(单调队列优化)

用于处理如:[1,3,-1,-3,5,3,6,7],滑动窗口大小 k=3 时,每个窗口内的最大值。

功能说明:

  • 保持一个单调递减队列(deque中存下标)。
  • 窗口滑动时移除已滑出的元素。
  • 每次窗口满了就将最大值加入结果。

示例代码:

#include <iostream>
#include <vector>
#include <deque>std::vector<int> maxSlidingWindow(const std::vector<int>& nums, int k) {std::deque<int> dq;std::vector<int> result;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);std::cout << "滑动窗口最大值:";for (int val : result)std::cout << val << " ";  // 输出:3 3 5 5 6 7std::cout << std::endl;
}

示例二:限长队列(固定大小缓存或日志)

模拟一个最大容量为 N 的队列,插入新元素时若超过容量,自动从头部弹出旧元素。

功能说明:

  • 封装成 LimitedQueue<T> 模板类
  • 支持 push()pop()size()front()back() 等基本操作

示例代码:

#include <iostream>
#include <deque>template <typename T>
class LimitedQueue {
public:LimitedQueue(size_t capacity) : max_size(capacity) {}void push(const T& value) {if (dq.size() >= max_size)dq.pop_front();  // 超出容量,弹出旧元素dq.push_back(value);}void print() const {for (const auto& item : dq)std::cout << item << " ";std::cout << "\n";}size_t size() const { return dq.size(); }private:std::deque<T> dq;size_t max_size;
};int main() {LimitedQueue<int> q(5);  // 最多保存 5 个元素for (int i = 1; i <= 10; ++i) {q.push(i);std::cout << "插入 " << i << " 后队列内容:";q.print();}
}

输出示例:

插入 1 后队列内容:1 
插入 2 后队列内容:1 2 
插入 3 后队列内容:1 2 3 
插入 4 后队列内容:1 2 3 4 
插入 5 后队列内容:1 2 3 4 5 
插入 6 后队列内容:2 3 4 5 6 
插入 7 后队列内容:3 4 5 6 7 
...

六、与其他容器对比

特性vectordequelist
随机访问
快速尾部插入✅(均摊常数)
快速头部插入❌(O(n))
中间插入/删除❌(慢)❌(稍快)✅(快)
内存连续性❌(分段)

七、建议与最佳实践

  • 推荐用于: 需要双端插入/删除,且访问频率较高的场景。
  • 避免: 中间频繁插入、与 C 接口配合使用。
  • 调试时: 注意调试器中 deque 不总能完整显示所有元素(因为分段结构)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/86684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AI大模型入门指南】概念与专有名词详解 (二)

【AI大模型入门指南】概念与专有名词详解 &#xff08;二&#xff09; 一 、前言 当你和聊天机器人聊得天花乱坠时&#xff0c;当你用文字让AI生成精美图片时&#xff0c;当手机相册自动帮你分类照片时 —— 这些看似智能的操作背后&#xff0c;都藏着 AI 大模型的身影。 本…

AIStor 的模型上下文协议 (MCP) 服务器:管理功能

在本系列的上一篇博文中&#xff0c;我们讨论了 MinIO AIStor 的模型上下文协议 (MCP) 服务器的基本用户级功能。我们学习了如何使用人类语言命令查看存储桶的内容、分析对象并标记它们以便将来处理&#xff0c;以及如何通过 LLM&#xff08;例如 Anthropic Claude&#xff09;…

期权末日轮实值期权盈利未平仓怎么办?

本文主要介绍期权末日轮实值期权盈利未平仓怎么办&#xff1f;期权末日轮实值期权盈利未平仓该怎么办&#xff0c;需要明确几个关键点&#xff1a;末日轮指的是期权到期日临近的时候&#xff0c;通常指最后一周&#xff0c;尤其是最后一天&#xff0c;这时候时间价值衰减很快&a…

C++/Qt 联合编程中的定时器使用陷阱:QObject::startTimer 报错详解

在 Qt 开发中&#xff0c;QTimer 是一个常用的工具类&#xff0c;用于处理定时事件。但不少开发者在 C/Qt 联合编程&#xff0c;尤其是在工具类、静态类、线程中使用定时器时&#xff0c;会遇到如下令人困惑的报错&#xff1a; QObject::startTimer: Timers can only be used …

CentOS7.9 查询运维安全日志,排查恶意用户

1、查看系统版本 cat /etc/redhat-release uname -a 2、查看所有账号 cat /etc/shadow 3、修改 root 密码 passwd 3、查看账号ID id jinzhi 4、查看登录日志 lastlog 5、查看操作日志 cat .bash_history sudo cat /home/yunwei/.bash_history sudo grep root /va…

多模态大语言模型arxiv论文略读(117)

Training-free Zero-shot Composed Image Retrieval via Weighted Modality Fusion and Similarity ➡️ 论文标题&#xff1a;Training-free Zero-shot Composed Image Retrieval via Weighted Modality Fusion and Similarity ➡️ 论文作者&#xff1a;Ren-Di Wu, Yu-Yen L…

如何正确的配置eureka server集群

将 Eureka Server 实例的 hostname 都配置成相同的值&#xff0c;在 Eureka Server 集群环境下同样是不推荐且通常会导致严重问题的&#xff0c; 核心问题&#xff1a;Eureka Server 集群的工作机制 Eureka Server 集群通过相互注册&#xff08;Peering&#xff09;来实现高可…

AI支持下的-ArcGIS数据处理、空间分析、可视化及多案例综合应用

查看原文>>> 从入门到精通-AI支持下的-ArcGIS数据处理、空间分析、可视化及多案例综合应用 结合ArcGIS和GPT的优势&#xff0c;本文重点进行AI大模型应用、ArcGIS工作流程及功能、Prompt使用技巧、AI助力工作流程、AI助力数据读取与处理、AI助力空间分析、AI助力遥感…

vue3-ts: v-model 和 props 的关系

在 Vue.js 中&#xff0c;v-model 是一个语法糖&#xff0c;它实际上是 :value 和 input 事件的组合。 当你使用 v-model 绑定一个组件时&#xff0c;默认情况下&#xff0c;组件会通过 props 接收 value 这个 prop&#xff0c; 并通过触发 input 事件来更新父组件中的数据。 …

学车笔记 变挡

超15就可以加一档了 有些人对手动挡的档位有一些误解_哔哩哔哩_bilibili 献给所有新司机.开手动档摆脱顿挫的根本方法.学会看转速!没那么复杂!_哔哩哔哩_bilibili 减速到怠速降一档

STM32的DMA简介

STM32的DMA简介 一、DMA概述 DMA&#xff08;Direct Memory Access&#xff0c;直接存储器存取&#xff09;是一种硬件机制&#xff0c;它允许外设和存储器之间或者存储器和存储器之间进行高速数据传输&#xff0c;而无需CPU的干预。这种机制可以极大地节省CPU资源&#xff0c…

Spring-AOP知识点

一、AOP简介 1.AOP概念 2.AOP思想实现方案 3.AOP相关概念 二、基于xml配置AOP 1.快速入门 2.AOP配置详解 3.AOP原理剖析 三、基于注解配置AOP 1.快速入门 2.注解方式AOP配置详解 抽取切点表达式

Java@Data 与 @NotNull 注解冲突问题

第一章&#xff1a;核心概念解析 1. Data&#xff08;Lombok 提供&#xff09; 自动生成以下方法&#xff1a; gettersettertoString()equals()hashCode() 简化实体类编写&#xff0c;提高开发效率。 示例&#xff1a; import lombok.Data;Data public class User {private…

离线部署openstack 2024.1 glance

控制节点镜像服务 离线下载 apt install --download-only glancemkdir /controller/glance mv /var/cache/apt/archives/*.deb /controller/glance/ dpkg -i /controller/glance/*.deb在一个控制节点操作 CREATE DATABASE glance; GRANT ALL PRIVILEGES ON glance.* TO glan…

.NET AOT 详解

简介 AOT&#xff08;Ahead-Of-Time Compilation&#xff09;是一种将代码直接编译为机器码的技术&#xff0c;与传统的 JIT&#xff08;Just-In-Time Compilation&#xff09;编译方式形成对比。在.NET 中&#xff0c;AOT 编译可以在应用发布时将 IL&#xff08;中间语言&…

博客系统自动化测试

基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架构建的个人博客系统&#xff0c;通过分层架构实现高效协作&#xff1a;Spring负责依赖注入与事务管理&#xff0c;Spring MVC处理HTTP请求分发&#xff0c;MyBatis完成数据持久化操作。系统包含以下核心功能模块…

animate.css详解:轻松实现网页动画效果

前言 在网页设计中&#xff0c;动画效果不仅仅是视觉上的装饰&#xff0c;更是提升用户体验的重要元素。animate.css 作为一个轻量级的 CSS 动画库&#xff0c;提供了丰富的预设动画效果&#xff0c;本文将探讨 animate.css 使用方法以及在实际项目中的应用案例&#xff0c;帮助…

【多智能体】基于嵌套进化算法的多代理工作流

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本专栏《人工智能》旨在记录最新的科研前沿&#xff0c;包括大模型、具身智能、智能体等相关领域&#xff0c;期待与你一同探索、学习、进步&#xff0c;一起卷起来叭&#xff…

电源知多少?LDO VS DCDC((下)

首先补充几个上一节没有提到的知识&#xff0c;我们通常说的DCDC同步整流是指什么&#xff1f; 同步是指采用通态电阻极低的专用功率MOS来取代整流二极管以降低整流损耗&#xff0c;&#xff0c;但是同步整流有以下两点需要注意&#xff1a;1、MOS在导通之后的压降比较低&…

数组方法_push()/pop()/数组方法_shift()/unshift()

push 方法用于在数组的末端添加一个或多个元素&#xff0c;并返回添加新元 素后的数组长度。注意&#xff0c;该方法会改变原数组 var arr [];arr.push("颤三") // 1arr.push(itbaizhan) // 2arr.push(true, {}) // 4arr // [颤三 , itbaizhan, true, {}] pop 方法用…