【C++】-list的具体使用

在这里插入图片描述
💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee✨
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、什么是list
  • 二、具体使用
    • 2.1构造函数
    • 2.2迭代器的使用
    • 2.3容量的函数
    • 2.4修改函数
    • 2.5其他的操作函数
  • 三、总结


前言

今天,博主来给大家介绍STL中的另一个容器——list的具体使用,这个容器平时使用的也非常的多,接口也挺多的,但是有的部分和之前的意思的一样的,有不一样的接口再重点讲解一下,话不多说,我们一起来看正文。


一、什么是list

我们一起来看一下文档:
在这里插入图片描述

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。

我们发现底层是双向链表,倒是再模拟实现的时候难度就有所提升。大致了解list是一个什么样的容器了吧,接下来就看他的具体使用:

二、具体使用

2.1构造函数

我们要使用list必须先将list的对象创建出来,所以目前看他的构造函数:

在这里插入图片描述
这个几乎和vector的构造函数一模一样,来看示例:

	list<int> lt1;//默认构造list<int> lt2(4, 1);//构造n个大小的空间,并初始化为想要的值int a[] = { 1,2,3,4 };list<int> lt3(a,a+4);//通过其他迭代器进行构造list<int> lt4(lt3);//拷贝构造

在这里插入图片描述

2.2迭代器的使用

再list我们的迭代器的好处就体现出来了,它不像string或者vector一样可以通过下标来访问,因为这两个都是连续的空间,而list是链表一样的结构,通过下标肯定是不行了,所以我们只能使用迭代器来访问list里面的元素:

在这里插入图片描述


我们的容易提供的迭代器接口都是一样的,就是为了方便一个会了,其他的都会了,降低了学习成本,但是我们再底层的实现都是千差万别的,我们先来看看使用吧:

	list<int> lt1(4, 1);list<int>::iterator it = lt1.begin();while (it != lt1.end()){(*it) = 100;cout << *it << " ";it++;}

在这里插入图片描述

既然这样,我们来简单说明一下,我们发现我们的使用和之前的是一样的,不管是解引用还是++或者结束条件的判断都是一样的,再vector或者string那一块,我们还可以想懂,因为地址是连续的一块空间,迭代器就是地址,++就是加了此类型的空间大小,跳到下一个元素的,但是再list当中就不一样了,我们的链表地址是不连续的,那么++怎么找到的下一个位置,肯定不是加类型的大小,就找到下一下位置,我们之前学过链表,想要找到下一个位置,就需要通过next指针去找,说明我们的迭代器++肯定做了运算符重载,才达到此目的,解引用等其他操作肯定都重载了,既然有重载,我们不可能把一个单独的节点弄成指针的形式,而是要将节点封装成一个迭代器,再定义一个结构体,完成其他操作的重载,就可以达到我们后面想要的操作,等到模拟实现的时候再好好解释一样

节点也不是单纯的内置类型,节点里面的成员变量是内置类型,节点是自定义类型,我们到时候使用迭代器的时候,就不能像内置类型一样,使用原始指针(int* double*)假设节点叫node,不能使用node这样的迭代器,迭代器的主要作用是访问节点里面的数据,node将节点整体的打包起来起来了取得地址,这是管理节点的方式,是list本身去管理的,不是迭代器的事,迭代器只管访问里面的数据,目前有的抽象,大家先看着理解。


既然迭代器可以使用,那我们的范围for也就可以使用了

	list<int> lt1(4, 1);list<int>::iterator it = lt1.begin();for (auto& e : lt1){e += 10;cout << e << " ";}cout << endl;

在这里插入图片描述
迭代器到时候再sort那块再讲一点细节,模拟实现是重点,我们来看下一个操作

2.3容量的函数

在这里插入图片描述
我们发现对于容量的操作据这么两个,相比较前面的vector和string,少了reserve,因为此结构是链表,不存在扩容的情况,而resize是放在修改那一块,不算改变容量,所以只有这上面两个接口:

	list<int> lt1(4, 1);cout << lt1.size() << endl;cout << lt1.empty() << endl;

在这里插入图片描述

2.4修改函数

在这里插入图片描述
(1)头插头删和尾插尾删
我们看到头插头删,尾插尾删,在vector中,我们只有尾插尾删,因为头插头删对于vector来说消耗太大,需要把所有数据都挪动,而list不存在这样的情况,所以提供了头插头删,来看一下使用:

	list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);//尾插print(lt1);lt1.push_front(100);lt1.push_front(90);lt1.push_front(80);lt1.push_front(70);//头插print(lt1);lt1.pop_back();lt1.pop_back();//尾删print(lt1);lt1.pop_front();lt1.pop_front();//头删print(lt1);

