[C++] vector对比list deque的引出

news2024/12/27 11:56:00

Kevin的技术博客.png

文章目录

  • `list`与`vector`的对比
  • 双端队列`deque`
    • `deque`的特性
    • `deque`的底层实现原理
      • 内存结构
        • 块表(Block Array)
        • 块(Block)
      • 插入与删除
        • 两端插入
        • 两端删除
      • 随机访问
        • 如何计算位置
      • 迭代器设计
  • 总结


listvector的对比

vectorlist都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及 应用场景不同,其主要不同如下:

特性**vector**(动态数组)**list**(双向链表)
底层结构动态顺序表,一段连续空间带头结点的双向循环链表
随机访问支持随机访问,访问效率O(1)不支持随机访问,访问某个元素效率O(N)
插入和删除任意位置插入和删除效率低,需要搬移元素,时间复杂度为O(N),插入时有可能需要增容,增容:开辟新空间,拷贝元素,释放旧空间,导致效率更低任意位置插入和删除效率高,不需要搬移元素,时间复杂度为O(1)
空间利用率底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高
(但是扩容会二倍扩,可能造成空间浪费)底层节点动态开辟,小节点容易造成内存碎片,空间利用率低,缓存利用率低
(在申请空间的时候是按需申请,不会浪费空间)
迭代器封装原生态指针对原生态指针(节点指针)进行封装
迭代器失效在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效插入元素不会导致迭代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响
使用场景需要高效存储,支持随机访问,不关心插入删除效率大量插入和删除操作,不关心随机访问

[C++] vector入门&迭代器失效问题详解-CSDN博客
[C++] 深入浅出list容器-CSDN博客
以上是对listvector的相关讲解。在关于list的文章中有对list容器关于将原生指针包装为迭代器的详细讲解,以及关于listvector中关于迭代器失效等问题的详细解答。

双端队列deque

deque的特性

deque(双端队列)结合了vectorlist的优缺点,提供了在两端进行高效插入和删除的能力,同时支持高效的随机访问。deque的底层实现比vectorlist更复杂,它使用了一系列的小的连续数组块来管理数据,这样可以在两端插入和删除时避免频繁的内存分配和拷贝。
基于deque的如上特性,经常用来作为queue的实现所基于的容器。queue 可以基于任何类型的容器来实现,而 deque 提供了高效的队列操作所需的基本功能:从前端插入和删除元素,以及从后端插入元素。

deque 提供了以下特性,使其适合作为 queue 的底层实现:

  • 从两端快速插入和删除元素的能力。
  • 动态大小调整,不需要像 vector 那样进行整体的内存重新分配。

1627372174-103268.png

deque的底层实现原理

deque(双端队列)的底层实现可以理解为一个动态的分段数组。它结合了数组和链表的优点,通过一组固定大小的小数组(称为缓冲区)来管理数据。

内存结构

deque并不是像vector那样的一块连续内存,而是由多个固定大小的块组成。每个块是一个连续的小数组,这些块按顺序排列,形成一个类似环形的结构。每个块的大小是固定的,但deque可以动态增加或减少块的数量。
czGx1.png
deque起初是在多个的中间位置开始建立,如此可以更高效的向前或者向后延伸。

块表(Block Array)

deque内部维护了一个指向这些块的指针数组,这个数组被称为块表(block array)。块表记录了所有块的指针,通过块表可以定位到具体的块,从而找到存储的数据。

块(Block)

每个块内部是一个固定大小的数组。每个块的大小通常是一个固定的常量,这样可以在块表中通过偏移量计算快速定位到块中的元素。

插入与删除

deque支持在两端高效的插入和删除,这主要得益于其分段结构。

两端插入
  • 前端插入:在前端插入元素时,若当前前端块有空间,则直接插入;否则,在块表的前端插入一个新的块,然后将数据插入新块中。
  • 后端插入:后端插入的处理方式与前端类似。如果后端块已满,则在块表后端新增一个块。
两端删除
  • 前端删除:从前端块删除元素,如果前端块为空,则释放该块并调整块表。
  • 后端删除:与前端删除类似,删除后如果后端块为空,则释放该块。

随机访问

deque支持高效的随机访问,这是因为它可以通过块表和块内偏移快速定位元素。

如何计算位置

