深入解析【C++ list 容器】:高效数据管理的秘密武器
目录
1. list 的介绍及使用
1.1 list 的介绍
知识点:
小李的理解:
1.2 list 的使用
1.2.1 list 的构造
知识点:
小李的理解:
代码示例:
1.2.2 list 迭代器的使用
知识点:
小李的理解:
代码示例:
1.2.3 list 的容量
知识点:
小李的理解:
代码示例:
1.2.4 list 的元素访问
知识点:
小李的理解:
代码示例:
1.2.5 list 的修改操作
知识点:
小李的理解:
代码示例:
1.2.6 list 迭代器失效
知识点:
小李的理解:
代码示例:
2. list 的模拟实现
知识点:
小李的理解:
代码示例:
3. list 与 vector 的对比
知识点:
小李的理解:
总结
专栏:C++学习笔记
上一卷:【C++ 】-vector:新时代动态数组的革新与未来
C++ 中的 list
是一个强大的容器,特别适用于需要频繁插入和删除元素的场景。本文将详细介绍 list
容器,包括其介绍、使用方法、实现原理以及与 vector
容器的对比。
1. list
的介绍及使用
1.1 list
的介绍
知识点:
list
是一种序列式容器,底层实现为双向链表。双向链表中的每个元素存储在独立的节点中,节点通过指针互相连接,可以在常数时间内在任意位置进行插入和删除操作。与 forward_list
的单链表不同,list
支持双向迭代。与其他序列式容器(如 array
、vector
、deque
)相比,list
在插入和删除操作方面表现更优,但不支持随机访问。
小李的理解:
list
就像一条双向街道上的车队,每辆车(节点)都有前后两个链接,指向前后两辆车。你可以轻松地在任何地方插入或删除一辆车,而不需要移动其他车。但是,如果你想找到某辆车,就需要从头或尾开始,一辆辆查找,比较费时。
1.2 list
的使用
1.2.1 list
的构造
知识点:
list
提供多种构造方法,包括创建空的 list
,创建包含多个相同元素的 list
,使用区间构造 list
以及拷贝构造等。
小李的理解:
构造 list
就像创建不同类型的车队,你可以创建一个空车队,或者一个全是同样车的车队,还可以用现有的车队来创建新的车队。
代码示例:
#include <list>
#include <iostream>int main() {// 创建一个空的 liststd::list<int> empty_list;// 创建一个包含 5 个值为 10 的元素的 liststd::list<int> filled_list(5, 10);// 使用区间构造 listint arr[] = {1, 2, 3, 4, 5};std::list<int> range_list(arr, arr + 5);// 打印 filled_list 的元素for(int n : filled_list) {std::cout << n << " ";}std::cout << std::endl;return 0;
}
这个程序首先创建一个空的
list
,然后创建一个包含 5 个值为 10 的list
,接着用数组中的元素构造一个list
。最后打印filled_list
的元素,显示 5 个 10。
1.2.2 list
迭代器的使用
知识点:
list
的迭代器类似于指针,指向 list
中的节点。你可以使用迭代器遍历 list
,访问或修改元素。
小李的理解:
迭代器就像你走在车队中的一个人,你可以走到每辆车旁边查看里面的东西,或者往回走查看后面的车。
代码示例:
#include <list>
#include <iostream>int main() {std::list<int> my_list = {1, 2, 3, 4, 5};// 正向迭代for (auto it = my_list.begin(); it != my_list.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;// 反向迭代for (auto rit = my_list.rbegin(); rit != my_list.rend(); ++rit) {std::cout << *rit << " ";}std::cout << std::endl;return 0;
}
这个程序创建一个包含 5 个整数的
list
。正向迭代器遍历list
,从头到尾打印元素,反向迭代器遍历list
,从尾到头打印元素。
1.2.3 list
的容量
知识点:
你可以使用 empty()
函数检查 list
是否为空,使用 size()
函数获取 list
中的元素个数。
小李的理解:
这就像你检查车队中是否有车,以及数一数车队中有多少辆车。
代码示例:
#include <list>
#include <iostream>int main() {std::list<int> my_list = {1, 2, 3, 4, 5};// 检查是否为空if (my_list.empty()) {std::cout << "List is empty" << std::endl;} else {std::cout << "List is not empty" << std::endl;}// 获取大小std::cout << "List size: " << my_list.size() << std::endl;return 0;
}
程序首先检查
list
是否为空,显然my_list
不为空,然后打印list
的大小,显示有 5 个元素。
1.2.4 list
的元素访问
知识点:
你可以使用 front()
函数访问 list
的第一个元素,使用 back()
函数访问 list
的最后一个元素。
小李的理解:
这就像你想看看车队的第一辆车和最后一辆车里装了什么东西。
代码示例:
#include <list>
#include <iostream>int main() {std::list<int> my_list = {1, 2, 3, 4, 5};// 访问第一个和最后一个元素std::cout << "First element: " << my_list.front() << std::endl;std::cout << "Last element: " << my_list.back() << std::endl;return 0;
}
程序分别打印
list
的第一个和最后一个元素,显示 1 和 5。
1.2.5 list
的修改操作
知识点:
list
提供丰富的修改操作,包括在头部和尾部插入和删除元素,插入和删除特定位置的元素,交换两个 list
的内容以及清空 list
。
小李的理解:
这就像你可以在车队的任何位置加车或减车,甚至可以交换两队车里的车,或者把整个车队清空。
代码示例:
#include <list>
#include <iostream>int main() {std::list<int> my_list = {1, 2, 3, 4, 5};// 插入和删除操作my_list.push_front(0); // 在前面插入 0my_list.push_back(6); // 在后面插入 6my_list.pop_front(); // 删除第一个元素my_list.pop_back(); // 删除最后一个元素// 插入和删除特定位置的元素auto it = my_list.begin();++it; // 指向第二个元素my_list.insert(it, 100); // 在第二个位置插入 100it = my_list.begin();++it;my_list.erase(it); // 删除第二个位置的元素// 交换和清空 liststd::list<int> another_list = {10, 20, 30};my_list.swap(another_list);my_list.clear();return 0;
}
以下是程序在各步之后的状态:
my_list
初始为{1, 2, 3, 4, 5}
- 插入 0 和 6 后为
{0, 1, 2, 3, 4, 5, 6}
- 删除第一个和最后一个元素后为
{1, 2, 3, 4, 5}
- 在第二个位置插入 100 后为
{1, 100, 2, 3, 4, 5}
- 删除第二个位置的元素后为
{1, 2, 3, 4, 5}
- 与
another_list
交换后my_list
为{10, 20, 30}
- 清空后
my_list
为空
1.2.6 list
迭代器失效
知识点:
在 list
中,插入操作不会导致迭代器失效,删除操作会使指向被删除节点的迭代器失效。
小李的理解:
就像你从车队中移走一辆车时,那个位置的指示牌(迭代器)也被移走了,但其他位置的指示牌不受影响。
代码示例:
#include <list>
#include <iostream>int main() {std::list<int> my_list = {1, 2, 3, 4, 5};auto it = my_list.begin();while (it != my_list.end()) {it = my_list.erase(it); // 删除元素后,更新迭代器}return 0;
}
这个程序将删除
list
中的所有元素,最后my_list
为空。每次删除一个元素后,迭代器指向下一个元素,直到
list
清空。
2. list
的模拟实现
知识点:
实现一个简化版本的 list
,需要理解其底层结构和接口的含义。以下是一个简化的 list
实现示例:
小李的理解:
模拟实现 list
就像你自己动手造一辆汽车,你需要理解汽车的每个部件和它们如何协同工作。
代码示例:
#include <iostream>template<typename T>
class Node {
public:T data;Node* prev;Node* next;Node(T val) : data(val), prev(nullptr), next(nullptr) {}
};template<typename T>
class List {
private:Node<T>* head;Node<T>* tail;public:List() : head(nullptr), tail(nullptr) {}void push_back(T val) {Node<T>* newNode = new Node<T>(val);if (!tail) {head = tail = newNode;} else {tail->next = newNode;newNode->prev = tail;tail = newNode;}}void print() {Node<T>* temp = head;while (temp) {std::cout << temp->data << " ";temp = temp->next;}std::cout << std::endl;}~List() {Node<T>* temp;while (head) {temp = head;head = head->next;delete temp;}}
};int main() {List<int> my_list;my_list.push_back(1);my_list.push_back(2);my_list.push_back(3);my_list.print();return 0;
}
这个程序手动实现了一个简单的
list
,并添加了 3 个元素。最终打印出list
中的所有元素。
3. list
与 vector
的对比
知识点:
底层结构:
vector
:动态顺序表,连续内存空间。list
:双向链表,不连续。随机访问:
vector
:支持,效率为 O(1)。list
:不支持,效率为 O(N)。插入和删除:
vector
:效率低,时间复杂度为 O(N)。list
:效率高,时间复杂度为 O(1)。空间利用率:
vector
:高,连续空间,缓存利用率高。list
:低,节点动态分配,容易造成内存碎片。迭代器:
vector
:原生指针。list
:封装的节点指针。迭代器失效:
vector
:插入时可能失效,删除时当前迭代器失效。list
:插入不会失效,删除时当前迭代器失效。使用场景:
vector
:高效存储,随机访问。list
:频繁插入和删除操作。
小李的理解:
vector
就像一块连续的停车场,每辆车(元素)都紧挨着,如果你要在中间插入或删除一辆车,就需要挪动很多车。而 list
就像一列火车,每节车厢(元素)独立,可以随意插入或移除车厢,但要找到某个特定车厢就得一节一节地找。
总结
C++ 中的
list
容器是一个基于双向链表的序列式容器,适用于需要频繁插入和删除操作的场景,但不支持随机访问。list
提供了多种构造方法和丰富的操作接口,包括插入、删除、访问等。与vector
相比,list
在插入和删除操作上更高效,但在随机访问和空间利用率上较差。
相关文章:

深入解析【C++ list 容器】:高效数据管理的秘密武器
目录 1. list 的介绍及使用 1.1 list 的介绍 知识点: 小李的理解: 1.2 list 的使用 1.2.1 list 的构造 知识点: 小李的理解: 代码示例: 1.2.2 list 迭代器的使用 知识点: 小李的理解࿱…...

NFS服务器、autofs自动挂载综合实验
综合实验 现有主机 node01 和 node02,完成如下需求: 1、在 node01 主机上提供 DNS 和 WEB 服务 2、dns 服务提供本实验所有主机名解析 3、web服务提供 www.rhce.com 虚拟主机 4、该虚拟主机的documentroot目录在 /nfs/rhce 目录 5、该目录由 node02 主机…...

自动驾驶事故频发,安全痛点在哪里?
大数据产业创新服务媒体 ——聚焦数据 改变商业 近日,武汉城市留言板上出现了多条关于萝卜快跑的投诉,多名市民反映萝卜快跑出现无故停在马路中间、高架上占最左道低速行驶、转弯卡着不动等情况,导致早晚高峰时段出现拥堵。萝卜快跑是百度 A…...

SpringSecurity框架【认证】
目录 一. 快速入门 二. 认证 2.1 登陆校验流程 2.2 原理初探 2.3 解决问题 2.3.1 思路分析 2.3.2 准备工作 2.3.3 实现 2.3.3.1 数据库校验用户 2.3.3.2 密码加密存储 2.3.3.3 登录接口 2.3.3.4 认证过滤器 2.3.3.5 退出登录 Spring Security是Spring家族中的一个…...
python安全脚本开发简单思路
文章目录 为什么选择python作为安全脚本开发语言如何编写人生第一个安全脚本开发后续学习 为什么选择python作为安全脚本开发语言 易读性和易维护性:Python以其简洁的语法和清晰的代码结构著称,这使得它非常易于阅读和维护。在安全领域,代码…...