在这里插入图片描述
(2)insert和erase
在这里插入图片描述
对于insert我们发现也有三个接口,但是要主要的时候,我们不能通过lt1.begin()+3这种方式来传迭代器,空间不连续,也侧面说明迭代器内部内有重载+这个运算符,只能通过循环先找到想要的位置,我们来看具体怎么操作的:

//90 100 1 2//想在第2个位置插入一个10auto it = lt1.begin();//lt1.insert(it+1, 10);这种是不对的for (int i = 0; i < 1; i++){++it;}lt1.insert(it, 10);print(lt1);//想在第2个位置后插入一个数组int a[] = { 5,6,7,8 };lt1.insert(it, a, a + 4);print(lt1);

在这里插入图片描述
这是相比较前面两个不太的地方

在这里插入图片描述
参数列表都是和之前一样的,传的迭代器和上面的insert一样需要重新计算出来:

	auto it = lt1.begin();for (int i = 0; i < 1; i++){++it;}lt1.erase(it);print(lt1);//想把第二个位置后面三个值都删除,就是删除第三个位置和第五个位置删除auto first = lt1.begin();auto last = lt1.begin();for (int i = 0; i < 5; i++){if (i < 2){++first;//先找到第三个位置}++last;//先找到第五个位置}lt1.erase(first, last);print(lt1);

在这里插入图片描述


迭代器失效的问题:
在前面我们说过什么情况会导致迭代器失效,是迭代器指向了已经释放的空间,才会导致失效,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

在这里插入图片描述
这中就会导致失效,第一次erase就已经导致it指向一个不存在的节点,此时按照之前按的方法重新赋值一下就行了。
在这里插入图片描述
不涉及到扩容,这一块的问题还是相对好解决的,罪域头插头删,尾插尾删都是复用insert和erase,这个就不给大家测试了。

(3)resize和clear
之前是放在容量那一块,这个改变有效字符个数也涉及不到扩容,所以就放在修改函数这一块了,我们来看看具体使用吧

	list<int> lt1;lt1.resize(5, 20);print(lt1);lt1.clear();print(lt1);

在这里插入图片描述

这个用法和前面的一样。

2.5其他的操作函数

接下来的函数有几个是之前没有学到的函数,重点介绍一下

在这里插入图片描述
(2)splice函数
这是拼接函数,准确来说是转移函数,将另一个链表的数据转移到另一个链表上,原来链表的数据就没有了
在这里插入图片描述
我们来看使用:

	list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);list<int> lt2;lt2.push_back(100);lt2.push_back(200);lt2.push_back(300);lt2.push_back(400);cout << "void splice(iterator position, list & x);//把lt2的数据转移到lt1的开头" << endl;print(lt1);print(lt2);lt1.splice(lt1.begin(), lt2);print(lt1);print(lt2);cout << "void splice(iterator position, list & x, iterator i);//把lt1的第一个数据转移到lt2的开头,只转移一个" << endl;lt2.splice(lt2.begin(), lt1, lt1.begin());print(lt1);print(lt2);cout << "void splice(iterator position, list & x, iterator first, iterator last);//把lt1的一部分数据转移到lt2的开头" << endl;lt2.splice(lt2.begin(), lt1, lt1.begin(), lt1.end());print(lt1);print(lt2);

在这里插入图片描述
这个函数用到不多,大家了解就好了
(2)remove
在这里插入图片描述
这个函数就是先查找,在进行删除:
在这里插入图片描述

(3)remove_if
这个函数的参数是传一个函数参数,通过函数的功能进行筛选进行删除:
在这里插入图片描述

(4)sort
这个函数博主要重点介绍一下,在vector那个环节,sort函数是在算法里卖弄的,那个一位我们的容器要是排序使用算法里面的排序就好了,但是这里有单独设计了一个,这是为什么,是不是没有意义,我们用一下算法库里面的,在用一下本身的看看有什么区别:
本身的:
在这里插入图片描述
算法库里的:
在这里插入图片描述

