Day 26 C++ list容器(链表)
文章目录
- list基本概念
 - 定义
 - 结构
 - 双向迭代器
 - 优点
 - 缺点
 - List和vector区别
 - 存储结构
 - 内存管理
 - 迭代器稳定性
 - 随机访问效率
 
- list构造函数——创建list容器
 - 函数原型
 - 示例
 
- list 赋值和交换
 - 函数原型
 
- list 大小操作
 - 函数原型
 - 示例
 
- list 插入和删除
 - 函数原型
 - 示例
 
- list 数据存取
 - 函数原型
 - 注意
 - 示例
 
- list 反转和排序
 - 函数原型
 - 示例
 - 高级排序——在排序规则上再进行一次逻辑规则制定
 
list基本概念
定义
链表(list)是一种物理存储单元上非连续的存储结构,可以将数据进行链式存储,数据元素的逻辑顺序是通过链表中的指针链接实现的。STL中的链表是一个双向循环链表。
结构
链表的组成:链表由一系列结点组。
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
 ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P6joB49u-1691658357899)(assets/clip_image002-1547608564071.jpg)]](https://img-blog.csdnimg.cn/1d0b240f129c4a8cab7abd4324559dc6.png)
双向迭代器
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
优点
- 采用动态存储分配,不会造成内存浪费和溢出
 - 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
 
缺点
- 链表灵活,但是空间(指针域) 和 时间(遍历)额外耗费较大
 
> 链表在每个节点都需要存储额外的指针域,会消耗更多的内存空间。此外,由于链表是非连续存储的,访问特定位置的元素需要从头或尾按顺序遍历链表,时间复杂度为O(n),相对于向量的常数时间访问O(1),效率较低。
List和vector区别
存储结构
list是一个双向链表,每个节点包含一个值和前后指针;
 而vector是一个动态数组,使用连续的内存块来存储元素。
内存管理
由于list使用动态内存分配,可以在任意位置高效地插入和删除元素,但同时会产生额外的指针开销;
 而vector使用连续的内存块,尽管插入和删除操作需要移动元素,但内存访问位置更加连续,可以提供更好的缓存性能。
迭代器稳定性
在list中,插入或删除元素不会影响已存在的迭代器的有效性;
 而在vector中,当插入或删除元素时,可能会导致迭代器失效,需要重新获取。
随机访问效率
由于vector使用连续的内存块,可以通过索引随机访问元素,并具有较好的性能;
 而list为了访问指定位置的元素,需要从头或从尾按顺序遍历链表,效率较低。
在插入和删除频繁的场景下,list可能更适合;
而在需要快速随机访问元素或者容器规模较大的情况下,vector可能更合适。
list构造函数——创建list容器
函数原型
list<T> lst;//list采用采用模板类实现,对象的默认构造形式:list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。list(n,elem);//构造函数将n个elem拷贝给本身。list(const list &lst);//拷贝构造函数。
list构造方式同其他几个STL常用容器一致
示例
#include <list>
#include <iostream>
#include <list>int main() {// 示例1:使用默认构造函数创建空的liststd::list<int> myList1;// 示例2:使用迭代器构造函数将数组中的元素拷贝到list中int arr[] = {1, 2, 3, 4, 5};std::list<int> myList2(arr, arr + sizeof(arr) / sizeof(int));// 示例3:使用元素数量和元素值构造liststd::list<int> myList3(3, 10); // 包含三个值为10的元素// 示例4:使用拷贝构造函数创建一个副本std::list<int> myList4(myList3);// 输出list中的元素std::cout << "myList1: ";for (const auto& element : myList1) {std::cout << element << " ";}std::cout << std::endl;std::cout << "myList2: ";for (const auto& element : myList2) {std::cout << element << " ";}std::cout << std::endl;std::cout << "myList3: ";for (const auto& element : myList3) {std::cout << element << " ";}std::cout << std::endl;std::cout << "myList4: ";for (const auto& element : myList4) {std::cout << element << " ";}std::cout << std::endl;return 0;
} 
输出
 myList1:
 myList2: 1 2 3 4 5
 myList3: 10 10 10
 myList4: 10 10 10
