C++ STL之deque的理解及使用

文章目录

  • 1. 介绍
  • 2. 实现原理(简单理解)
  • 3. deque的优缺点
  • 4. deque类的使用
    • 4.1 deque类对象的构造函数
    • 4.2 deque类对象的容量操作
    • 4.3 deque类对象的修改操作
    • 4.4 deque类对象的访问及遍历操作


1. 介绍

deque(双端队列):是一种双开口的连续空间的容器,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高,且支持下标访问。

在这里插入图片描述

2. 实现原理(简单理解)

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:

在这里插入图片描述

这里如果中控数组满了,扩容的代价是很低的,只需要将指针变量数组扩容即可。

双端队列底层是一段假象的连续空间,实际是分段连续的,所以维护其整体连续以及随机访问的假象的任务就落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:

在这里插入图片描述

3. deque的优缺点

  • 与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是比 vector 高的。
  • 与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段,且支持下标访问。

但是,deque 有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑 vector 和 list,deque 的应用并不多,而目前能看到的一个应用就是,STL 用其作为 stack 和 queue 的底层数据结构。

为什么选择deque作为stack和queue的底层默认容器?

stack 是一种后进先出的特殊线性数据结构,因此只要具有push_back()pop_back()操作的线性结构,都可以作为 stack 的底层容器,比如 vector 和 list 都可以;queue 是先进先出的特殊线性数据结构,只要具有push_back()pop_front()操作的线性结构,都可以作为 queue 的底层容器,比如 list。但是 STL 中对 stack 和 queue 默认选择 deque 作为其底层容器,主要是因为:

  1. stack 和 queue 不需要遍历(因此 stack 和 queue 没有迭代器),只需要在固定的一端或者两端进行操作,使用deque效率很高。

  2. 在 stack 中元素增长时,deque 比 vector 的效率高(扩容时不需要搬移大量数据);queue 中的元素增长时,deque 不仅效率高,而且内存使用率高。

所以 stack 和 queue 结合了 deque 的优点,而完美的避开了其缺陷。

4. deque类的使用

4.1 deque类对象的构造函数

(constructor)构造函数代码功能说明
explicit deque (const allocator_type& alloc = allocator_type());(默认构造函数)构造一个空的容器,没有任何元素。
explicit deque (size_type n, const value_type& val = value_type(), onst allocator_type& alloc = allocator_type());(填充构造函数)构造一个包含 n 个元素的容器,每个元素都是 val 的副本。
template <class InputIterator>
deque (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());
(范围构造函数)根据范围[first, last)中的元素构造一个容器,容器中的元素个数与该范围中的元素个数相同,并且顺序相同。
deque (const deque& x);(拷贝构造函数)构造一个容器,其中的每个元素都是 x 中对应元素的副本,顺序相同。

4.2 deque类对象的容量操作

函数名称代码功能说明
sizesize_type size() const;返回 deque 容器中元素个数。
max_sizesize_type max_size() const;返回 deque 容器可以容纳最大元素个数。
resizevoid resize (size_type n, value_type val = value_type());调整容器的大小,使其包含 n 个元素。如果 n 小于当前容器的大小,容器的内容将被减少到前 n 个元素,移除超出范围的元素。如果 n 大于当前容器的大小,容器的内容将通过在末尾插入足够数量的元素来扩展到大小为 n。如果指定了 val,新插入的元素将被初始化为 val 的副本;否则,它们将进行值初始化。
emptybool empty() const;返回 deque 容器是否为空(即其大小是否为 0)。

4.3 deque类对象的修改操作

函数名称代码功能说明
push_backvoid push_back (const value_type& val);在 deque 容器开头插入一个新元素 val。
push_frontvoid push_front (const value_type& val);在 deque 容器开头插入一个新元素 val。
pop_backvoid pop_back();删除最后一个元素。
pop_frontvoid pop_front();删除第一个元素。
insertiterator insert (iterator position, const value_type& val);
void insert (iterator position, size_type n, const value_type& val);
template <class InputIterator>
void insert (iterator position, InputIterator first, InputIterator last);
在指定位置 position 之前插入新元素 val、n 个 val或者迭代器区间[first, last)范围的元素。
eraseiterator erase (iterator position);
iterator erase (iterator first, iterator last);
删除 position 位置的元素或者迭代器区间[first, last)范围的元素。
swapvoid swap (deque& x);与另一个相同类型的 deque 容器 x 交换内容。存在一个同名的非成员函数 swap,重载该算法的意义是优化交换时间。
clearvoid clear();从 deque 容器中移除所有元素,使容器的大小变为0。

4.4 deque类对象的访问及遍历操作

函数名称代码功能说明
operator[]reference operator[] (size_type n);
const_reference operator[] (size_type n) const;
返回 deque 容器中位置 n 处的元素的引用。
at reference at (size_type n);
const_reference at (size_type n) const;
返回 deque 容器中位置 n 处的元素的引用。该函数会自动检查 n 是否在 deque 容器的有效元素范围内,如果不在范围内(即 n 大于或等于向量的大小),则抛出 out_of_range 异常。这与成员运算符 operator[] 不同,后者不进行边界检查。
frontreference front();
const_reference front() const;
返回 deque 容器中第一个元素的引用。
backreference back();
const_reference back() const;
返回 deque 容器中最后一个元素的引用。