在这里插入图片描述
我们发现是库里面的函数出现错误,没有匹配的重载函数,我们也看到我们传的参数应该没有问题啊,但是细心的朋友可能就看出来了,模板参数的名字有所不太一样,来看分析:
在这里插入图片描述
至此我们的list自带的sort是不就有意义了,但是要告诉你一点,意义不大,因为list里面的排序效率太慢了,我们通过vector的排序来比较,但是这样测的话要在realse版本下进行测试
在这里插入图片描述
通过上面的例子可以还行啦,在相同数据的情况,vector使用算法库的排序,比list本身的怕思绪效率要高不好,尤其在数据量特别大的情况下更明显

那我们通过什么办法通过vector来帮助list排序呢??
在这里插入图片描述
将数据拷贝到vector进行排序,然后再拷贝回来就可以了,效率比原来的sort要高

原因是算法库里面的排序使用的快排,而list本身的排序使用的是归并,所以数据量特别大的时候算法库里面的排序会特别快

注意:
我们一定要在realse版本下运行,上面也说过了,原因是,debug版本会添加许多调试信息,而快排是递归,调试信息会更多,而这里的归并用的是循环,所以调试信息少,如果再debug下测试,算符库里面的排序会慢很多。


(5)merge和reverse
这就是一个归并,两个合并成一个有序,前提两个链表都是有序的,reverse就是逆置,这两个函数用的不多,我就不用例子来解释了,大家自己去测试一下

三、总结

至此我们的vector的使用就讲解完毕了,接下来博主就要带大家进行模拟实现了,理解难度有所上升,大家要做好准备,把前面的知识点好好复习一下,我们下篇再见
请添加图片描述

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

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

相关文章

HTML学习 第一部分(前端学习)

参考学习网站: 网页简介 (w3schools.com) 我的学习思路是&#xff1a;网站实践视频。 视频很重要的&#xff0c;因为它会给你一种开阔思路的方式。你会想&#xff0c;噢&#xff01;原来还可以这样。这是书本或者网站教程 所不能教给你的。而且&#xff0c;对一些教程&#…

Ubuntu搭建docker+laradock

使用Ubuntu搭建dockerlaradock windows 下载Ubuntu工具二选一 链接&#xff1a;https://pan.baidu.com/s/154K6MKdFZxWqaTn2q-6MSQ 提取码&#xff1a;06lc https://www.jianshu.com/p/b7e11d0dbe8c借鉴地址&#xff1a;https://zhuanlan.zhihu.com/p/547169542 备注&#x…

没有人能真正精通C++

目录 1、C的“双峰”特性 2、没人能真正精通C 3、世界仍然需要C 任何说自己很懂C的人可能都是在夸大其词。 我想你可能已经注意到了&#xff0c;是的&#xff0c;今天的大多数程序员都在使用Python、Rust、Go或是其他新的编程语言。大部分人已经不再需要掌握C、C等古老的编…

微信加粉计数器后台开发

