C++之序列容器(vector,list,dueqe)

devtools/2025/3/10 19:23:03/

1.大体对比

在软件开发的漫长历程中,数据结构与算法始终占据着核心地位,犹如大厦的基石,稳固支撑着整个程序的运行。在众多编程语言中,数据的存储与管理方式各有千秋,而 C++ 凭借其丰富且强大的工具集脱颖而出,尤其是在处理序列数据方面,C++ 标准模板库(STL)中的序列容器 vectorlist 和 deque 更是展现出卓越的性能与高度的灵活性。

和一些编程语言中单一的数据存储方式相比,C++ 这三种序列容器的存在,无疑为开发者提供了更多样化的选择。例如,在 Python 中,主要通过列表(list)来存储序列数据,其本质上是一种动态数组,但在处理大规模数据的随机访问和频繁插入删除操作时,性能表现往往不尽如人意。反观 C++ 的 vector,它与传统数组有相似之处,却具备了自动调整大小的功能,这一特性让其在面对数据量动态变化的场景时,能够轻松应对,极大地提升了开发效率。

再将目光投向链表结构。在 Java 语言中,虽然没有像 C++ list 这样直接对应的双向链表容器,但开发者可以通过自定义类和节点来构建链表结构。然而,这种方式不仅实现起来较为繁琐,而且在进行常见的元素操作,如插入和删除时,其效率远不及 C++ 的 list。C++ 的 list 作为双向链表,每个节点都包含指向前一个节点和后一个节点的指针,这种数据结构使得在任意位置进行插入和删除操作的时间复杂度都保持在常数级别,在需要频繁修改序列数据的场景中,它的优势便得以充分彰显。

deque 则是 C++ 序列容器中的一颗独特 “新星”,它巧妙地融合了 vector 和 list 的部分优势。和 Java 中的双端队列(ArrayDeque)相比,C++ 的 deque 不仅在两端进行元素的插入和删除操作时具有高效性,而且在支持随机访问方面也毫不逊色。这意味着,在既需要快速在两端增减元素,又要对序列中的元素进行随机访问的复杂场景下,deque 能够提供更为平衡和高效的解决方案。

正是基于这些显著的特性差异,深入了解 C++ 的 vectorlist 和 deque 这三种序列容器,对于每一位追求卓越编程质量的开发者而言,都显得尤为重要。接下来,让我们拨开迷雾,详细剖析这三种序列容器的独特之处,探寻它们在不同编程场景下的最佳应用方式

 2.数据结构

1.vector(连续)

 2.list(指针)

3.deque

3.成员函数

这个三个人的成员函数是一样

3.1 创建

vector():默认构造函数,创建一个空的 vector。
vector(size_type n, const T& value = T()):创建一个包含 n 个值为 value 的元素的 vector。
vector(const vector& other):拷贝构造函数,创建一个 other 的副本。
vector(InputIterator first, InputIterator last):使用迭代器 first 到 last 范围内的元素初始化list():默认构造函数,创建一个空的 vector。
list(size_type n, const T& value = T()):创建一个包含 n 个值为 value 的元素的 vector。
list(const vector& other):拷贝构造函数,创建一个 other 的副本。
list(InputIterator first, InputIterator last):使用迭代器 first 到 last 范围内的元素初始化 deque():默认构造函数,创建一个空的 vector。
deque(size_type n, const T& value = T()):创建一个包含 n 个值为 value 的元素的 vector。
deque(const vector& other):拷贝构造函数,创建一个 other 的副本。
deque(InputIterator first, InputIterator last):使用迭代器 first 到 last 范围内的元素初始化 

 3.2 访问


back()//返回队列尾部元素的引用。
front()//返回队列头部元素的引用。
clear()//清空队列中的所有元素。
empty()//判断队列是否为空。
size()//返回队列中元素的个数。
begin()//返回头位置的迭代器
end()//返回尾+1位置的迭代器//vector没有
rbegin()//返回逆头位置的迭代器 
rend()//返回逆尾-1位置的迭代器 //list没有
下标访问 []

 3.3删除

pop_back()//删除队列尾部的元素。
pop_front()//删除队列头部的元素
erase(iterator pos):移除 pos 位置的元素。
erase(iterator first, iterator last):移除 first 到 last 范围内的元素。
clear():移除 vector 中的所有元素

