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

【C++】deque的实现原理简单介绍

前言

deque被称为双端队列,它的出现主要是为了结合vectorlist的优点并减小它们的缺点,实际上deque确实结合了vectorlist的优点减小了它们的缺点,但是它的结合也让它自己的优点没有原始的vectorlist那么极致,导致deque变得很中庸,所以deque的应用场景也并没有那么多,它经常被用来作为stackqueue的底层容器

本篇文章我们来一起简单探讨一下deque的实现原理

deque的简单介绍

  • 一、deque的原理介绍
  • 二、deque的一些基本特性
    • 1、deque的随机访问
    • 2、deque的中间插入与删除
  • 三、deque的迭代器
  • 四、deque的优缺点分析
    • 1、优点:
    • 2、缺点:
  • 五、为什么选择deque作为stack和queue的底层默认容器

一、deque的原理介绍

deque(双端队列):是一种双开口的" 连续 "空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高,不太容易造成内存碎片。

在这里插入图片描述

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

当中控数组满了,我们也只需要对中控数组进行扩容,然后拷贝指针就行了,并不需要对真正存储数据的小数组做改动,这大大减少了拷贝数据的个数。

二、deque的一些基本特性

1、deque的随机访问

deque的随机访问有两种情况: 这与deque中的小数组的大小是否固定有关。

  • 假设我们deque中的小数组是固定大小,不能进行扩容,那么我们就可以使用除模运算进行随机访问,假设想要访问的位置是 x x x,第一个数组中的元素个数是 y y y,数组的大小固定为 n n n,想要访问的小数组是从第二个数组开始第 r o w row row个,想要访问的位置在对应小数组的第 c o l col col个。

    我们就可以通过 r o w = ( x − y ) / n row = (x - y)/n row=(xy)/n c o l = ( x − y ) % n col = (x-y)\%n col=(xy)%n从而确定我们想要访问的位置。时间复杂度是 O ( 1 ) O(1) O(1)

  • 假设我们deque的小数组可以扩容,我们的中控数组可以存放一个自定义类型,自定义类型里面有指针也有对应小数组中数据的个数。那么我们就要用从第一个数组的个数 +第二个数组的个数 +第三个数组的长度 + …直到加到某个数组时大于我们想要访问的位置,我们才能确定对应是第几个数组,然后在小数组中进行访问该元素,这样的话时间复杂度就是遍历中控数组,时间复杂度是 O ( n ) O(n) O(n)

2、deque的中间插入与删除

deque的中间插入也有两种情况: 这也与deque中的小数组的大小是否固定有关。

  • 假设我们deque中的小数组是固定大小,不能进行扩容,那么我们在中间位置进行插入或者删除时,就要移动数据,也就是说可能要把一个小数组中的数据移动到另一个小数组里。
  • 假设我们deque中的小数组是不是固定大小的。
    那么我们在中间位置进行插入就可以只对当前的小数组进行扩容然后再进行插入,这样我们就不必对其他小数组中的数据进行移动了
    如果我们对中间的数据进行删除,我们也只需要对当前的小数组进行缩容就进行了,如果小数组中的数据全部被删除了,那可以直接释放掉空间,然后调整中控数组就行了。

总结deque的随机访问与deque的中间插入与删除之间有负相关的作用。当小数组固定时,随机访问效率会变高但是中间位置的插入与删除效率会变低;当小数组不固定大小时,随机访问效率会变低但是中间位置的插入与删除效率会变高。

在STL的SGI版本中对于deque的小数组选择了固定大小,且小数组中可以存储数据的个数是8(这个大小可以通过模板参数进行调整)

三、deque的迭代器

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

在这里插入图片描述

deque的迭代器有四个指针,第一个cur指向小数组中要指向的数据,第二个first指向小数组中的第一个位置,第三个last指向小数组中最后一个数据的下一个,第四个node反向指向中控数组,方便遍历完一个小数组后跳到下一个小数组。

四、deque的优缺点分析

1、优点:

  1. vector比较,deque的优势是:
    • 头部插入和删除时,不需要搬移元素,效率特别高。
    • 在扩容时,也不需要搬移大量的元素,只需要搬移中控数组中的指针就行了。
  2. list比较,deque的优势是:
    • 其底层是连续空间,空间利用率比较高,不需要存储额外字段。
    • 支持随机访问