后台包括管理后台与代理后台两部分 管理后台 管理后台自带网络验证卡密系统,一个后台可以完成对Pc端的全部对接,可以自定义修改分组名称 分享等等代理后台 分享页 调用示例 <?php$request new HttpRequest(); $request->setUrl(http://xxxxxxx/api); $request->…

Spingboot 多模块引入第三方jar包

1. 在需要的模块中引入jar包 2. 在此模块中的pom.xml 中引用 3. 要想打包部署服务器&#xff0c;需要在启动模块中添加配置信息 ps&#xff1a;启动模块要引用此模块才能将此一起jar打包部署 <build><plugins><plugin><groupId>org.springframework.…

基于阿里云微信小程序语音识别

页面效果 其中采用阿里云语音识别&#xff1a;阿里云一句话语音识别 语音识别页面 <template><view><view class"chat_list"><view v-for"v in chatList" :class"v.type right ? type_right : type_left"><chat …

Nautilus Chain 更换全新测试网,主网即将在不久上线

目前&#xff0c;Nautilus Chain 正在为主网上线前的最后阶段做准备&#xff0c;据悉该链更新了全新的测试网&#xff0c;在此前版本的测试网的基础上进行了全新的技术升级&#xff0c;最新测试网版本与生态发展的技术规划更为贴近。本次测试网升级将会是最后一次测试网版本的迭…

MacOS上安装Portainer

Portainer介绍 Portainer 是一个很方便的 Docker 可视化管理工具。主要的功能包括: 管理 Docker 主机,可以添加和删除 Docker 主机管理容器,可以启动、停止、删除等容器管理镜像,可以搜索、拉取、删除镜像管理卷,可以查看、删除卷管理网络,可以创建 Docker 网络管理用户和角色…

Redis数据持久化

Redis数据持久化 redis一共提供了两种数据持久化的方式RDB和AOF。 RDB ​ RDB全称为Redis Database Backup file&#xff08;数据备份文件&#xff09;&#xff0c;也被叫做Redis数据快照。简单来说就是将内存中的全部数据都记录到磁盘中&#xff0c;当redis发生宕机或是一些…

VSCode种git rebase分支冲突解决无法继续rebase

情景&#xff1a; 常规来说我们git开分支开发完新功能之后&#xff0c;提交之前rebase dev分支&#xff0c;然后合并到dev上算是开发完成。 问题还原&#xff1a; 在开发完之后执行如下指令&#xff1a; 1.执行变基操作&#xff1a;git rebase dev。 //这一步出现冲突vscode上…

微信小程序基于Promise封装发起网络请求

1.创建一个request.js // 相当于域名 const baseURL ***************; // 暴露一个request函数 export function request(parms) {// 路径拼接const url baseURL parms.url;// 请求体&#xff0c;默认为{}const data parms.data || {};// 请求方式&#xff0c;默认为GETco…

HTTPS详解

1 概述 HTTPS 协议之所以是安全的是因为 HTTPS 协议会对传输的数据进行加密&#xff0c;而加密过程是使用了非对称加密实现。但其实&#xff0c;HTTPS 在内容传输的加密上使用的是对称加密&#xff0c;非对称加密只作用在证书验证阶段。 2 HTTPS请求过程 HTTPS的整体过程分为…

【FAQ】API6低代码开发问题汇总

参考文档&#xff1a; 低代码开发参考文档&#xff1a; 文档中心:使用低代码进行开发 基于景区模板开发元服务&#xff1a; 文档中心:模板简介 使用API6低代码开发遇到的问题汇总情况如下&#xff1a; 1、低代码环境下&#xff0c;如何实现box-shadow阴影效果的配置&#…

Angular 调试工具(Augury)

目录 1、简介 2、检验代码 3、Angury 本地构建和安装 3.1 添加到Chrome 浏览器&#xff1a; 3.2 添加到Firefox浏览器 4、项目中对应的Npm脚本 5、Augury 三大主要功能 5.1 组件树&#xff08;Component Tree&#xff09; 5.1.1 Component Tree 5.2 路由树&#xff0…

带记忆的Transformer模块

MEMORIZING TRANSFORMERS 返回论文和资料目录 论文地址 1.导读 谷歌去年做的一个工作。内容很简单&#xff0c;在Transformer模块中加入了一层记忆层&#xff0c;结果表明这个方法可以帮助模型提高在NLP任务上的表现&#xff1a;generic webtext (C4), math papers (arXiv),…

Generative Adversarial Network

Goodfellow,2014年 文献阅读笔记--GAN--Generative Adversarial NetworkGAN的原始论文-组会讲解_gan英文论文_Flying Warrior的博客-CSDN博客 启发:如何看两个数据是否来自同一个分布? 在统计中,two sample test。训练一个二分类的分类器,如果能分开这两个数据,说明来自…

数据库复习

select 查询 字段别名用 as (可以为中文) 例如 select distinct 关键字 去重复值 例如select distinct deptno from test where 条件过滤 and or 和 not运算符 and同时成立 or有一个成立就可以了 优先级and>or>not不符合&#xff08;!&#xff09; in 匹配多个值 selec…

Windows上查看服务器上tensorboad内容

文章目录 前言一、SSH的设置二、tensorboard命令 前言 本篇文章是针对于局域网内的服务器的tensorboard可视化&#xff0c;由于设置方式稍微有点复杂&#xff0c;导致我每次隔了一段时间之后&#xff0c;就不知道该怎么查看tensorboard了&#xff0c;每次都要百度搜一大堆资料…

SpringCloud系列(十六)[分布式搜索引擎篇] - DSL 查询及相关性算分的学习 (部分)

在SpringCloud系列&#xff08;十五&#xff09;[分布式搜索引擎篇] - 结合实际应用场景学习并使用 RestClient 客户端 API这篇文章中我们已经对 RestClient 有了初步的了解, 并且已经将一些数据进行了存储, 但是这并不是我们学习 ElasticSearch 的目的, ElasticSearch 最擅长的…

物业管理微信小程序的设计与开发

1.物业管理微信小程序实现的功能 该微信小程序包含小程序端&#xff0c;后台管理端以及后端。 小程序端提供给业主使用&#xff0c;实现的功能模块有公告通知、访客预约、车位申请、装修申请、一键报修、报修单、意见反馈、缴费通知、一键求助、个人信息管理&#xff1b; 后台…