【C++】list 类深度解析:探索双向链表的奇妙世界

🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟   

如果你对string,vector还存在疑惑,欢迎阅读我之前的作品 : 

之前文章🔥🔥🔥 【C++】vector 类深度解析:探索动态数组的奥秘

               🔥🔥🔥 【C++】string 类深度解析:探秘字符串操作的核心


目录

💯前言

💯为什么要学习 list 类

(一)高效的插入和删除操作

(二)灵活的内存管理

(三)迭代器稳定性

💯标准库中的 list 类

(一)定义与头文件📄

💯list 类的内部结构🧐

(一)节点结构

(二)内存布局

💯list 类的构造函数🚀

(一)默认构造函数

(二)带参数的构造函数

💯list 类的成员函数

(一)获取链表信息的函数📈

(二)链表修改函数✍️

(三)获取特定元素的函数🔍

(四)链表查找函数🔎

💯list 类的操作符重载🎯

(一)赋值操作符(=)

(二)下标操作符([])

💯总结


💯前言

嘿😎,小伙伴们!在 C++ 编程的奇妙旅程中,我们经常会碰到各种数据结构的难题🧐。今天,咱们就来好好研究一下 C++ 标准库中的 list 类,它就像一个超级厉害的双向链表小助手,能帮我们轻松搞定很多复杂的任务哦😜!当我们需要频繁地在数据序列中插入和删除元素时,list 类可是个绝佳的选择呢🤩!它比传统数组灵活多啦,不会因为插入或删除一个元素就把其他元素弄得乱七八糟😏。想知道它为什么这么神奇吗🧐?那就接着往下看吧😎!

相关资料👉list文档介绍


💯为什么要学习 list 类

(一)高效的插入和删除操作

想象一下🤔,你有一排小玩偶🧸,想要在中间插入一个新的玩偶或者拿走一个玩偶。如果它们是像传统数组那样紧紧挨在一起排列的,每次插入或拿走一个玩偶,都得把后面的玩偶一个一个地挪动位置,是不是超级麻烦😫?但是,如果这些玩偶是用一种特殊的方式连接起来的,就像 list 类中的双向链表一样,每个玩偶都有两条 “小绳子”🧵,一条连着前面的玩偶,一条连着后面的玩偶。当你要插入或拿走一个玩偶时,只需要解开和系上相应的 “小绳子” 就可以啦,是不是简单多了😃?这就是 list 类在插入和删除元素时的厉害之处哦!无论在链表的哪个位置进行操作,它都能快速完成,时间复杂度是常数级别呢😎!对于那些经常需要修改数据顺序的程序来说,它简直就是一个神器👏!

(二)灵活的内存管理

list 类的内存管理就像搭积木一样有趣又灵活😄!每个元素就像是一块单独的积木🧱,它们不需要紧紧地靠在一起,可以分散在内存的各个地方。当你需要添加或删除一个元素时,就像拿走或添加一块积木,不会影响其他积木的位置哦😏。这种方式避免了因为内存碎片而导致的性能问题,能让你的程序更好地利用内存资源,是不是很棒呢😎?

(三)迭代器稳定性

迭代器就像是一个小小的导航员🧭用来在 list 中逐个访问元素。在 list 中,当你插入或删除一个元素时,除了指向被操作元素的迭代器会失效(因为这个元素被改变了嘛😉),其他迭代器就像坚固的小灯塔一样,依然稳稳地指向它们原来的元素哦😎!这在我们需要一边遍历 list,一边进行插入或删除操作时特别有用,不用担心因为操作一个元素而导致其他元素找不到了,程序可以稳稳地运行下去,是不是很让人安心呢😃?

 


💯标准库中的 list 类

(一)定义与头文件📄

list 类住在 C++ 标准库的<list>头文件里哦🧐。就像我们要去一个神秘的地方需要知道地址一样,想要使用 list 类,就得先包含这个头文件,然后加上using namespace std;这句话,这样我们就能在程序里使用 list 类提供的各种神奇功能啦😎!