遍历操作

遍历操作

#include <iostream>
#include <deque>int main()
{std::deque<int> dq(10, 100);// 1.普通下标遍历for (size_t i = 0; i < dq.size(); ++i)std::cout << dq[i] << " ";std::cout << '\n';// 2.迭代器遍历for (std::deque<int>::iterator it = dq.begin(); it != dq.end(); ++it)std::cout << *it << " ";std::cout << '\n';// 3.范围for遍历for (auto e : dq)std::cout << e << " ";std::cout << '\n';return 0;
}

输出结果

在这里插入图片描述

说明

  1. 普通下标遍历:
    在此代码段中,通过使用普通的下标操作符 [],从索引 0 开始,逐个访问 deque 容器dq 中的元素,并将其打印出来。循环变量 i 从 0 递增到 dq.size()-1,并使用 dq[i] 访问每个元素。最后,打印一个换行符。
  2. 迭代器遍历:
    在此代码段中,使用迭代器进行遍历。首先,通过 dq.begin() 获取 deque 容器 dq 的起始迭代器,通过 dq.end() 获取 deque 容器 dq 的结束迭代器。然后,通过迭代器 it 遍历从起始迭代器到结束迭代器之间的所有元素,并使用 *it 打印每个元素的值。最后,打印一个换行符。
  3. 范围for循环遍历:
    在此代码段中,使用范围for循环对 deque 容器 dq 进行遍历。对于 deque 容器 dq 中的每个元素,将其依次赋值给循环变量 e,然后打印出 e 的值。此方法不需要显式地使用迭代器或下标来访问向量的元素,因为范围for循环会自动处理迭代过程,并在每次迭代中将元素赋值给循环变量。最后,打印一个换行符。

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

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

相关文章

PiflowX-JdbcCatalog组件

JdbcCatalog组件 组件说明 通过JDBC协议将Flink连接到关系数据库,目前支持Postgres Catalog和MySQL Catalog。 计算引擎 flink 组件分组 Catalog 端口 Inport&#xff1a;默认端口 outport&#xff1a;默认端口 组件属性 名称展示名称默认值允许值是否必填描述例子c…

系统学习Python——类(class):静态方法(staticmethod)和类方法(classmethod)-[实例:用类方法计数]

分类目录&#xff1a;《系统学习Python》总目录 文章《系统学习Python——类&#xff08;class&#xff09;&#xff1a;静态方法&#xff08;staticmethod&#xff09;和类方法&#xff08;classmethod&#xff09;-[实例&#xff1a;用静态方法计数]》中使用了静态方法对类生…

MATLAB curve fitting toolbox没有怎么办?

版本&#xff1a;MATLAB R2023b 如果在安装MATLAB时仅仅选择了安装MATLAB&#xff0c;而并未选择其他选项&#xff0c;则在进入MATLAB后会发现顶部的APP栏中无法找到曲线拟合工具箱。 本人跟随MATLAB中的教程进行下载时&#xff0c;出现了如下报错&#xff1a; 最终解决方案&a…

【SVD生成视频+可本地部署】ComfyUI使用(二)——使用Stable Video Diffusion生成视频 (2023.11开源)

SVD官方主页 &#xff1a; Huggingface | | Stability.ai || 论文地址 huggingface在线运行demo : https://huggingface.co/spaces/multimodalart/stable-video-diffusion SVD开源代码&#xff1a;Github&#xff08;含其他项目&#xff09; || Huggingface 在Comfyui使用&…

【博士论文写作 笔记02】研究挑战、研究目标、研究方案和研究内容的区别?

文章目录 一、声明二、介绍三、示例&#xff08;涉及的博士论文未争取作者同意之前暂不公布&#xff09; 一、声明 未完部分后续会更新 二、介绍 在博士论文写作中研究挑战、研究目标、研究方案和研究内容需要做详尽的阐述&#xff0c;但是几个概念很容易混淆&#xff0c;我…

MIT_线性代数笔记:线性代数常用概念及术语总结

目录 1.系数矩阵2.高斯消元法3.置换矩阵 Permutation4.逆矩阵 Inverse 1.系数矩阵 线性代数的基本问题就是解 n 元一次方程组。例如&#xff1a;二元一次方程组 2 x − y 0 − x 2 y 3 \begin{align*} & 2x - y 0\\ & -x2y 3 \end{align*} ​2x−y0−x2y3​ 写成…

通过strings二进制文件分析工具排查 version ‘GLIBC_2.25‘ not found 报错

strings命令简介 strings命令用于打印文件中可打印字符串, 可以打印文本文件、可执行程序&#xff0c;库文件等。一般用于分析可执行程序和库文件。strings命令较为常用的功能有以下两种 查看系统的GLIBC版本和目标文件的依赖的GLIBC版本&#xff0c;当系统的GLIBC版本与目标文…