list 赋值和交换
函数原型
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。assign(n, elem);//将n个elem拷贝赋值给本身。list& operator=(const list &lst);//重载等号操作符swap(lst);//将lst与本身的元素互换。
示例:
#include <iostream>
#include <list>int main() {std::list<int> myList1 = {1, 2, 3};std::list<int> myList2 = {4, 5, 6};std::cout << "Before swap:" << std::endl;std::cout << "myList1: ";for (const auto& element : myList1) {std::cout << element << " ";}std::cout << std::endl;std::cout << "myList2: ";for (const auto& element : myList2) {std::cout << element << " ";}std::cout << std::endl;// 使用swap函数交换两个list的元素myList1.swap(myList2);std::cout << "After swap:" << std::endl;std::cout << "myList1: ";for (const auto& element : myList1) {std::cout << element << " ";}std::cout << std::endl;std::cout << "myList2: ";for (const auto& element : myList2) {std::cout << element << " ";}std::cout << std::endl;return 0;
} 
输出
 Before swap:
 myList1: 1 2 3
 myList2: 4 5 6
 After swap:
 myList1: 4 5 6
 myList2: 1 2 3
list 大小操作
函数原型
-  
size();//返回容器中元素的个数 -  
empty();//判断容器是否为空 -  
resize(num);//重新指定容器的长度为num,若容器变长,则以默认值0填充新位置。 //如果容器变短,则末尾超出容器长度的元素被删除。
 -  
resize(num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。//如果容器变短,则末尾超出容器长度的元素被删除。
 
示例
#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3, 4, 5};// 使用size函数获取容器中元素的个数std::cout << "Size of myList: " << myList.size() << std::endl;// 使用empty函数判断容器是否为空if (myList.empty()) {std::cout << "myList is empty." << std::endl;} else {std::cout << "myList is not empty." << std::endl;}// 使用resize函数改变容器的长度为7,默认填充0myList.resize(7);std::cout << "myList after resize to size 7 with default value:" << std::endl;for (const auto& element : myList) {std::cout << element << " ";}std::cout << std::endl;// 使用resize函数改变容器的长度为10,使用值9填充新位置myList.resize(10, 9);std::cout << "myList after resize to size 10 with value 9:" << std::endl;for (const auto& element : myList) {std::cout << element << " ";}std::cout << std::endl;// 使用resize函数将容器的长度改为3myList.resize(3);std::cout << "myList after resize to size 3:" << std::endl;for (const auto& element : myList) {std::cout << element << " ";}std::cout << std::endl;return 0;
} 
输出
 Size of myList: 5
 myList is not empty.
 myList after resize to size 7 with default value:
 1 2 3 4 5 0 0
 myList after resize to size 10 with value 9:
 1 2 3 4 5 0 0 9 9 9
 myList after resize to size 3:
 1 2 3
在示例中,我们创建了一个list对象myList并初始化它的元素。
 然后,我们使用size函数输出容器的大小,使用empty函数判断容器是否为空。
 接着,我们使用resize函数将容器的大小分别改变为7、10和3。
 当容器变大时,新位置会用默认值0或指定的值9进行填充;
 当容器变小时,末尾超出容器长度的元素会被删除。最终,我们打印出修改后的容器内容
list 插入和删除
函数原型
- push_back(elem);//在容器尾部加入一个元素
 - pop_back();//删除容器中最后一个元素
 - push_front(elem);//在容器开头插入一个元素
 - pop_front();//从容器开头移除第一个元素
 - insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
 - insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
 - insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
 - clear();//移除容器的所有数据
 - erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
 - erase(pos);//删除pos位置的数据,返回下一个数据的位置。
 - remove(elem);//删除容器中所有与elem值匹配的元素。
 
注意
 插入多个数据无返回值,删除返回下一个数据位置
 beg end 均为迭代器