#include <iostream>
#include <list>using namespace std;

💯list 类的内部结构🧐

(一)节点结构

list 类内部是由一个个节点组成的,每个节点就像一个小小的魔法盒子🎁,里面装着三个重要的东西呢😎!首先是真正的数据元素,就像魔法盒子里的宝藏一样🧳;然后是一个指向前面节点的指针,就像魔法盒子前面的小钩子🪝,可以勾住前面的节点;还有一个指向后面节点的指针,就像魔法盒子后面的小尾巴🐈,可以连接后面的节点。通过这些指针,节点们就像手拉手的好朋友一样,形成了一个双向链表,我们可以从前往后或者从后往前遍历哦,是不是很有趣😃?

(二)内存布局

节点们在内存里就像一群自由自在的小精灵🧚‍♂️🧚‍♀️,它们不需要站在连续的位置上。每个节点根据自己的需要在内存中找到一个合适的地方安家🏠。当我们要插入或删除一个节点时,就像小精灵飞进或飞出它们的群体一样,只需要调整相关节点的指针,不需要像数组那样大规模地移动元素,所以操作起来速度很快哦😎!

 


💯list 类的构造函数🚀

(一)默认构造函数

list 类的默认构造函数就像一个神奇的魔法咒语✨,念一下就能创建一个空的 list 对象,这个时候 list 里面什么元素都没有,就像一个空的魔法盒子一样🎁。例如:

(二)带参数的构造函数

使用迭代器区间构造


我们还可以用迭代器区间来创建 list 对象哦😉!比如说,我们有一个其他容器(像 vector)里的一段元素,想把它们放到 list 里,就可以用迭代器指定这个区间,然后 list 就会把这段区间里的元素一个一个复制过来,就像把一群小蚂蚁从一个地方搬到另一个地方一样🐜。例如:

#include <iostream>
#include <list>
#include <vector>using namespace std;int main() {vector<int> v = {1, 2, 3, 4, 5};list<int> l(v.begin(), v.end());cout << "使用迭代器区间构造的list对象的大小为: " << l.size() << endl;return 0;
}

 

指定数量和初始值构造


另外,我们也可以指定要创建的 list 对象里元素的数量,让它们都用默认值初始化,或者直接指定数量和初始值😎。就像我们要订做一批小蛋糕🎂,可以告诉面包师做几个,是都做成普通口味(默认值),还是都做成巧克力口味(指定初始值)。例如:

#include <iostream>
#include <list>using namespace std;int main() {list<int> l1(5);  // 创建包含5个默认初始化元素的listcout << "使用指定数量默认初始化构造的list对象l1的大小为: " << l1.size() << endl;list<int> l2(3, 10);  // 创建包含3个值为10的元素的listcout << "使用指定数量和初始值构造的list对象l2的大小为: " << l2.size() << endl;return 0;
}

 


💯list 类的成员函数

(一)获取链表信息的函数📈

  1. size()函数
    size()函数就像一个小计数器🧮,它能准确地返回 list 中当前元素的个数😃。例如:
    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l = {1, 2, 3, 4, 5};cout << "list中的元素个数为: " << l.size() << endl;return 0;
    }

  2. empty()函数
    empty()函数则像一个小检查员👀,用来检测 list 是否为空。如果 list 里面没有元素,它就会返回true,就像告诉你 “这个盒子是空的哦”😏;如果有元素,就返回false。例如:
    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l1;cout << "list1是否为空: " << (l1.empty() ? "是" : "否") << endl;list<int> l2 = { 1 };cout << "list2是否为空: " << (l2.empty() ? "是" : "否") << endl;return 0;
    }

 