对于一个给定的索引,首先需要计算它所在的块,然后计算块内的偏移量。具体计算公式如下:

  1. 计算块索引:block_index = (start + index) / block_size
  2. 计算块内偏移:offset = (start + index) % block_size

迭代器设计

deque的迭代器较为复杂,因为它需要封装块表、块和块内元素的位置信息。deque的迭代器通常包含以下信息:

  1. 当前块指针:指向当前元素所在的块。
  2. 块内指针:指向当前块中的具体位置。
  3. 块表指针:指向块表中的位置。

通过这些信息,迭代器可以支持前向、后向的遍历和随机访问。当进行迭代操作时,迭代器需要处理跨块的情况,这增加了迭代器的复杂性。
IgAwE.png

总结

  • deque的底层是一个分段的、动态的二维数组结构,它提供了高效的两端插入删除操作(中间删除操作效率和**vector**一样,需要移动数据 O(N)),同时保留了随机访问的能力(下标随机访问略逊与vector)。
  • 这种分段结构使得deque在需要频繁修改两端的数据的场景下,具有比vector更高的性能和灵活性。
  • 迭代器的设计相对复杂,需要维护跨块的信息,但也因此提供了强大的功能。


image.png

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

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

相关文章

实战AR增强现实【OpenCV+Ogre】

作为一份小小的礼物,我想向你展示借助 Ogre 和 OpenCV 自己制作增强现实变得多么容易。你应该知道,除了图形之外,我的另一个兴趣是计算机视觉。 演示将不依赖于 ARCore 或 ARKit 等专有解决方案 - 所有这些都将使用开源代码完成,…

【ROS2】 默认的DDS通信中间件替换为Eclipse Cyclone_DDS (DDS配置方法)

ROS2替换中间件为Cyclone_DDS 1.一些介绍:)2.不同DDS的RMW实现3.默认的FastDDS替换为Cyclone DDSi.安装依赖ii.编译 cyclone-dds 4.配置网络 1.一些介绍:) 上一篇我们探讨了ros1和ros2编写launch的区别 【ROS2】launch启动文件编…

相机外参矩阵

在上一篇文章中,我们学习了如何将相机矩阵分解为内参矩阵和外参矩阵的乘积。在接下来的两篇文章中,我们将更详细地探讨外参矩阵和内参矩阵。首先,我们将探讨查看外参矩阵的各种方式,并在最后进行交互式演示。 SDT工具推荐&#xf…

程序员必知必懂运维技术概念

引言 随着互联网和云计算的迅速发展,传统的单体架构逐渐被微服务架构所取代。这一变化带来了许多新的挑战,如环境一致性、应用的可移植性、服务的扩展性、服务间通信的管理以及安全性等。为了解决这些问题,业界开发了许多工具和技术&#xf…

SPSSAU | Adaboost模型原理及案例实操

AdaBoost(Adaptive Boosting)算法的核心思想是将多个弱分类器组合成一个强分类器。其算法步骤如下: 第一:初始化权重,为每个训练样本分配相等的初始权重; 第二:训练弱分类器,根据当…

如何做OLED屏幕安装方案

制定OLED屏幕安装方案时,需要综合考虑多个方面,包括安装环境、屏幕尺寸、支架选择、电源与信号连接、调试与测试等。以下是一个详细的OLED屏幕安装方案: 一、前期准备 确定安装位置: 根据使用需求和环境条件,选择一个…

基于FPGA的以太网设计(4)----详解PHY的使用(以YT8531为例)

目录 1、前言 2、如何了解PHY芯片? 2.1、总览 2.2、管脚 2.3、编码 2.4、自协商 2.5、环回模式 2.6、睡眠模式 2.7、复位 2.8、PHY地址 3、PHY芯片的寄存器配置 3.1、Basic Control Register (0x00) 3.2、Basic StatusRegister (0x01) 3.3、PHY Specific Status…

重生了,这一世 我一定要学会服务器 只因………

你好,我是Qiuner. 为帮助别人少走弯路和记录自己编程学习过程而写博客 这是我的 github https://github.com/Qiuner ⭐️ ​ gitee https://gitee.com/Qiuner 🌹 如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^) 想看更多 那就点个关注吧 我…

IT运维管理与ITSM:理论与实践