示例
#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3, 4, 5};std::cout << "Initial myList:" << std::endl;for (const auto& element : myList) {std::cout << element << " ";}std::cout << std::endl;// 在容器尾部加入一个元素myList.push_back(6);// 删除容器中最后一个元素myList.pop_back();// 在容器开头插入一个元素myList.push_front(0);// 从容器开头移除第一个元素myList.pop_front();// 在指定位置插入元素的拷贝auto it = myList.begin();std::advance(it, 2);myList.insert(it, 7);// 在指定位置插入多个相同元素it = myList.begin();std::advance(it, 3);myList.insert(it, 3, 8);// 在指定位置插入另一个区间的元素std::list<int> newElements = {9, 10};it = myList.begin();std::advance(it, 4);myList.insert(it, newElements.begin(), newElements.end());std::cout << "myList after modifications:" << std::endl;for (const auto& element : myList) {std::cout << element << " ";}std::cout << std::endl;// 移除容器的所有数据myList.clear();std::cout << "myList after clear:" << std::endl;if (myList.empty()) {std::cout << "myList is empty." << std::endl;} else {std::cout << "myList is not empty." << std::endl;}return 0;
} 
list 数据存取
函数原型
front();//返回第一个元素。back();//返回最后一个元素。
注意
list容器的迭代器是双向迭代器,不支持随机访问,没有索引,不能跳跃访问 ,也不可以通过[]或者at方式访问数据
示例
#include <list>//数据存取
void test01()
{list<int>L1;L1.push_back(10);L1.push_back(20);L1.push_back(30);L1.push_back(40);//cout << L1.at(0) << endl;//错误 不支持at访问数据//cout << L1[0] << endl; //错误  不支持[]方式访问数据cout << "第一个元素为: " << L1.front() << endl;cout << "最后一个元素为: " << L1.back() << endl;//list容器的迭代器是双向迭代器,不支持随机访问list<int>::iterator it = L1.begin();//it = it + 1;//错误,不可以跳跃访问,即使是+1
}int main() {test01();system("pause");return 0;
} 
list 反转和排序
函数原型
reverse();//反转链表sort();//链表排序 //默认的排序规则 从小到大 升序
示例
#include <iostream>
#include <list>int main() {std::list<int> myList = {5, 2, 4, 1, 3};// 反转链表myList.reverse();std::cout << "Reversed list: ";for (const auto& element : myList) {std::cout << element << " ";}std::cout << std::endl;// 链表排序myList.sort();std::cout << "Sorted list: ";for (const auto& element : myList) {std::cout << element << " ";}std::cout << std::endl;return 0;
} 
输出
 Reversed list: 3 1 4 2 5
 Sorted list: 1 2 3 4 5
高级排序——在排序规则上再进行一次逻辑规则制定
- 对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
 - 高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂
 
#include <iostream>
#include <vector>
#include <algorithm>struct Student {std::string name;int age;int score;
};bool compareStudents(const Student& student1, const Student& student2) {// 先按分数降序排序if (student1.score != student2.score) {return student1.score > student2.score;}// 如果分数相同,则按年龄升序排序if (student1.age != student2.age) {return student1.age < student2.age;}// 如果分数和年龄都相同,则按姓名的字典序升序排序return student1.name < student2.name;
}int main() {// 创建学生对象std::vector<Student> students = {{"Alice", 20, 90}, {"Bob", 18, 85}, {"Charlie", 19, 90}};// 使用自定义的排序规则对学生进行排序std::sort(students.begin(), students.end(), compareStudents);// 输出排序结果for (const auto& student : students) {std::cout << "Name: " << student.name << ", Age: " << student.age << ", Score: " << student.score << std::endl;}return 0;
} 
首先,我们定义了一个名为Student的结构体,包含学生的姓名、年龄和分数。
 接下来,我们实现了一个名为compareStudents的自定义比较函数。
 该函数根据学生的分数、年龄和姓名进行排序。
 首先按照分数降序排序,如果分数相同,则按照年龄升序排序,最后按照姓名的字典序升序排序。
 在主函数中,我们创建了一个存储学生对象的vector,并初始化了几个学生对象。
 然后,我们使用std::sort函数对学生对象进行排序,传入自定义的比较函数作为参数。
 最后,我们遍历排序后的学生对象,并输出姓名、年龄和分数。