谷歌公布一个可以让 AI 进行自我判断输出内容正确性的模型训练框架 ASPIRE

谷歌开发了一款名为 ASPIRE 的训练框架&#xff0c;旨在增强人工智能&#xff08;AI&#xff09;模型的选择性预测能力。这款框架为模型引入了 “可信度” 机制&#xff0c;即模型会输出一系列答案&#xff0c;并为每个答案赋予一个正确概率评分。通过这种方式&#xff0c;ASPI…

经典面试题-死锁

目录 1.什么是死锁&#xff1f; 2.形成死锁的四个必要条件 3.死锁的三种情况 第一种情况&#xff1a; 举例&#xff1a; 举例&#xff1a; 第二种情况&#xff1a;两个线程 两把锁 举例&#xff1a; 第三种情况&#xff1a;N个线程 M把锁 哲学家进餐问题 1.什么是死锁&…

windows11部署linux程序

windows11部署 msys2在windows10系统的安装 https://blog.csdn.net/engineer520/article/details/82192776 MSYS2使用记录——win10系统64位安装msys2最新版&#xff08;msys2-x86_64-20190524.exe&#xff09; _ https://www.cnblogs.com/world-explorer/p/16319426.html C语言…

Unity Asset store下载资源修改位置

Unity Asset Store的资源会随着项目的增长和资源的积累而越来越多。 在本文中&#xff0c;我们将修改Unity Asset Store的默认下载路径。 一、 默认保存路径的问题 当安装unity后&#xff0c;从Unity Asset Store下载资源时&#xff0c;它们通常会被存放在以下默认路径&#…

ThreadLocal使用

在用户每一次发起请求都会在tomcat服务器请求一个新的线程&#xff0c;我们在生成JWT token的时候将登录的用户信息注入到threadlocal中&#xff0c;那么这个线程进行其他请求都会携带着用户信息&#xff0c;我们可以在其他功能中得到当前的登录的用户信息&#xff0c;比如得到…

vue3中使用 vue3-slide-verify 滑块验证登录

在日常项目中我们实现登录的时候&#xff0c;会进行人为操作验证&#xff0c;这里使用滑块验证&#xff0c;常见的验证方式 我们借助插件 vue3-slide-verify 安装 npm install --save vue3-slide-verify 使用 在页面创建组件verification.vue 名字随意写入下面代码 <…

Linux破解密码

破解root密码&#xff08;Linux 7&#xff09; 1、先重启——e 2、Linux 16这一行 末尾加rd.break&#xff08;不要回车&#xff09;中断加载内核 3、再ctrlx启动&#xff0c;进入救援模式 4、mount -o remount&#xff0c;rw /sysroot/——&#xff08;mount挂载 o——opti…

大二下 课程安排

专业选修 web前端开发 信息与网络安全 必修 数据库原理 4 概率论与数理统计 4 软件设计与体系结构 3 编译技术 3 软件设计实践 2 大学体育 1 选修 &#xff08;待更新&#xff09; 目标 大二下一定要好好学习&#xff0c;不然最后总的排名真的就垫底了&#xff0c;大一上…

选择海外云手机需要考虑什么?

随着跨境电商行业的蓬勃发展&#xff0c;企业们纷纷寻找提升平台流量和广告投放效果的方法&#xff0c;这已成为业界的当务之急。传统的宣传模式在国内受到直播和链接带货等新兴方式的冲击&#xff0c;而在国外&#xff0c;类似的趋势也在悄然兴起&#xff0c;呈现出广阔的发展…

Halcon优化模板匹配速度

Halcon优化模板匹配速度 文章目录 Halcon优化模板匹配速度1. 缩小搜索空间2. 使用图像下采样 优化匹配速度可以从两个方面入手&#xff1a;缩小搜索空间和使用图像下采样。本节将分别从这两个方面进行解释。 1. 缩小搜索空间 搜索空间指搜索的范围&#xff0c;它是一个广义的概…

服务器运维小技巧(二)——如何进行监控告警

服务器运维难度高的原因&#xff0c;很大程度是因为服务器一旦出现问题&#xff0c;生产环境的业务就会受到严重影响&#xff0c;极有可能带来难以承担的后果。因此这份工作要求工程师保持高要求的服务质量&#xff0c;能够快速响应问题&#xff0c;及时解决问题。 但是“及时…

google-webrtc 原理

Google WebRtc Android 使用详解(包括客户端和服务端代码) - 知乎 (zhihu.com) 【记】Android使用WebRTC未释放资源导致的内存泄露 - 掘金 (juejin.cn)

Eureka-第一篇

​ 一、Eureka的概述 Eureka的基本概念和作用 Eureka是一个基于REST的服务&#xff0c;主要用于定位运行在AWS域中的中间层服务&#xff0c;以达到负载均衡和中间层服务故障转移的目的。Eureka是Netflix开发的服务发现框架&#xff0c;主要用于解决在云计算环境中动态位置服…