C++——list的了解和使用

目录

引言

forward_list与list

标准库中的list

一、list的常用接口

1.list的迭代器

2.list的初始化

3.list的容量操作

4.list的访问操作

5.list的修改操作

6.list的其他操作

二、list与vector的对比

结束语


引言

本篇博客要介绍的是STL中的list。

求点赞收藏评论关注!!!十分感谢!!!

forward_list与list

首先我们先简单了解一下forward_list与list:

forward_list与list都是C++标准模板库(STL)中的容器,它们提供了不同的链表实现,适用于不同的场景。

forward_list

定义与结构:

1.forward_list是C++11引入的一种容器,它提供了一种单向链表的数据结构。

2.它只维护一个指向下一个节点的指针,因此内存使用相对高效。

特点:

1.只能在单向遍历,即只能从前往后遍历,不能反向遍历。

2.在已知位置的情况下,插入和删除操作非常高效,时间复杂度为O(1)。

3.不支持通过索引访问元素,只能使用迭代器进行访问。

适用场景:

1.适用于需要频繁进行前向遍历和插入、删除操作的场景。

2.当内存使用要求较高,且不需要双向遍历时,forward_list是更好的选择。

list

定义与结构:

1.list是C++标准库中基于带头双向循环链表实现的容器。

2.它支持双向迭代器,可以从前往后和从后往前遍历。

特点:

1.在任何位置进行插入和删除操作的时间复杂度都是近似O(1)。

2.支持双向遍历,迭代器使用更灵活。

3.与forward_list相比,内存占用稍多,因为每个节点需要维护两个指针(一个指向前一个节点,一个指向下一个节点)。

适用场景:

1.适用于需要双向遍历和更灵活操作的场景。

2.当需要在列表中间频繁插入或删除元素时,list是更好的选择。

具体内容可以看看这两篇文章:

数据结构——单链表

数据结构——双向链表

本文的重点是list。

标准库中的list

一、list的常用接口

list接口

1.list的迭代器

list的迭代器访问元素与我们之前学习的其他容器的迭代器访问一样。

int main()
{list<int> li = { 1, 2, 3, 4, 5 };list<int>::iterator it = li.begin();cout << "顺序遍历:";while (it != li.end()){cout << *it << " ";++it;}cout << endl;cout << "逆序遍历:";list<int>::reverse_iterator rit = li.rbegin();while (rit != li.rend()){cout << *rit << " ";++rit;}return 0;
}

由于list的迭代器是双向迭代器,支持++和--操作,因此可以在list中向前和向后遍历。

2.list的初始化

list的初始化与我们之前学习的其他容器的初始化一样,我们直接看个简单的使用示例:

int main()
{// 默认构造函数list<int> numbers1;cout << "默认构造: ";for (const auto& num : numbers1) {cout << num << " ";}cout << endl;// n个val构造list<int> numbers2(5, 5);cout << "n个val构造: ";for (const auto& num : numbers2) {cout << num << " ";}cout << endl;int arr[] = { 1, 2, 3, 4, 5 };// 通过vector的迭代器初始化list<int> numbers3(arr, arr + sizeof(arr) / sizeof(arr[0]));cout << "迭代器区间构造: ";for (const auto& num : numbers3) {cout << num << " ";}cout << endl;list<int> numbers4 = { 6, 7, 8, 9, 10 };// 拷贝构造list<int> numbers5(numbers4);cout << "拷贝构造: ";for (const auto& num : numbers5) {cout << num << " ";}cout << endl;numbers1 = numbers2;// 赋值重载cout << "赋值重载: ";for (const auto& num : numbers1) {cout << num << " ";}cout << endl;return 0;
}

输出结果为:

3.list的容量操作
函数名称功能
size返回列表中元素的数量
max_size返回列表可容纳的最大元素数量
empty检查列表是否为空,是则返回 true,否则返回 false
resize重新设置列表中元素的数量,超过原来数量则用默认值填充
clear清空列表中的所有元素

这些函数也是很容易理解的,我们还是直接看代码示例:

int main()
{list<int> li = { 1,2,3,4,5 };cout << "Size of list: " << li.size() << endl;cout << "Max size of list: " << li.max_size() << endl;if (li.empty()){cout << "empty" << endl;}else{cout << "not empty" << endl;}li.clear();if (li.empty()){cout << "empty" << endl;}else{cout << "not empty" << endl;}return 0;
}

输出结果为

与deque这一容器一样,list也没有reserve这一接口。