3.4插入

push_back(const T& value)
push_front(const T& value)
insert(iterator pos, const T& value)

 4.实现队列和栈

 栈:一种先进后出的数据结构

队列:一种先进先出的数据结构

用vector实现栈:

#include<vector>
#include<string>
using namespace std;template<class T> class stack {
private:std::vector<T> data;
public://创建stack();stack(const stack& other):data(other.data){};stack& operator=(const stack& other){data=other.data;return *this;}stack(int n, T val):data(n,val){}//访问int size()const {return data.size();}bool empty()const{if(data.size()==0)return true;elsereturn false;}T top() const{if(data.empty()==true)throw string("stack is empty");elsereturn data.back();}//插入void push(T val){data.push_back(val);}//删除void pop(){if(data.empty()==true)throw string("stack is empty");else{data.pop_back();}}~stack();};

5.总结

对比维度std::vectorstd::liststd::deque
底层结构动态数组,在内存中分配连续的存储空间。当容量不足时,通常会重新分配更大的内存块,将原数据复制过去并释放旧内存。双向链表,由一系列节点构成,每个节点包含数据、指向前一个节点的指针和指向后一个节点的指针。由多个固定大小的数组块组成,每个数组块内部连续存储,数组块之间通过指针连接,形成双端队列结构。
访问操作- 支持随机访问,可通过下标直接访问元素,时间复杂度为 \(O(1)\)。
- 访问元素非常高效,就像操作普通数组一样。
- 不支持随机访问,若要访问特定位置元素,需从头或尾开始遍历链表,时间复杂度为 (O(n))。
- 只能顺序访问元素。
- 支持随机访问,通过下标访问元素的时间复杂度为(O(1))。
- 虽然能随机访问,但由于是分段连续存储,在效率上可能略低于 vector
插入操作 在尾部插入元素效率高,平均时间复杂度为 (O(1)),但若触发内存重新分配,时间复杂度为 (O(n))。 在中间或头部插入元素,需要移动插入位置之后的所有元素,时间复杂度为 (O(n))。- 在任意位置插入元素的时间复杂度均为 (O(1)),只需修改相邻节点的指针。
- 插入操作非常灵活,效率高。
- 在头部和尾部插入元素效率高,时间复杂度为 (O(1))。
- 在中间插入元素,需要移动部分元素,时间复杂度为 (O(n)),但通常比 vector 移动元素的开销小。
删除操作- 在尾部删除元素效率高,时间复杂度为(O(1))。
- 在中间或头部删除元素,需要移动删除位置之后的所有元素,时间复杂度为 (O(n))。
 在任意位置删除元素的时间复杂度均为 (O(1)),只需修改相邻节点的指针。- 在头部和尾部删除元素效率高,时间复杂度为 \(O(1)\)。
- 在中间删除元素,需要移动部分元素,时间复杂度为 \(O(n)\),但通常比 vector 移动元素的开销小。
空间利用- 由于是连续存储,可能会有内存碎片问题。当容量不足重新分配内存时,可能会预留一定的额外空间,造成空间浪费。
- 不过,它的空间利用率相对较高,因为没有额外的指针开销。
每个节点都需要额外的指针来指向前一个和后一个节点,增加了内存开销。
- 但链表节点在内存中可以不连续存储,不会因为预留空间而造成浪费。
- 由于需要维护多个数组块以及块之间的连接信息,会有一定的额外开销。
- 不过,它在动态扩展时不需要像 vector 那样重新分配并复制大量数据,空间管理相对灵活。
迭代器-随机访问迭代器,支持 ++--+- 等操作,可以像指针一样灵活地在容器中移动。- 双向迭代器,支持 ++ 和 -- 操作,能双向遍历链表,但不支持随机访问。- 随机访问迭代器,与 vector 的迭代器类似,支持高效的随机访问操作。
迭代器失效情况- 当发生插入或删除操作导致内存重新分配时,所有迭代器、指针和引用都会失效。
- 在插入或删除元素后,插入或删除位置之后的迭代器、指针和引用会失效。
- 插入操作不会使任何迭代器、指针和引用失效。
- 删除操作只会使指向被删除节点的迭代器、指针和引用失效。
在头部或尾部插入元素时,迭代器一般不会失效,但指向元素的引用和指针可能会失效。
- 在中间插入或删除元素时,插入或删除位置之后的迭代器、指针和引用会失效。
使用场景 适合需要频繁随机访问元素,且插入和删除操作主要在尾部进行的场景,如存储一组数据并经常通过下标访问。
- 实现栈、队列等数据结构时,若操作主要集中在尾部,vector 是不错的选择。
- 适合需要频繁在任意位置进行插入和删除操作,而对随机访问需求较少的场景,如实现链表类的数据结构。
- 当需要频繁进行元素的移动、插入和删除,且不需要随机访问元素时,list 更合适。
- 适合需要在头部和尾部频繁进行插入和删除操作,同时也需要随机访问元素的场景,如实现双端队列。
- 当数据量较大,且需要在两端进行高效操作时,deque 是一个较好的选择。


http://www.ppmy.cn/devtools/166083.html

相关文章

深入探索 Django 内置的 User 模型及其自定义扩展

深入探索 Django 内置的 User 模型及其自定义扩展 在 Django 框架中&#xff0c;内置的 User 模型是处理用户认证和授权的核心组件。它提供了一系列预定义的属性和方法&#xff0c;使得开发者能够轻松管理用户信息、进行用户认证以及控制用户权限。本文将详细介绍 Django 内置…

批量在 Word 的指定位置插入页,如插入封面、末尾插入页面

我们经常会碰到需要在 Word 文档中插入新的页面的需求&#xff0c;比如在 Word 文档末尾插入一个广告页、给 Word 文档插入一个说明封面&#xff0c;在 Word 文档的中间位置插入新的页面等等。相信这个操作对于大部分小伙伴来说都不难&#xff0c;难的是同时给多个 Word 文档插…

视频输入设备-V4L2的开发流程简述

一、摄像头的工作原理与应用 基本概念 V4L2的全称是Video For Linux Two&#xff0c;其实指的是V4L的升级版&#xff0c;是linux系统关于视频设备的内核驱动&#xff0c;同时V4L2也包含Linux系统下关于视频以及音频采集的接口&#xff0c;只需要配合对应的视频采集设备就可以实…

蓝桥杯嵌入式组第七届省赛题目解析+STM32G431RBT6实现源码

文章目录 1.题目解析1.1 分而治之&#xff0c;藕断丝连1.2 模块化思维导图1.3 模块解析1.3.1 KEY模块1.3.2 ADC模块1.3.3 IIC模块1.3.4 UART模块1.3.5 LCD模块1.3.6 LED模块1.3.7 TIM模块 2.源码3.第七届题目 前言&#xff1a;STM32G431RBT6实现嵌入式组第七届题目解析源码&…

阿里云操作系统(AliOS)

引言 阿里云操作系统&#xff08;AliOS&#xff09;是阿里巴巴集团专为物联网&#xff08;IoT&#xff09;和智能设备开发的操作系统&#xff0c;致力于为智能汽车、智能家居、工业设备等提供高效、安全、智能化的解决方案。作为一款云端一体的操作系统&#xff0c;AliOS深度融…

深度学习---卷积神经网络

一、卷积尺寸计算公式 二、池化 池化分为最大池化和平均池化 最常用的就是最大池化&#xff0c;可以认为最大池化不需要引入计算&#xff0c;而平均池化需要引出计算&#xff08;计算平均数&#xff09; 每种池化还分为Pooling和AdaptiveAvgPool Pooling(2)就是每2*2个格子…

景联文科技:以精准数据标注赋能AI进化,构筑智能时代数据基石

在人工智能技术席卷全球的浪潮中&#xff0c;高质量数据已成为驱动AI模型进化的核心燃料。作为全球领先的AI数据服务解决方案提供商&#xff0c;景联文科技深耕数据标注领域多年&#xff0c;以技术为基、以专业为本&#xff0c;致力于为全球客户提供全场景、高精度、多模态的数…

第10章 metasploit(网络安全防御实战--蓝军武器库)

网络安全防御实战--蓝军武器库是2020年出版的&#xff0c;已经过去3年时间了&#xff0c;最近利用闲暇时间&#xff0c;抓紧吸收&#xff0c;总的来说&#xff0c;第10章开始学习利用metasploit渗透测试工具去打metasploit2虚拟机&#xff0c;本文我演示了metasploit端口扫描和…