(二)链表修改函数✍️

  1. push_front()函数
    push_front()函数就像一个热情的小主人,总是在 list 的开头添加新元素😎。例如:
    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l;l.push_front(5);l.push_front(3);l.push_front(1);for (int i : l) {cout << i << " ";}cout << endl;return 0;
    }

  2. push_back()函数
    push_back()函数则像一个贴心的小尾巴,在 list 的末尾添加元素😄。例如:
    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l;l.push_back(1);l.push_back(3);l.push_back(5);for (int i : l) {cout << i << " ";}cout << endl;return 0;
    }

  3. pop_front()函数
    pop_front()函数就像一个勇敢的小先锋,从 list 的开头删除元素😉。例如:
    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l = {1, 2, 3, 4, 5};l.pop_front();for (int i : l) {cout << i << " ";}cout << endl;return 0;
    }

  4.  pop_back()函数
    pop_back()函数像一个安静的小后卫,从 list 的末尾删除元素😎。例如:

    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l = {1, 2, 3, 4, 5};l.pop_back();for (int i : l) {cout << i << " ";}cout << endl;return 0;
    }

  5. insert()函数
    insert()函数是一个多功能的小工匠🧑‍🔧,它可以在指定位置插入一个或多个元素😉。例如:
    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l = {1, 3, 4, 5};auto it = l.begin();++it;l.insert(it, 2);for (int i : l) {cout << i << " ";}cout << endl;return 0;
    }

  6. erase()函数
    erase()函数像一个精准的小剪刀✂️,可以删除 list 中的指定元素或元素区间😎。例如:
    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l = {1, 2, 3, 4, 5};auto it = l.begin();++it;l.erase(it);for (int i : l) {cout << i << " ";}cout << endl;return 0;
    }

 

(三)获取特定元素的函数🔍

  1. front()函数
    front()函数就像一个小探险家🧗‍♂️,总是能快速找到 list 中的第一个元素并返回它😎。例如:
    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l = {1, 2, 3, 4, 5};cout << "list中的第一个元素为: " << l.front() << endl;return 0;
    }

  2. back()函数
    back()函数则像一个小后卫👮‍♂️,负责返回 list 中的最后一个元素😉。例如:
    #include <iostream>
    #include <list>using namespace std;int main() {list<int> l = {1, 2, 3, 4, 5};cout << "list中的最后一个元素为: " << l.back() << endl;return 0;
    }

 

(四)链表查找函数🔎

在 list 中查找元素可以使用find()算法结合 list 的迭代器。就像在一个宝藏迷宫里寻找特定的宝物一样🧳,我们可以通过迭代器逐个比较元素来找到我们想要的元素😉。例如:

#include <iostream>
#include <list>
#include <algorithm>using namespace std;int main() {list<int> l = {1, 2, 3, 4, 5};auto it = find(l.begin(), l.end(), 3);if (it!= l.end()) {cout << "找到元素的位置为: " << distance(l.begin(), it) << endl;} else {cout << "未找到元素" << endl;}return 0;
}


💯list 类的操作符重载🎯

(一)赋值操作符(=)

list 类重载了赋值操作符,就像一个神奇的复制魔法🪄,可以将一个 list 对象的值复制给另一个 list 对象😎。例如:

#include <iostream>
#include <list>using namespace std;int main() {list<int> l1 = {1, 2, 3};list<int> l2;l2 = l1;for (int i : l2) {cout << i << " ";}cout << endl;return 0;
}

(二)下标操作符([])

虽然 list 类本身没有像 vector 那样直接支持下标操作符重载,但我们可以通过迭代器来模拟类似的功能😉。例如:

#include <iostream>
#include <list>using namespace std;int main() {list<int> l = {1, 2, 3, 4, 5};auto it = l.begin();advance(it, 2);  // 将迭代器移动到第三个元素位置cout << "第三个元素的值为: " << *it << endl;return 0;
}


💯总结