2、缺点:

  1. 中间的插入删除与随机访问不好抉择,难以两全其美。

  2. 优点没有vectorlist极致,随机访问的速度没有vector快,(vector是真正的连续空间,在计算机硬件中缓存利用率极高,在排序方面这点很重要!!!),中间位置的插入与删除没有list快(list的中间位置的插入与删除是 O ( 1 ) O(1) O(1)),deque需要进行扩容,而list根本不需要扩容

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

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


stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()pop_back()操作的线性结构,都可以作为stack的底层容器,比如vectorlist都可以;

queue是先进先出的特殊线性数据结构,只要具有push_backpop_front操作的线性结构,都可以作为queue的底层容器,比如list。但是STL中对stackqueue默认选择deque作为其底层容器,主要是因为:

  1. stackqueue不需要遍历(因此stackqueue没有迭代器),只需要在固定的一端或者两端进行操作。
  2. stack中元素增长时,dequevector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。两个适配器都结合了deque的优点,而完美的避开了其缺陷。

相关文章:

【C++】deque的实现原理简单介绍

前言 deque被称为双端队列,它的出现主要是为了结合vector和list的优点并减小它们的缺点,实际上deque确实结合了vector和list的优点减小了它们的缺点,但是它的结合也让它自己的优点没有原始的vector和list那么极致,导致deque变得很…...

UWB隧道人员定位技术应用,施工作业安全精准保障

隧道施工的安全不仅关系到工程项目的质量和施工效率,也关系到我国的资金安全、施工人员和人民的生命财产安全。如何有效加强隧道施工的安全管理能力,成为隧道施工企业管理者最关心的问题。国家铁道局在《关于加强铁路隧道工程安全工作的若干意见》中指出…...

15.2 矩阵链乘法