相关文章:
Day 26 C++ list容器(链表)
文章目录 list基本概念定义结构双向迭代器优点缺点List和vector区别存储结构内存管理迭代器稳定性随机访问效率 list构造函数——创建list容器函数原型示例 list 赋值和交换函数原型 list 大小操作函数原型示例 list 插入和删除函数原型示例 list 数据存取函数原型注意示例 lis…...
【深度学习注意力机制系列】—— SKNet注意力机制(附pytorch实现)
SKNet(Selective Kernel Network)是一种用于图像分类和目标检测任务的深度神经网络架构,其核心创新是引入了选择性的多尺度卷积核(Selective Kernel)以及一种新颖的注意力机制,从而在不增加网络复杂性的情况…...
Markdown语法和表情
Markdown语法和表情 1. 标题2. 段落3. 加粗和斜体4.分隔线5.删除线6.下划线7.引用8.列表9.链接10. 图片11. 代码12.Markdown 表格其他1.支持的 HTML 元素2.转义3.公式 Markdown表情参考 Markdown 是一种轻量级的标记语言,用于简洁地编写文本并转换为HTML。它的语法简…...
CSDN编纂目录索引跳转设置
CSDN编纂目录索引跳转设置 文章目录 题目第一小节第二小节第三小节结论 题目 第一小节 第二小节 第三小节 结论...
cpu的架构
明天继续搞一下cache,还有后面的, 下面是cpu框架图 开始解释cpu 1.控制器 控制器又称为控制单元(Control Unit,简称CU),下面是控制器的组成 1.指令寄存器IR:是用来存放当前正在执行的的一条指令。当一条指令需要被执行时,先按…...
FastAPI和Flask:构建RESTful API的比较分析
Python 是一种功能强大的编程语言,广泛应用于 Web 开发领域。FastAPI 和 Flask 是 Python Web 开发中最受欢迎的两个框架。本文将对 FastAPI 和 Flask 进行综合对比,探讨它们在语法和表达能力、生态系统和社区支持、性能和扩展性、开发工具和调试支持、安…...
用康虎云报表打印二维码
用康虎云报表打印二维码 1 安装: 下载地址: https://www.khcloud.net/cfprint_download, 选择Odoo免代码报表模块和自定义SQL报表模块 下载下来后解压缩,一共有四个模块 cf_report_designer # 报表设计模块 cf_sale_print_ext # 演示模块 cf_sql_report cfprint …...
网盘直链下载助手
一、插件介绍 1.介绍 这是一款免费开源获取网盘文件真实下载地址的油猴脚本,基于 PCSAPI,支持 Windows,Mac,Linux 等多平台,支持 IDM,XDown,Aria2 等多线程下载工具,支持 JSON-RPC…...
【EI复现】售电市场环境下电力用户选择售电公司行为研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
并发——何谓悲观锁与乐观锁
乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。 悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会…...
【C++】模板
1.模板的概念 2.函数模板基本语法 3.未完待续。。。 https://www.bilibili.com/video/BV1et411b73Z?p169&spm_id_frompageDriver&vd_sourcefb8dcae0aee3f1aab700c21099045395...
【Echart地图】jQuery+html5基于echarts.js中国地图点击弹出下级城市地图(附完整源码下载)
文章目录 写在前面涉及知识点实现效果1、实现中国地图板块1.1创建dom元素1.2实现地图渲染1.3点击地图进入城市及返回 2、源码分享2.1 百度网盘2.2 123云盘2.3 邮箱留言 总结 写在前面 这篇文章其实我主要是之前留下的一个心结,依稀记得之前做了一个大屏项目的时候&…...
Python AI 绘画
Python AI 绘画 本文我们将为大家介绍如何基于一些开源的库来搭建一套自己的 AI 作图工具。 需要使用的开源库为 Stable Diffusion web UI,它是基于 Gradio 库的 Stable Diffusion 浏览器界面 Stable Diffusion web UI GitHub 地址:GitHub - AUTOMATI…...
mongodb:环境搭建
mongodb 是什么? MongoDB是一款为web应用程序和互联网基础设施设计的数据库管理系统。没错MongoDB就是数据库,是NoSQL类型的数据库 为什么要用mongodb? (1)MongoDB提出的是文档、集合的概念,使用BSON&am…...
Grafana技术文档--基本安装-docker安装并挂载数据卷-《十分钟搭建》
阿丹: Prometheus技术文档--基本安装-docker安装并挂载数据卷-《十分钟搭建》_一单成的博客-CSDN博客 在正确安装了Prometheus之后开始使用并安装Grafana作为Prometheus的仪表盘。 一、拉取镜像 搜索可拉取版本 docker search Grafana拉取镜像 docker pull gra…...
【Github】Uptime Kuma:自托管监控工具的完美选择
简介: Uptime Kuma 是一款强大的自托管监控工具,通过简单的部署和配置,可以帮助你监控服务器、VPS 和其他网络服务的在线状态。相比于其他类似工具,Uptime Kuma 提供更多的灵活性和自由度。本文将介绍 Uptime Kuma 的功能、如何使…...
linux环形缓冲区kfifo实践3:IO多路复用poll和select
基础知识 poll和select方法在Linux用户空间的API接口函数定义如下。 int poll(struct pollfd *fds, nfds_t nfds, int timeout); poll()函数的第一个参数fds是要监听的文件描述符集合,类型为指向struct pollfd的指针。struct pollfd数据结构定义如下。 struct poll…...
SpringBoot系列---【使用jasypt把配置文件密码加密】
使用jasypt把配置文件密码加密 1.引入pom坐标 <dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.5</version> </dependency> 2.新增jasypt配置 2.1…...
大数计算(大数加法/大数乘法)
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C 🔥座右铭:“不要等到什么都没有了,才下…...
【腾讯云 Cloud Studio 实战训练营】基于Cloud Studio构建React完成点餐H5页面
前言 【腾讯云 Cloud Studio 实战训练营】基于Cloud Studio 构建React完成点餐H5页面一、Cloud Studio介绍1.1 Cloud Studio 是什么1.2 相关链接1.3 登录注册 二、实战练习2.1 初始化工作空间2.2 开发一个简版的点餐系统页面1. 安装 antd-mobile2. 安装 less 和 less-loader3. …...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