int main()
{list<int> li = { 1,2,3 };li.resize(5);for (auto& num : li){cout << num << " ";}cout << endl;li.resize(2);for (auto& num : li){cout << num << " ";}return 0;
}

输出结果为;

4.list的访问操作
函数名称功能
back返回列表最后一个元素
front返回列表第一个元素

由于list 是一个双向链表,不支持高效的随机访问。在链表中,访问某个元素需要从头节点开始顺序遍历,直到找到目标元素。因此,为 list 提供下标运算符或 at 方法并不合适。

访问操作的使用示例如下:

int main()
{list<int> li = { 1,2,3 };cout << li.front() << endl;cout << li.back() << endl;return 0;
}

输出结果为:

5.list的修改操作

常用的修改操作有如下几个:

函数名称功能
push_back在列表尾部添加元素
push_front在列表头部添加元素
pop_back删除列表最后一个元素
pop_front删除列表第一个元素
insert在指定位置插入元素
erase删除指定位置或区间的元素
swap交换两个列表
assign使用指定列表替换原列表

这些接口我们也是十分熟悉了,我们直接看代码示例:

尾删和尾插:

int main()
{list<int> li;li.push_back(1);li.push_back(2);li.push_back(3);li.push_back(4);for (auto& num : li) {cout << num << " ";}cout << endl;li.pop_back();for (auto& num : li){cout << num << " ";}cout << endl;return 0;
}

输出结果为:

头删和头插:

int main()
{list<int> li;li.push_front(1);li.push_front(2);li.push_front(3);li.push_front(4);for (auto& num : li){cout << num << " ";}cout << endl;li.pop_front();for (auto& num : li){cout << num << " ";}cout << endl;return 0;
}

输出结果为:

assign和swap:

int main()
{list<int> li1 = { 1,1,1,1,1 };li1.assign(3, 3);for (auto& num : li1){cout << num << " ";}cout << endl;list<int> li2 = { 2,2,2,2,2 };li1.swap(li2);for (auto& num : li1){cout << num << " ";}cout << endl;for (auto& num : li2){cout << num << " ";}return 0;
}

输出结果为:

insert:

int main()
{list<int> li = { 1,2,3,4,5 };list<int>::iterator it = li.begin();it = li.insert(it, 6);it = li.insert(it, 7);for (auto& num : li){cout << num << " ";}return 0;
}

输出结果为:

erase:

int main()
{list<int> li = { 1,2,3,4,5 };list<int>::iterator it = li.begin();it = li.erase(it);for (auto& num : li){cout << num << " ";}return 0;
}

输出结果为:

6.list的其他操作

接下来我们来学习list的其他操作:

函数名称功能描述
splice将元素从一个列表转移到另一个列表
remove移除具有特定值的元素
remove_if移除满足条件的元素
unique移除重复的值
sort对容器中的元素进行排序
merge合并已排序的列表
reverse反转元素的顺序

splice:

splice 是 list 提供的一个成员函数,用于将一个列表(list)中的元素移动到另一个列表中,而不需要进行元素复制或移动操作。

使用示例:

int main()
{list<int> li1 = { 1,2,3 };list<int> li2 = { 4,5,6 };list<int> li3 = { 7,8,9 };list<int> li4 = { 0 };// 将 li2 的所有元素拼接到 li1 的末尾// li1 现在包含 {1, 2, 3, 4, 5, 6}// li2 现在为空 {}li1.splice(li1.end(), li2);for (auto num : li1){cout << num << " ";}cout << endl;// 获取 li3 的迭代器,指向第一个元素(7)auto begin1 = li3.begin();// 将迭代器向前移动一位,指向第二个元素(8)++begin1;// 将 li3 的第一个元素(7)移动到 li4 的末尾// li4 现在包含 {0, 7}// li3 现在包含 {8, 9}li4.splice(li4.end(), li3, li3.begin(), begin1);for (auto num : li4){cout << num << " ";}return 0;
}

输出结果为:

remove:

用于从容器中移除所有等于指定值的元素。

与成员函数 erase 不同,成员函数 erase 按元素的位置擦除元素(使用迭代器),此函数  按元素的值删除元素。

int main()
{list<int> li = { 1,2,3,3,4,5 };li.remove(3);for (auto num : li){cout << num << " ";}cout << endl;return 0;
}

输出结果为:

remove_if:

用于从容器中移除满足特定条件的元素。

bool fun(int num)
{return num == 3;
}int main()
{list<int> li = { 1,2,3,3,4,5 };li.remove_if(fun);for (auto num : li){cout << num << " ";}cout << endl;return 0;
}

输出结果为:

unique:

用于移除容器中连续重复的元素。

int main()
{list<int> li = { 1,2,3,3,4,5 };li.unique();for (auto num : li){cout << num << " ";}return 0;
}

输出结果为:

sort:

用于对容器中的元素进行排序。

int main()
{list<int> li = { 9,1,5,3,2,4,8,0,7,6 };li.sort();for (auto num : li){cout << num << " ";}return 0;
}

输出结果为:

merge:

用于将两个已排序的范围合并成一个有序范围。

要求输入的两个范围必须是有序的(通常是升序)。它会将两个范围中的元素按顺序合并到目标范围中。目标范围必须有足够的空间来存储合并后的结果。

int main()
{list<int> li1 = { 1,3,2,5,7 };list<int> li2 = { 2,3,4,6,8 };li1.sort();li2.sort();li1.merge(li2);for (auto num : li1){cout << num << " ";}return 0;
}

输出结果为:

reverse:

用于反转容器中元素的顺序。

int main()
{list<int> li = { 9,1,5,3,2,4,8,0,7,6 };li.reverse();for (auto num : li){cout << num << " ";}return 0;
}

输出结果为:

二、list与vector的对比

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

结束语

求点赞收藏评论关注!!!

感谢各位大佬的支持!!!

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

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

相关文章

mysql 学习6 DQL语句,对数据库中的表进行 查询 操作