哇哦😎!C++ 的 list 类真的是一个非常强大且有趣的双向链表工具呢👏!它的内部结构、构造函数、成员函数和操作符重载等特性,让我们在处理动态数据序列时更加得心应手😃。通过深入理解 list 类,我们可以更好地应对各种编程挑战,提高程序的灵活性和效率💪。在实际编程中,我们要根据具体需求合理选择使用 list 类,充分发挥它的优势,避免一些常见的错误哦😉。希望小伙伴们在 C++ 的编程世界里继续探索,发现更多的乐趣和惊喜😜!


 期待下次与你们分享更多精彩内容哦🤗!欢迎关注我👉【A Charmer】 

 

 

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

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

相关文章

uniapp如何i18n国际化

1、正常情况下项目在代码生成的时候就已经有i18n的相关依赖&#xff0c;如果没有可以自行使用如下命令下载&#xff1a; npm install vue-i18n --save 2、创建相关文件 en文件下&#xff1a; zh文件下&#xff1a; index文件下&#xff1a; 3、在main.js中注册&#xff1a…

VScode-Java开发常用插件

中文——界面易读 字体主题——代码可观 头注释——项目信息明了 java开发包——java必备 git协作开发——版本控制

前端(3)——快速入门JaveScript

参考&#xff1a; 罗大富 JavaScript 教程 | 菜鸟教程 JavaScript 教程 1. JaveScript JavaScript 简称 JS JavaScript 是一种轻量级、解释型、面向对象的脚本语言。它主要被设计用于在网页上实现动态效果&#xff0c;增加用户与网页的交互性。作为一种客户端脚本语言&#…

FRP 实现内网穿透

如何通过 FRP 实现内网穿透&#xff1a;群晖 NAS 的 Gitea 和 GitLab 访问配置指南 在自建服务的过程中&#xff0c;经常会遇到内网访问受限的问题。本文将介绍如何利用 FRP&#xff08;Fast Reverse Proxy&#xff09;来实现内网穿透&#xff0c;以便在外网访问群晖 NAS 上的…

我们来学mysql -- EXPLAIN之select_type(原理篇)

EXPLAIN之select_type 题记select_type 题记 书接上文《 EXPLAIN之ID》2024美国大选已定&#xff0c;川普剑登上铁王座&#xff0c;在此过程中出谋划策的幕僚很重要&#xff0c;是他们决定了最终的执行计划在《查询成本之索引选择》中提到&#xff0c;explain的输出&#xff0…

uni-app快速入门(五)--判断运行环境及针对不同平台的条件编译

一、判断运行环境 在实际项目开发中&#xff0c;经常需要进行开发环境和生产环境的切换&#xff0c;uni-app可根据process.env.NODE_ENV判断当前运行环境是开发环境和生产环境&#xff0c;根据不同的环境调用不同的后台接口&#xff0c;具体实现方式: 在项目的static目录下建…

北京大学c++程序设计听课笔记101

基本概念 程序运行期间&#xff0c;每个函数都会占用一段连续的内存空间。而函数名就是该函数所占内存区域的起始地址&#xff08;也称“入口地址”&#xff09;。我们可以将函数的入口地址赋给一个指针变量&#xff0c;使该指针变量指向该函数。然后通过指针变量就可以调用这个…

构建客服知识库:企业效率提升的关键步骤

客服知识库是企业提升客户服务效率和质量的重要工具。它不仅帮助客服团队快速准确地回答客户问题&#xff0c;还能通过数据分析来优化服务流程和提升客户满意度。 1. 明确知识库的目标和范围 构建客服知识库的第一步是明确其目标和范围。这包括确定知识库的主要用户群体、需要…

Linux运维工程师推荐学习的开发语言

前言&#xff1a;会开发的运维和不会开发的运维可以说是两个世界的运维。 个人推荐python和go&#xff0c;前者可以做自动化运维&#xff0c;后者可以深挖k8s&#xff1b;最近就不先演示运维服务技术的部署和架构搭建了&#xff0c;在深挖自动化运维&#xff0c;为了让现在的工…

整合seata遇到的问题

自己遇到的问题&#xff0c;记录一下。 1、版本问题 我seata用的是1.7&#xff0c; 数据库驱动是 <dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.31</version><scope>…

