【C++入门到精通】C++入门 —— deque(STL)
阅读导航
- 前言
- 一、deque简介
- 1. 概念
- 2. 特点
- 二、deque使用
- 1. 基本操作(增、删、查、改)
- 2. 底层结构
- 三、deque的缺陷
- 四、 为什么选择deque作为stack和queue的底层默认容器
- 总结
- 温馨提示
前言
文章绑定了VS平台下std::deque的源码,大家可以下载了解一下😍
前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的命名空间的一些知识点以及关于C++的缺省参数、函数重载,引用 和 内联函数也认识了什么是类和对象以及怎么去new一个 ‘对象’ ,以及学习了几个STL的结构也相信大家都掌握的不错,接下来博主将会带领大家继续学习有关C++比较重要的知识点—— deque(STL)。下面话不多说坐稳扶好咱们要开车了😍
一、deque简介
1. 概念
(官方文档介绍)
在C++中,deque(双端队列)是一种容器。deque是缩写形式,表示"double-ended queue",即双向队列。deque是C++标准库提供的一种方便、高效的双向队列容器,提供了在两端进行插入和删除操作的能力,同时支持随机访问。
2. 特点
-
双向访问:deque允许在队列的两端进行插入和删除操作。这意味着你可以在队列的头部和尾部同时执行插入和删除操作,而不仅仅限制在一端。
-
动态大小:deque的大小是动态调整的,它可以根据需要自动增加或减少。这使得deque能够灵活地应对不同的数据量和操作需求。
-
高效插入和删除:与vector相比,在deque的头部和尾部进行插入和删除操作的时间复杂度是常数时间O(1)。这意味着deque对于频繁的插入和删除操作非常高效。
-
随机访问:与vector类似,deque也支持随机访问。你可以使用索引来访问deque中的元素,这使得deque在需要快速访问元素的情况下非常有用。
-
存储连续性:deque在内部使用一系列分段的固定大小数组来存储元素。每个分段都具有连续的内存,但这些分段之间不要求连续。这种内部结构使得deque能够提供高效的双向访问和动态大小调整。
二、deque使用
1. 基本操作(增、删、查、改)
-
插入元素:
push_back(value)
: 在deque的尾部插入一个元素。push_front(value)
: 在deque的头部插入一个元素。
-
删除元素:
pop_back()
: 删除deque的尾部元素。pop_front()
: 删除deque的头部元素。
-
访问元素:
front()
: 返回deque的头部元素的引用。back()
: 返回deque的尾部元素的引用。
-
判断容器是否为空:
empty()
: 如果deque为空,则返回true;否则返回false。
-
获取容器的大小:
size()
: 返回deque中元素的个数。
-
清空容器:
clear()
: 删除deque中的所有元素,使其变为空。
-
随机访问元素:
at(index)
: 返回位于指定索引位置的元素的引用,索引从0开始。operator[](index)
: 返回位于指定索引位置的元素的引用。
下面是一些使用deque的基本代码:
#include <iostream>
#include <deque>int main() {std::deque<int> myDeque;// 插入元素myDeque.push_back(10);myDeque.push_front(5);// 访问元素std::cout << "Front element: " << myDeque.front() << std::endl;std::cout << "Back element: " << myDeque.back() << std::endl;// 删除元素myDeque.pop_back();myDeque.pop_front();// 判断容器是否为空if (myDeque.empty()) {std::cout << "Deque is empty" << std::endl;} else {std::cout << "Deque is not empty" << std::endl;}// 获取容器的大小std::cout << "Deque size: " << myDeque.size() << std::endl;// 清空容器myDeque.clear();return 0;
}
2. 底层结构
deque(双端队列)的底层结构通常由多个固定大小的缓冲区组成,每个缓冲区是一个连续的存储块。这些缓冲区通过一个指向前一个缓冲区和一个指向后一个缓冲区的指针进行连接,形成了一个双向链表。
deque的内部缓冲区以分块的形式存储元素。每个缓冲区有一个固定的大小,它通常是2的幂次方,例如512、1024等。缓冲区中的元素被存储在数组中,以保持元素的连续性。
deque的双向链表由一个或多个缓冲区组成,每个缓冲区都包含一个指向前一个缓冲区和一个指向后一个缓冲区的指针。第一个缓冲区的指向前一个缓冲区的指针为空指针,最后一个缓冲区的指向后一个缓冲区的指针也为空指针。
当需要在deque的头部或尾部插入或删除元素时,只涉及到相关缓冲区的操作,而不会涉及其他缓冲区。这种设计使得deque的插入和删除操作时间复杂度为常数级别(O(1))。
⭕部分源代码(详细代码在文件里)
namespace program_queue
{
template <class ContainerAllocator>
struct DequeueProgramRequest_
{typedef DequeueProgramRequest_<ContainerAllocator> Type;DequeueProgramRequest_(): token(0), id(0) {}DequeueProgramRequest_(const ContainerAllocator& _alloc): token(0), id(0) {(void)_alloc;}typedef uint64_t _token_type;_token_type token;typedef uint64_t _id_type;_id_type id;typedef boost::shared_ptr< ::program_queue::DequeueProgramRequest_<ContainerAllocator> > Ptr;typedef boost::shared_ptr< ::program_queue::DequeueProgramRequest_<ContainerAllocator> const> ConstPtr;}; // struct DequeueProgramRequest_
...............................
三、deque的缺陷
⭕deque(双端队列)在大多数情况下是非常高效且灵活的数据结构,但它也有一些缺点需要注意。
-
相对于vector,deque的内存占用更高:deque的底层实现通常由多个固定大小的缓冲区组成。这导致deque在存储元素时可能需要更多的内存空间,相对于vector而言。
-
不支持随机访问:尽管deque支持常数时间的插入和删除操作,但由于内部缓冲区是分块存储的,因此对于deque而言,随机访问的性能较差。在deque中进行随机访问需要根据元素的索引进行计算,而不是直接通过指针操作。
-
迭代器的失效:如果在deque中插入或删除元素,会导致原始deque的迭代器失效。这意味着在操作之前获取的迭代器可能不再有效,需要重新获取或使用新的迭代器。
-
对于大量元素的频繁插入和删除,效率较低:当大量元素需要在deque的中间位置插入或删除时,由于涉及到内存的重分配和数据的移动,deque的性能可能受到影响。
-
可能不利于缓存:由于deque的底层实现包含多个不相邻的缓冲区,这可能导致在连续访问元素时,对CPU缓存的使用效率不高。
四、 为什么选择deque作为stack和queue的底层默认容器
-
高效的插入和删除操作:deque支持在队列的前端和后端进行高效的插入和删除操作。这对于实现stack的后进先出(LIFO)语义和queue的先进先出(FIFO)语义非常重要。
-
避免元素移动:相对于vector来说,deque的插入和删除操作不会引起元素的移动。而对于vector,当在前端插入或删除元素时,需要将整个元素序列进行移动;当在队列的末端插入或删除元素时,除了移动元素,还要考虑重新分配内存空间。这使得deque在插入和删除操作时更加高效。
-
动态大小调整:deque支持动态大小调整,可以根据需要自动增长或缩小存储空间。虽然这也是vector的特性,但由于deque的内部实现不需要进行元素的移动,所以在动态调整大小时,deque的性能更好。
-
同时提供栈和队列功能:由于deque既支持在队列的前端和后端进行插入和删除操作,也提供了随机访问的能力,因此可以同时满足栈和队列的需求。
⭕尽管deque有一些缺点,但这些缺点相对于deque在栈和队列操作中的优势来说是可以接受的。总体而言,deque作为stack和queue的底层默认容器是一个平衡性能和功能的选择。但是,也可以根据具体需要选择其他容器来实现stack和queue,例如vector或list,这取决于具体的使用场景和需求。
总结
首先,我们了解了deque的基本概念和特点,包括多个固定大小的缓冲区、双向链表连接以及高效的插入和删除操作。接着,我们深入探讨了deque的使用方法,包括基本操作和底层结构。其中,我们了解了如何进行增、删、查、改操作,以及deque由多个缓冲区组成的底层实现结构。此外,我们也提及了deque的一些缺陷,如内存占用较高、随机访问效率较低等。最后,我们解释了为何选择deque作为stack和queue的底层默认容器,包括高效的插入和删除操作、避免元素移动、动态大小调整等优势。然而,根据具体需求,我们也可以选择其他容器来实现相同的功能。
⭕总的来说,deque作为一种高效且灵活的数据结构,在栈和队列的实现中发挥着重要作用。通过了解deque的特点和使用方法,读者可以更好地理解和应用这一数据结构,并在实际开发中做出明智的选择。无论是作为stack还是queue的底层容器,deque在提供高效操作的同时,也带来了一些缺陷,因此需要根据具体的场景和需求来选择合适的数据结构。
温馨提示
感谢您对博主文章的关注与支持!在阅读本篇文章的同时,我们想提醒您留下您宝贵的意见和反馈。如果您喜欢这篇文章,可以点赞、评论和分享给您的同学,这将对我提供巨大的鼓励和支持。另外,我计划在未来的更新中持续探讨与本文相关的内容。我会为您带来更多关于C++以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注博主的更新,不要错过任何精彩内容!
再次感谢您的支持和关注。我们期待与您建立更紧密的互动,共同探索C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
相关文章:

【C++入门到精通】C++入门 —— deque(STL)
阅读导航 前言一、deque简介1. 概念2. 特点 二、deque使用1. 基本操作(增、删、查、改)2. 底层结构 三、deque的缺陷四、 为什么选择deque作为stack和queue的底层默认容器总结温馨提示 前言 文章绑定了VS平台下std::deque的源码,大家可以下载…...

Codeforces Round 893 (Div. 2) D.Trees and Segments
原题链接:Problem - D - Codeforces 题面: 大概意思就是让你在翻转01串不超过k次的情况下,使得a*(0的最大连续长度)(1的最大连续长度)最大(1<a<n)。输出n个数&…...

SpringBoot + Vue 前后端分离项目 微人事(九)
职位管理后端接口设计 在controller包里面新建system包,再在system包里面新建basic包,再在basic包里面创建PositionController类,在定义PositionController类的接口的时候,一定要与数据库的menu中的url地址到一致,不然…...
【业务功能篇71】Cglib的BeanCopier进行Bean对象拷贝
选择Cglib的BeanCopier进行Bean拷贝的理由是, 其性能要比Spring的BeanUtils,Apache的BeanUtils和PropertyUtils要好很多, 尤其是数据量比较大的情况下。 BeanCopier的主要作用是将数据库层面的Entity转化成service层的POJO。BeanCopier其实已…...

让eslint的错误信息显示在项目界面上
1.需求描述 效果如下 让eslint中的错误,显示在项目界面上 2.问题解决 1.安装 vite-plugin-eslint 插件 npm install vite-plugin-eslint --save-dev2.配置插件 // vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue import e…...

手摸手带你实现一个开箱即用的Node邮件推送服务
目录 编辑 前言 准备工作 邮箱配置 代码实现 服务部署 使用效果 题外话 写在最后 相关代码: 前言 由于邮箱账号和手机号的唯一性,通常实现验证码的校验时比较常用的两种方式是手机短信推送和邮箱推送,此外,邮件推送服…...

【Linux网络】网络编程套接字 -- 基于socket实现一个简单UDP网络程序
认识端口号网络字节序处理字节序函数 htonl、htons、ntohl、ntohs socketsocket编程接口sockaddr结构结尾实现UDP程序的socket接口使用解析socket处理 IP 地址的函数初始化sockaddr_inbindrecvfromsendto 实现一个简单的UDP网络程序封装服务器相关代码封装客户端相关代码实验结…...
Python学习笔记第六十四天(Matplotlib 网格线)
Python学习笔记第六十四天 Matplotlib 网格线普通网格线样式网格线 后记 Matplotlib 网格线 我们可以使用 pyplot 中的 grid() 方法来设置图表中的网格线。 grid() 方法语法格式如下: matplotlib.pyplot.grid(bNone, whichmajor, axisboth, )参数说明:…...

机器学习与模式识别3(线性回归与逻辑回归)
一、线性回归与逻辑回归简介 线性回归主要功能是拟合数据,常用平方误差函数。 逻辑回归主要功能是区分数据,找到决策边界,常用交叉熵。 二、线性回归与逻辑回归的实现 1.线性回归 利用回归方程对一个或多个特征值和目标值之间的关系进行建模…...

vue启动配置npm run serve,动态环境变量,根据不同环境访问不同域名
首先创建不同环境的配置文件,比如域名和一些常量,创建一个env文件,先看看文件目录 env.dev就是dev环境的域名,.test就是test环境域名,其他同理,然后配置package.json文件 {"name": "require-admin&qu…...
HTML <strike> 标签
HTML5 中不支持 <strike> 标签在 HTML 4 中用于定义删除线文本。 定义和用法 <strike> 标签可定义加删除线文本定义。 浏览器支持 元素ChromeIEFirefoxSafariOpera<strike>YesYesYesYesYes 所有浏览器都支持 <strike> 标签。 HTML 与 XHTML 之间…...
数学建模-模型详解(1)
规划模型 线性规划模型: 当涉及到线性规划模型实例时,以下是一个简单的示例: 假设我们有两个变量 x 和 y,并且我们希望最大化目标函数 Z 5x 3y,同时满足以下约束条件: x > 0y > 02x y < 10…...
MySQL 数据库表的基本操作
一、数据库表概述 在数据库中,数据表是数据库中最重要、最基本的操作对象,是数据存储的基本单位。数据表被定义为列的集合,数据在表中是按照行和列的格式来存储的。每一行代表一条唯一的记录,每一列代表记录中的一个域。 二、数…...

企业微信电脑端开启chrome调试
首先: Mac端调试开启的快捷键:control shift command d Window端调试开启的快捷键: control shift alt d 这边以Mac为例,我们可以在电脑顶部看到调试的入口: 然后我们点击 『浏览器、webView相关』菜单,勾选上…...

Maven官网下载配置新仓库
1.Maven的下载 Maven的官网地址:Maven – Download Apache Maven 点击Download,查找 Files下的版本并下载如下图: 2.Maven的配置 自己在D盘或者E盘创建一个文件夹,作为本地仓库,存放项目依赖。 将下载好的zip文件进行解…...
银河麒麟V10 达梦安装教程
安装前先准备要安装包,包需要需要区分X86和arm架构。 版本为:dm8_20230419_FTarm_kylin10_sp1_64.iso 达梦数据库下载地址: https://www.aliyundrive.com/s/Qm7Es5BQM5U 第一步创建用户 su - root 1. 创建安装用户组 dminstall。 groupad…...

Python操作MongoDB数据库
安装MongoDB库 pip install pymongopython 代码 Author: tkhywang 2810248865qq.com Date: 2023-08-21 10:22:30 LastEditors: tkhywang 2810248865qq.com LastEditTime: 2023-08-21 11:17:45 FilePath: \PythonProject02\MongoDB 数据库.py Description: 这是默认设置,请设置…...

《HeadFirst设计模式(第二版)》第十一章代码——代理模式
代码文件目录: RMI: MyRemote package Chapter11_ProxyPattern.RMI;import java.rmi.Remote; import java.rmi.RemoteException;public interface MyRemote extends Remote {public String sayHello() throws RemoteException; }MyRemoteClient packa…...

QT的工程文件认识
目录 1、QT介绍 2、QT的特点 3、QT模块 3.1基本模块 3.2扩展模块 4、QT工程创建 1.选择应用的窗体格式 2.设置工程的名称与路径 3.设置类名 4.选择编译器 5、QT 工程解析 xxx.pro 工程配置 xxx.h 头文件 main.cpp 主函数 xxx.cpp 文件 6、纯手工创建一个QT 工程…...

typeScript安装及TypeScript tsc 不是内部或外部命令,也不是可运行的程序或批处理文件解决办法
一、typeScript安装: 1、首先确定系统中已安装node, winr 输入cmd 打开命令行,得到版本号证明系统中已经安装node node -v //v18.17.0 2、使用npm 全局安装typeScript # 全局安装 TypeScript npm i -g typescript 二、检查是否安装成功ts #检查t…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...