前期准备数据 重新create 一张表 create table emp(id int comment 编号,workno varchar(10) comment 工号,name varchar(10) comment 姓名,gender char comment 性别,ager tinyint unsigned comment 年龄,idcard char(18) comment 身份证号,workaddress varchar(10) c…

Arduino大师练成手册 -- 控制 MH-SD 卡模块

要在 Arduino 上控制 MH-SD 卡模块&#xff0c;你可以按照以下步骤进行&#xff1a; 硬件连接 VCC&#xff1a;连接到 Arduino 的 3.3V 或 5V 引脚&#xff08;根据模块的要求&#xff09;。 GND&#xff1a;连接到 Arduino 的 GND 引脚。 CS&#xff1a;连接到 Arduino 的…

【记录】日常|从零散记录到博客之星Top300的成长之路

文章目录 shandianchengzi 2024 年度盘点概述写作风格简介2024年的创作内容总结 shandianchengzi 2024 年度盘点 概述 2024年及2025年至今我创作了786即84篇文章&#xff0c;加上这篇就是85篇。 很荣幸这次居然能够入选博客之星Top300&#xff0c;这个排名在我之前的所有年份…

Elastic Agent 对 Kafka 的新输出:数据收集和流式传输的无限可能性

作者&#xff1a;来 Elastic Valerio Arvizzigno, Geetha Anne 及 Jeremy Hogan 介绍 Elastic Agent 的新功能&#xff1a;原生输出到 Kafka。借助这一最新功能&#xff0c;Elastic 用户现在可以轻松地将数据路由到 Kafka 集群&#xff0c;从而实现数据流和处理中无与伦比的可扩…

对神经网络基础的理解

目录 一、《python神经网络编程》 二、一些粗浅的认识 1&#xff09; 神经网络也是一种拟合 2&#xff09;神经网络不是真的大脑 3&#xff09;网络构建需要反复迭代 三、数字图像识别的实现思路 1&#xff09;建立一个神经网络类 2&#xff09;权重更新的具体实现 3&am…

Java后端之AOP

AOP&#xff1a;面向切面编程&#xff0c;本质是面向特定方法编程 引入依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>示例&#xff1a;记录…

【25考研】人大计算机考研复试该怎么准备?有哪些注意事项?

人大毕竟是老牌985&#xff0c;复试难度不会太低&#xff01;建议同学认真复习&#xff01;没有机试还是轻松一些的&#xff01; 一、复试内容 由公告可见&#xff0c;复试包含笔试及面试&#xff0c;没有机试&#xff01; 二、参考书目 官方无给出参考书目&#xff0c;可参照…

汽车OEMs一般出于什么目的来自定义Autosar CP一些内容

汽车OEMs在使用AUTOSAR CP(Classic Platform)协议时,可能会根据自身的特定需求对标准协议进行修改,形成自己的企业标准(企标)。这种修改通常是为了满足特定的硬件平台、功能需求、安全要求或优化性能。以下是一些常见的修改场景和例子: 1. 硬件平台适配 企业可能会根据…

基于语义-拓扑-度量表征引导的大语言模型推理的空中视觉语言导航

1. 摘要翻译及主要贡献点 摘要&#xff1a; 空中视觉语言导航&#xff08;VLN&#xff09;是一项新兴任务&#xff0c;它使无人机能够通过自然语言指令和视觉线索在户外环境中导航。由于户外空中场景中复杂的空间关系&#xff0c;这项任务仍然具有挑战性。本文提出了一种端到…

HTML-新浪新闻-实现标题-样式1

用css进行样式控制 css引入方式&#xff1a; --行内样式&#xff1a;写在标签的style属性中&#xff08;不推荐&#xff09; --内嵌样式&#xff1a;写在style标签中&#xff08;可以写在页面任何位置&#xff0c;但通常约定写在head标签中&#xff09; --外联样式&#xf…

LongLoRA:高效扩展大语言模型上下文长度的微调方法

论文地址&#xff1a;https://arxiv.org/abs/2309.12307 github地址&#xff1a;https://github.com/dvlab-research/LongLoRA 1. 背景与挑战 大语言模型&#xff08;LLMs&#xff09;通常在预定义的上下文长度下进行训练&#xff0c;例如 LLaMA 的 2048 个 token 和 Llama2 的…

.NET9增强OpenAPI规范,不再内置swagger

ASP.NETCore in .NET 9.0 OpenAPI官方文档ASP.NET Core API 应用中的 OpenAPI 支持概述 | Microsoft Learnhttps://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/openapi/overview?viewaspnetcore-9.0https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/ope…

景联文科技加入AIIA联盟数据标注分委会

2025年1月16日&#xff0c;中国人工智能产业发展联盟&#xff08;简称AIIA&#xff09;数据委员会数据标注分委会&#xff08;以下简称“分委会”&#xff09;正式成立。景联文科技成为第一批AIIA联盟数据标注分委会委员单位。 数据标注分委会的成立旨在搭建数据标注领域产学研…

SQL Server 建立每日自动log备份的维护计划

SQLServer数据库可以使用维护计划完成数据库的自动备份&#xff0c;下面以在SQL Server 2012为例说明具体配置方法。 1.启动SQL Server Management Studio&#xff0c;在【对象资源管理器】窗格中选择数据库实例&#xff0c;然后依次选择【管理】→【维护计划】选项&#xff0…

Level DB --- TableBuilder

TableBuilder是Level DB里面重要的类和模块&#xff0c;它描述了数据如何序列化到文件中&#xff0c;以及数据里面的格式逻辑。它里面包含了之前介绍的多个模块和类。 data block、filter block和index block block格式&#xff0c;之前已经介绍过Level DB --- BlockBuilder-…

【esp32-uniapp小程序】uniapp小程序篇02——Hbuilder利用git连接远程仓库

一、安装git Git - Downloading Package 下载所需的安装包&#xff0c;点击安装&#xff0c;一路跟着安装指示就行。 二、安装ToriseGit Download – TortoiseGit – Windows Shell Interface to Git 语言包可下载可不下载&#xff0c;软件默认语言是英语。 如果下载了语言…

Java Web-Tomcat Servlet

Web服务器-Tomcat Web服务器简介 Web 服务器是一种软件程序&#xff0c;它主要用于在网络上接收和处理客户端&#xff08;如浏览器&#xff09;发送的 HTTP 请求&#xff0c;并返回相应的网页内容或数据。以下是关于 Web 服务器的详细介绍&#xff1a; 功能 接收请求&#…

MiniMax-01中Lightning Attention的由来(线性注意力进化史)

目录 引言原始注意力线性注意力因果模型存在的问题累加求和操作的限制Lightning AttentionLightning Attention-1Lightning Attention-2 备注 引言 MiniMax-01: Scaling Foundation Models with Lightning Attention表明自己是第一个将线性注意力应用到如此大规模的模型&#…

Linux 内核进程调度

一、进程的分类 在CPU的角度看进程行为的话&#xff0c;可以分为两类&#xff1a; CPU消耗型&#xff1a;此类进程就是一直占用CPU计算&#xff0c;CPU利用率很高。IO消耗型&#xff1a;此类进程会涉及到IO&#xff0c;需要和用户交互&#xff0c;比如键盘输入&#xff0c;占用…

BLE透传方案,IoT短距无线通信的“中坚力量”

在物联网&#xff08;IoT&#xff09;短距无线通信生态系统中&#xff0c;低功耗蓝牙&#xff08;BLE&#xff09;数据透传是一种无需任何网络或基础设施即可完成双向通信的技术。其主要通过简单操作串口的方式进行无线数据传输&#xff0c;最高能满足2Mbps的数据传输速率&…