IT运维管理和IT服务管理(ITSM)在现代企业信息化过程中占据着举足轻重的地位。它们不仅是确保IT系统稳定运行和业务连续性的关键,还是推动企业数字化转型、提升竞争力的重要力量。本文将结合《IT运维管理和ITSM》文档的内容,深入探…

【C++/STL】:哈希的应用 -- 位图布隆过滤器

目录 🚀🚀前言一,位图1. 位图的概念2. STL库中的位图3. 位图的设计4. 位图的模拟实现5. 位图的优缺点6. 位图相关考察题⽬ 二,布隆过滤器1. 布隆过滤器的概念2. 布隆过滤器的实现3. 布隆过滤器删除问题4. 布隆过滤器的优缺点 点击…

江森自控引入电子签,“碳”索智能建筑数字未来

近年来,伴随着科技的不断进步和市场领域的持续延伸,智能建筑已然成为建筑业科技升级的必经之路。 作为智能建筑领域的全球领导者,江森自控始终走在数字化变革前列,并在业内率先引入了电子合同,通过全流程线上进行的签…

【办公类-53-03】2024年第一学期校历制作(“月/日(星期)”版、排班表、跳过节日和周三)

背景需求: 前期代码制作出2024年第一学期校历,按照5天一周的方法,提取实际工作日。制作成“周计划教案”使用的长日期、短日期 -【办公类-53--01】2024年第一学期校历制作(星火讯飞提取实际工作日,5天一行&#xff0…

Spring-Retry 框架实战经典重试场景

Spring-Retry框架是Spring自带的功能&#xff0c;具备间隔重试、包含异常、排除异常、控制重试频率等特点&#xff0c;是项目开发中很实用的一种框架。 1、引入依赖 坑点&#xff1a;需要引入AOP&#xff0c;否则会抛异常。 xml <!-- Spring-Retry --> <dependency&…

【AI大模型】通义千问:开启语言模型新篇章与Function Call技术的应用探索

文章目录 前言一、大语言模型1.大模型介绍2.大模型的发展历程3.大模型的分类a.按内容分类b.按应用分类 二、通义千问1.通义千问模型介绍a.通义千问模型介绍b.应用场景c.模型概览 2.对话a.对话的两种方式通义千问API的使用 b.单轮对话Vue页面代码&#xff1a;Django接口代码 c.多…

【C++】—— 类与对象(一)

【C】—— 类与对象&#xff08;一&#xff09; 1、类的定义1.1、类定义1.1.1、类定义格式1.1.2、成员变量的标识1.1.3、C 中的 s t r u c t struct struct1.1.4、C 中的内联函数1.1.5、总结 1.2、访问限定符1.3、类域 2、实例化2.1、实例化的概念2.2、对象大小2.2.1、对象的大…

【Hot100】LeetCode—1143. 最长公共子序列

目录 题目1- 思路2- 实现⭐最长公共子序列——题解思路 3- ACM 实现 题目 原题连接&#xff1a;1143. 最长公共子序列 1- 思路 模式识别1——> 求子序列问题 ——> dp数组定义为 i-1 和 j-1 动规五部曲 1- 创建dp数组 dp[i][j]&#xff0c;代表以 i-1 结尾的 text1 和…

“外挂”——逆向软件的分析与破解

本文来源无问社区&#xff0c;更多实战内容&#xff0c;渗透思路可前往查看http://www.wwlib.cn/index.php/artread/artid/11458.html#maodian1 前言&#xff1a; “外挂”的制作离不开软件的分析破解&#xff0c;这平时做ctf中的逆向题是有⼀定的差别的。最直观的区别体现在…

Leetcode 438. 找到字符串中所有字母异位词(java实现)

解题思路&#xff1a;滑动窗口。 异位词的典型解题方法就是用数组来统计出现的个数。本题也不例外。 直接上代码来进行讲解&#xff1a; public List<Integer> findAnagrams(String s, String p) {//初始化返回数组List<Integer> res new ArrayList<>();if …

百问网全志T113-PRO LVGL环境配置

运行LVGL示例 启动开发板 ​ 按要求接入电源或Type-c数据线&#xff0c;拨动拨码开关&#xff0c;将开发板上电 运行LVGL示例 ​ 打开串口终端软件&#xff0c;这里我使用MobaXterm软件演示&#xff0c;选择开发板的串口终端号&#xff0c;可以在设备管理中查看 这里我的串…