1.代码 public class MatrixChainMultiplication {public static void main(String[] args) { // 在该代码中,我们首先创建了两个n * n的矩阵m和s,分别用于记录最优值和分割点。 其中m 矩阵 通过i j 来显示在i到j的矩阵链中最优解 // // …...

向隐形冠军学习:聚焦人效,用时间管理提效益

注: 本文来源于盖雅工场联合创始人兼CEO 章新波 在2023狮山论坛“ 向隐形冠军学习: 聚焦人效,用时间管理提效益 ”的主题分享。 文|章新波 整理 |盖雅学苑 在人力资源行业以及各大企业,「人效」这个词…...

Protocol Buffers Go Generated Code Guide

Protocol Buffers Go 代码生成指南 本主题准确描述了协议缓冲区编译器为任何给定的协议定义生成的Go代码。 编译器调用 协议缓冲区编译器需要一个插件来生成Go 代码。使用Go 1.16或更高版本安装,方法是运行: go install google.golang.org/protobuf/…...

Python VTK STL 映射三维模型表面距离

目录 前言: 效果: 实现步骤: Code: 前言: 本文介绍了Python VTK映射三维模型表面距离,通过如何使用VTK计算两个三维模型(stl)的表面距离,并将其距离值以颜色映射到模型,可用于对比 两相模型…...

C# 异常处理机制和常见的异常类型

在 C# 中,异常处理是一个非常重要的概念,它可以让我们在程序发生错误时进行有效的处理,使程序具备更好的鲁棒性。C# 异常处理机制基于 try-catch-finally 语句块,其基本用法如下: try {// 可能会抛出异常的代码 } cat…...

【0187】客户端身份验证配置文件视图之pg_hba_file_rules

文章目录 1. 客户端身份验证配置文件视图2. 视图效果相关阅读: 【0179】配置PostgreSQL以允许远程连接 【0180】PG内核通过pg_hba.conf完成客户端认证(1) 【0181】PG内核通过pg_hba.conf完成客户端认证(2)...

模糊层次分析法(FAHP)Python实现

文章目录 理论基础三角模糊数概念参考 Python源码测试 理论基础 \quad 模糊层次分析法( F A H P FAHP FAHP)将模糊理论( F u z z y S e t Fuzzy Set FuzzySet)嵌入到基本层次分析法( A H P AHP AHP)中。 A …...

gdb切换窗口焦点

为了辅助调试,一般会使用layout src,调起TUI显示代码: 然而这种情况下我们写命令很不方便,无法方便地使用上一条命令、退格等。 按动上下左右方向键盘只会移动代码框,然而在伪终端下,可以用鼠标滚轮来上下…...

【Spring Security】 入门实战

文章目录 一、基本概念二、Spring Security第一个程序三、Spring Security没有生效四、修改默认账号密码(appliction.yml)五、修改默认账号密码(配置类)六、Spring Security的三个configure方法七、Spring Security的三种身份的验…...

SpringBoot的Interceptor拦截器的简介和实际使用

拦截器(Interceptor) 概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。 作用:拦截请求,在指定的方法调用前后,根据业务需要执行…...

5个面向Python高级开发者的技巧

使用这些用于自定义类行为、编写并发代码、管理资源、存储和操作数据以及优化代码性能的高级技术来探索 Python 的深度。 本文探讨了 Python 中的五个高级主题,它们可以为解决问题和提高代码的可靠性和性能提供有价值的见解和技术。从允许您在定义类时自定义类行为的…...

Nginx简介

Nginx是什么?可以做什么事情? Nginx是高性能的HTTP和反向代理的web服务器,处理高并发的能力十分强大,能经受高负载的考研,有报告表明能能支持高达50000个并发连接数。 特点 占有内存少:一万个长连接&…...

十五分钟带你学会 Electron

文章目录 什么是 Electron为什么要选择 Electron安装 Electron桌面CSDN实战Electron 基础配置Electron 进程主进程渲染进程主进程与渲染进程的区别主进程与渲染进程的通信 Electron 跨平台问题Electron 部署打包应用程序发布应用程序 Electron 跨端原理总结 什么是 Electron E…...

设计模式-结构型模式之桥接模式

2. 桥接模式 2.1. 模式动机 设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案: 第一种设计方案是为每一种形状…...

软件测试工程师为什么要写测试用例?

软件测试工程师为什么要写测试用例?相信从事软件测试行业的从业者来讲,测试用例并不陌生。因为测试用例不仅仅是一组简单的文档,它包含前提条件、输入、执行条件和预期结果等等重要内容,并且能够完成一定的测试目的和需求。下面本…...

【DAY40】VUE练习

DOS命令: DOS(Disk Operating System)是一种操作系统,它使用命令行界面(Command Prompt)进行交互。在 DOS 中,有一些常用的命令,可以用来定位目录、创建、删除、拷贝文件和目录&…...

实模式的寄存器

实模式的寄存器有8个通用寄存器,分别为AX、BX、CX、DX、SI、DI、BP和SP。通用的意思就是它们之中的大部分可以根据需要用于多种目的。 AX: accumulator,累加寄存器 BX: base,基址寄存器 CX: count,计数寄存器 SI: Source Index&am…...

【UE 控件蓝图】通过键盘选中要点击的按钮 通过Enter键点击

上一篇【UE 控件蓝图】菜单及功能实现博客已经完成了菜单的制作,但是我们只能通过鼠标来点击菜单选项,本篇博客实现的是能够通过键盘的上下键来选中按钮,然后按下“Enter”键来实现点击按钮的效果。 效果 可以看到并没有移动鼠标也可以通过…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...

fast-reid部署

配置设置&#xff1a; 官方库链接&#xff1a; https://github.com/JDAI-CV/fast-reid# git clone https://github.com/JDAI-CV/fast-reid.git 安装依赖&#xff1a; pip install -r docs/requirements.txt 编译&#xff1a;切换到fastreid/evaluation/rank_cylib目录下&a…...

Prompt工程学习之思维树(TOT)

思维树 定义&#xff1a;思维树&#xff08;Tree of Thoughts, ToT&#xff09; 是一种先进的推理框架&#xff0c;它通过同时探索多条推理路径对思维链&#xff08;Chain of Thought&#xff09;** 进行了扩展。该技术将问题解决视为一个搜索过程 —— 模型生成不同的中间步骤…...