从零到一:利用 AI 开发 iOS App 《震感》的编程之旅

在网上看到一篇关于使用AI开发的编程经历&#xff0c;分享给大家 作者是如何在没有 iOS 开发经验的情况下&#xff0c;借助 AI&#xff08;如 Claude 3 模型&#xff09;成功开发并发布《震感》iOS 应用。 正文开始 2022 年 11 月&#xff0c;ChatGPT 诞生并迅速引发全球关注。…

.netcore + postgis 保存地图围栏数据

一、数据库字段 字段类型选择(Type) 设置对象类型为&#xff1a;geometry 二、前端传递的Json格式转换 前端传递围栏的各个坐标点数据如下&#xff1a; {"AreaRange": [{"lat": 30.123456,"lng": 120.123456},{"lat": 30.123456…

系统掌握大语言模型提示词 - 从理论到实践

以下是我目前的一些主要个人标签&#xff1a; 6 年多头部大厂软件开发经验&#xff1b;1 年多 AI 业务应用经验&#xff0c;拥有丰富的业务提示词调优经验和模型微调经验。信仰 AGI&#xff0c;已经将 AI 通过自定义 Chatbot /搭建 Agent 融合到我的工作流中。头部大厂技术大学…

k8clone二进制工具迁移k8s中的无状态应用

1 概述 k8clone是一个简便的Kubernetes元数据克隆工具&#xff0c;它可以将Kubernetes元数据&#xff08;对象&#xff09;保存为本地压缩包&#xff0c;在恢复时可将这些元数据恢复到目标集群中&#xff08;已存在的资源不会被覆盖&#xff09;。它不依赖远程存储&#xff0c…

IDC 报告:百度智能云 VectorDB 优势数量 TOP 1

近日&#xff0c;IDC 发布了《RAG 与向量数据库市场前景预测》报告&#xff0c;深入剖析了检索增强生成&#xff08;RAG&#xff09;技术和向量数据库市场的发展趋势。报告不仅绘制了 RAG 技术的发展蓝图&#xff0c;还评估了市场上的主要厂商。在这一评估中&#xff0c;百度智…

计算机毕业设计Python+CNN卷积神经网络股票预测系统 股票推荐系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Nginx SSL+tomcat,使用request.getScheme() 取到https协议

架构上使用了 Nginx tomcat 集群, 且nginx下配置了SSL,tomcat no SSL,项目使用https和http协议。 发现 request.getScheme() //总是 http&#xff0c;而不是实际的http或https request.isSecure() //总是false&#xff08;因为总是http&#xff09; request.getRemoteAddr(…

机器学习 ---线性回归

目录 摘要&#xff1a; 一、简单线性回归与多元线性回归 1、简单线性回归 2、多元线性回归 3、残差 二、线性回归的正规方程解 1、线性回归训练流程 2、线性回归的正规方程解 &#xff08;1&#xff09;适用场景 &#xff08;2&#xff09;正规方程解的公式 三、衡量…

蓝桥杯c++算法学习【3】之思维与贪心(重复字符串、翻硬币、乘积最大、皮亚诺曲线距离【难】:::非常典型的必刷例题!!!)

别忘了请点个赞收藏关注支持一下博主喵&#xff01;&#xff01;&#xff01; 关注博主&#xff0c;更多蓝桥杯nice题目静待更新:) 思维与贪心 一、重复字符串 【问题描述】 如果一个字符串S恰好可以由某个字符串重复K次得到&#xff0c;我们就称S是K次重复字 符串…

Vue3 -- 基于Vue3+TS+Vite项目【项目搭建及初始化】

兼容性注意&#xff1a; Vite 需要 Node.js 版本 18 或 20。然而&#xff0c;有些模板需要依赖更高的 Node 版本才能正常运行&#xff0c;当你的包管理器发出警告时&#xff0c;请注意升级你的 Node 版本。【摘抄自vite官网】 这里我用的node版本是 v18.20.2 创建项目&#xf…