WPF学习(4) -- 数据模板
一、DataTemplate 在WPF(Windows Presentation Foundation)中,DataTemplate 用于定义数据的可视化呈现方式。它允许你自定义如何展示数据对象,从而实现更灵活和丰富的用户界面。DataTemplate 通常用于控件(如ListBox、…...

GuLi商城-商品服务-API-品牌管理-JSR303分组校验
注解:@Validated 实体类: package com.nanjing.gulimall.product.entity;import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.nanjing.common.valid.ListValue; import com.nanjing.common.valid.Updat…...
PyTorch DataLoader 学习
1. DataLoader的核心概念 DataLoader是PyTorch中一个重要的类,用于将数据集(dataset)和数据加载器(sampler)结合起来,以实现批量数据加载和处理。它可以高效地处理数据加载、多线程加载、批处理和数据增强…...

TCP传输控制协议二
TCP 是 TCP/IP 模型中的传输层一个最核心的协议,不仅如此,在整个 4 层模型中,它都是核心的协议,要不然模型怎么会叫做 TCP/IP 模型呢。 它向下使用网络层的 IP 协议,向上为 FTP、SMTP、POP3、SSH、Telnet、HTTP 等应用…...

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(五)-同时支持无人机和eMBB用户数据传输的用例
引言 本文是3GPP TR 22.829 V17.1.0技术报告,专注于无人机(UAV)在3GPP系统中的增强支持。文章提出了多个无人机应用场景,分析了相应的能力要求,并建议了新的服务级别要求和关键性能指标(KPIs)。…...

使用F1C200S从零制作掌机之debian文件系统完善NES
一、模拟器源码 源码:https://files.cnblogs.com/files/twzy/arm-NES-linux-master.zip 二、文件系统 文件系统:debian bullseye 使用builtroot2018构建的文件系统,使用InfoNES模拟器存在bug,搞不定,所以放弃&…...

Vue 3 与 TypeScript:最佳实践详解
大家好,我是CodeQi! 很多人问我为什么要用TypeScript? 因为 Vue3 喜欢它! 开个玩笑... 在我们开始探索 Vue 3 和 TypeScript 最佳实践之前,让我们先打个比方。 如果你曾经尝试过在没有 GPS 的情况下开车到一个陌生的地方,你可能会知道那种迷失方向的感觉。 而 Typ…...
PyMysql error : Packet Sequence Number Wrong - got 1 expected 0
文章目录 错误一错误原因解决方案 错误二原因解决方案 我自己知道的,这类问题有两类原因,两种解决方案。 错误一 错误原因 pymysql的主进程启动的connect无法给子进程中使用,所以读取大批量数据时最后容易出现了此类问题。 解决方案 换成…...
MVC 生成验证码
在mvc 出现之前 生成验证码思路 在一个html页面上,生成一个验证码,在把这个页面嵌入到需要验证码的页面中。 JS生成验证码 <script type"text/javascript">jQuery(function ($) {/**生成一个随机数**/function randomNum(min, max) {…...

OSPF.综合实验
1、首先将各个网段基于172.16.0.0 16 进行划分 1.1、划分为4个大区域 172.16.0.0 18 172.16.64.0 18 172.16.128.0 18 172.16.192.0 18 四个网段 划分R4 划分area2 划分area3 划分area1 2、进行IP配置 如图使用配置指令进行配置 ip address x.x.x.x /x 并且将缺省路由…...

云计算【第一阶段(29)】远程访问及控制
一、ssh远程管理 1.1、ssh (secureshell)协议 是一种安全通道协议对通信数据进行了加密处理,用于远程管理功能SSH 协议对通信双方的数据传输进行了加密处理,其中包括用户登录时输入的用户口令,建立在应用层和传输层基础上的安全协议。SSH客…...
2024前端面试真题【CSS篇】
盒子模型 盒子模型:box-sizing,描述了文档中的元素如何生成矩形盒子,并通过这些盒子的布局来组织和设计网页。包含content、padding、margin、border四个部分。 分类 W3C盒子模型(content-box):标准盒子模…...
python中设置代码格式,函数编写指南,类的编程风格
4.6 设置代码格式 随着你编写的程序越来越长,确保代码格式一致变得尤为重要。花时间让代码尽可能易于阅读,这不仅有助于你理解程序的功能,也能帮助他人理解你的代码。 为了保证所有人的代码结构大致一致,Python程序员遵循一系列…...

CentOS 8升级gcc版本
1、查看gcc版本 gcc -v发现gcc版本为8.x.x,而跑某个项目的finetune需要gcc-9,之前搜索过很多更新gcc版本的方式,例如https://blog.csdn.net/xunye_dream/article/details/108918316?spm1001.2014.3001.5506,但执行指令 sudo yu…...

Kafka基础入门篇(深度好文)
Kafka简介 Kafka 是一个高吞吐量的分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用与大数据实时处理领域。 1. 以时间复杂度为O(1)的方式提供消息持久化能力。 2. 高吞吐率。(Kafka 的吞吐量是MySQL 吞吐量的30…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...