详细介绍:STL 容器 --- list 类

news/2025/9/27 4:15:44/文章来源:https://www.cnblogs.com/lxjshuju/p/19110597

1. 前言

list 中使用的函数与之前所学的,并无太多的区别,下面只简单的讲解一些特殊的地方List 是链表,是之前数据结构所说的带头双向循环链表,使用 list 时需要包含头文件 --- list。原型为:template < class T, class Alloc = allocator<T> > class list

2. list 类

1. 初始化

list 支持无参初始化,n 个 val 值初始化,大括号初始化,迭代器区间初始化,如下代码所示:

template
void Print(list lt)
{
for (auto& e : lt)
{
cout  lt1; // 无参初始化
list lt2(10, 2); // n 个 val 值初始化
Print(lt2);
vector v = { 1, 3, 5, 7, 9 };
listlt3(v.begin(), v.end()); // 迭代器区间初始化
Print(lt3);
list lt4 = { 1, 2, 3, 4, 5 }; // 大括号初始化
Print(lt4);
return 0;
}

代码运行结果:



特殊的是支持用数组来初始化,如下代码所示:

int arr[10] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
list lt5(arr + 2, arr + 7);
Print(lt5);

运行结果:



为什么可以用数组来初始化呢?这里实际上调用了迭代器区间初始化函数。但是该函数的参数明明是迭代器,为什么可以传指针呢?指针是一种特殊的迭代器(前提是该指针是指向数组的指针,容器的迭代器不一定是指针),指向数组的指针的行为符合迭代器,迭代器的行为本质上模拟的就是指向数组的指针

在之前实现 vector 时,提到了算法库中的 sort 函数,该函数的原型为:template <class RandomAccessIterator> void sort (RandomAccessIterator first, RandomAccessIterator last)。它的参数为迭代器区间,它也可以接收数组指针。

2. 迭代器

1. 迭代器是通用的遍历容器的方式,并且封装了容器的底层,屏蔽了容器结构的差异和底层实现的细节

2. 迭代器可以复用/通用,实现算法时,用迭代器函数模板方式实现,跟底层容器结构解耦

3. 支持迭代器也就支持范围for

在查看 cplusplus 网站时也许会发现有些迭代器起的名字有些不同,如下图所示:



InputIterator 是只写迭代器,BidirectionalIterator 是双向迭代器,RandomAccessIterator 是随机迭代器。实践中容器迭代器分为三种类型:单向,双向,随机,它们是从功能的角度进行分类的,所有迭代器的都有的功能:++ ,*,!=;这三种迭代器的功能上有些许不同:

1. 单向迭代器支持:++,*,!=

2. 双向迭代器除了通用功能之外,还支持 - -

3. 随机迭代器除了通用功能之外,还支持 - - /+ /-

怎么知道容器的迭代器是什么类型呢?在 cplusplus 网站上搜索相应的容器,向下划至Member types ,就可以看到了,拿 list 举例子:



总结:

1. 单向:单链表/哈希表

2. 双向:红黑树/双向链表list

3. 随机:string/vector/双端队列deque

一个容器的迭代器是哪种类型由容器的底层结构决定,迭代器支持什么功能与容器的底层支不支持有很大的关系。从算法角度来看,一个算法不是所有的容器都可以使用(就如上述所说的算法库中的 sort 排序算法),算法对迭代器是有一些要求的,算法的迭代器名字就是要求;算法要求传什么类型的迭代器就传什么类型的迭代器,如果不符合它的要求,程序会报错。

但是如果算法要求传单向迭代器,既可以传单向,也可以传双向和随机;如果算法要求传双向迭代器,既可以传双向,也可以传随机。为什么可以这样呢?单向双向随机迭代器之间的关系是继承关系,单向是双向和随机的父类,双向是随机的父类,子类是特殊的父类,要求传父类,可以传子类(了解即可,在继承部分会详细讲解)。

设计迭代器时除了单向双向随机,还有只读和只写迭代器,然而实际使用中并不会使用自读和只写迭代器:



3. sort 函数

list 中提供了 sort 函数,但是算法库中不是存在一个 sort 函数吗,用现成的不行吗?为什么 list 这里还要提供一个函数?因为算法库中的 sort 函数要求传随机迭代器,list 的迭代器是双向的,算法库中的 sort 函数不支持 list 。但是 list 提供的 sort 没什么用,为什么呢?对比算法库中的 sort 函数和 list 的 sort 函数的效率:

生成一百万个随机数,将这些随机数存储到 vector 和 list 容器中,vector 使用算法库中的 sort 函数排序这一百万个数,list 使用自己的 sort 函数排序一百万个数,对比两者排序所需要的时间。

效率比较代码:

srand(time(0));
const int N = 1000000;
vector v;
list lt;
for (int i = 0; i < N; i++)
{
auto e = rand() + i;
v.push_back(e);
lt.push_back(e);
}
int begin1 = clock();
sort(v.begin(), v.end());
int end1 = clock();
int begin2 = clock();
lt.sort();
int end2 = clock();
printf("vector sort:%d\n", end1 - begin1);
printf("list sort:%d\n", end2 - begin2);

运行结果:



这个结果可能不太明显,因为这个是在 debug 版本下运行的结果,接下来在 release 版本下运行代码,结果如下图所示:



再来演示一个场景 --- 生成一百万个随机数,将这些随机数都存储在 list 的实例化对象 lt1 和 lt2 中,其中用 lt1 的迭代器区间初始化 vector 实例化的对象 v,接下来的操作与前面的一样,比较两者排序所需的时间。

效率比较代码:

srand(time(0));
const int N = 1000000;
list lt1;
list lt2;
for (int i = 0; i  v(lt1.begin(), lt1.end());
int begin1 = clock();
sort(v.begin(), v.end());
int end1 = clock();
int begin2 = clock();
lt2.sort();
int end2 = clock();
printf("list copy vector sort:%d\n", end1 - begin1);
printf("list sort:%d\n", end2 - begin2);

运行结果:



为什么 debug 版本下与 release 版本下的运行效率差这么多呢?算法库中的 sort 函数的底层运用了快速排序算法,list 中的 sort 函数的底层运用了归并排序算法。快速排序算法中使用了递归,在debug 版本下显示不出递归算法的优势;在 release 版本下会自动优化递归算法,所以两个版本下,效率会差很多。

既然算法库中的 sort 函数的底层使用了快速排序算法,list 中的 sort 函数的底层使用了归并排序算法。在学习数据结构排序时,我们知道两个算法针对数组的排序效率是差不多的,时间复杂度均为nlogn。但是针对链表的排序效率是不同的,为什么呢?这与 cpu 高速缓存命中率有关(了解即可)。

所以一般默认存储数据优先使用顺序表 vector 容器,这也是为什么在写那些算法体的时候,提供的容器是 vector。数据是存储在内存中的,vector 和 list 容器的不同之处在于,一个内存空间是连续的,一个内存空间是不连续的。

4. remove 函数和 splice 函数

remove 函数的函数原型为:void remove (const value_type& val),其函数的功能为:从容器中移除与 val 比较结果相等的所有元素。

代码:

list lt1 = { 2,4,5,3,7,3,7,2,1,3 };
Print(lt1);
lt1.remove(3);
Print(lt1);

运行结果:



splice 函数的函数原型为void splice (iterator position, list& x, iterator i),其函数的功能为:将元素从 x 转移到容器中,并将它们插入至指定位置。

代码:

listlt2 = { 2, 4, 6, 8, 0 };
Print(lt2);
auto it = find(lt2.begin(), lt2.end(), 0);
lt2.splice(lt2.begin(), lt2, it);
Print(lt2);

运行结果:



3. 结言

list 中许多函数的功能与 string 和 vector 容器的并无二异,掌握了 string 中的函数的使用方法,list 的函数也不在话下。本文最重要的部分是迭代器部分,之后模拟实现 list 时,最重要的部分也是迭代器部分。

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

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

相关文章

Idea代码回退已经push到远段仓库的代码分支到指定提交记录

步骤一:先打开git对应分支提交记录,回退本地代码到指定commitId。等待提交记录删除。 步骤二:找到要回退的commitId,并清除远端git提交记录Soft:仅移动分支指针,保留工作目录和暂存区的所有修改。相当于撤销了提…

开写第一篇

我的知识能力都是祂所赐的,若不靠着祂我什么也不能做 开写第一篇博客了,之前笔记也记了不少,但是没有正经的整理过,现在开始陆续整理上传。以前总是网上看别人写的技术博客,学了不少东西,希望我自己写的也能帮助…

重庆家居网站制作公司傻瓜建网站

java处理ip的工具类&#xff0c;包括把long类型的Ip转为一般Ip类型、把xx.xx.xx.xx类型的转为long类型、根据掩码位获取掩码、根据 ip/掩码位 计算IP段的起始IP、根据 ip/掩码位 计算IP段的终止IP等方法&#xff0c;可以直接使用&#xff01;package com.hh.test;import java.u…

大模型function calling多轮对话开发示例

OpenAI接口支持的function calling使得大模型能够方便的集成外部能力和数据,是实现agent(智能体)的重要基础,能让LLM和各种功能集成,从而解决复杂的问题。 对于兼容openai接口的大模型如阿里的通义千问,也是可以使…

ViTables 安装与 HDF5 数据可视化全指南 - 实践

ViTables 安装与 HDF5 数据可视化全指南 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

elementuiplus修改el-checked多选框样式

elementuiplus修改el-checked多选框样式废话不多说直接上代码: 1、给check加类名 2、css样式:/deep/.image-checkbox .el-checkbox__input .el-checkbox__inner {/* 隐藏原生复选框 */display: none; }/deep/.image…

怎样用dw做 网站首页网站关键词排行查询

首先&#xff0c;对于零基础的想学习C的同学&#xff0c;我想要你们先明白一件事&#xff1a;C是一门极为复杂且难以掌握的编程语言。因此推荐在学习C之前可以先去学习C语言&#xff0c;在拥有了一定的知识储备和编程能力后再学习C会更加的高效和相对轻松。 下面推荐从三个方面…

宜昌营销网站建设ppt模板免费下载素材医学类

一&#xff0c;dns与域名 网络基于tcp/ip协议进行通信和连接的&#xff0c;其中主机以ip地址做固定的地址标识&#xff0c;用以区分用户和计算机。ip地址是由32位二进制数组成&#xff0c;不方便记忆。为了方便记忆&#xff0c;采用了域名。但是网络通信的唯一标识是ip地址&…

DataGrip格式化SQL模板

个人使用比较好的,各位可以根据自己的使用习惯自行调整。 点击下载

靶向肽Dcpep - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

做一个网站完整的网页app软件开发sh365

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 文章目录 系列文章目录前言一、空间范围中点位数量的快速统计算法1.引入库2.百度地图基于范围的搜索 Java 前…

企业网站制作机构排名wordpress html音乐

基于STM32单片机多功能智能小车功能说明&#xff1a; TFTLCD显示按键LVGL&#xff08;菜单、小车工作模式选择、设置&#xff09;手机蓝牙遥控模式射频手柄遥控模式5路红外寻迹模式超声波避障模式语音播报低功耗控制 硬件原理图设计 单片机最小系统&#xff1a; 由于要使用…

怎么做盗号网站手机开发一个小程序游戏要多少钱

617.合并二叉树&#xff08;经典&#xff09; 合并二叉树是操作两棵树的题目里面很经典的&#xff0c;如何对两棵树遍历以及处理&#xff1f; 给定两个二叉树&#xff0c;想象当你将它们中的一个覆盖到另一个上时&#xff0c;两个二叉树的一些节点便会重叠。 你需要将他们合并…

在库言库建筑网站网页制作模板田田田田田田田田田田田田田田

1 vi 简介vi 编辑器是 Linux 和 Unix 上最基本的文本编辑器&#xff0c;工作在字符模式下。由于不需要图形界面&#xff0c;vi 是效率很高的文本编辑器。尽管在 Linux 上也有很多图形界面的编辑器可用&#xff0c;但 vi 在系统和服务器管理中的功能是那些图形编辑器所无法比拟的…

图思维胜过链式思维:JGraphlet构建任务流水线的八大核心原则

JGraphlet是一个轻量级零依赖的Java任务流水线库,采用有向无环图模型管理任务依赖关系。支持同步/异步任务混合执行、显式API设计、扇入输入处理、资源生命周期管理、上下文共享和可选缓存机制,适用于并行检索、数据…

两月九城,纷享销客渠道携手伙伴共创CRM新纪元

9月18日,SCEE 2025 中国软件渠道生态大会华南峰会在深圳成功举办。纷享销客作为中国 CRM 行业领导者再度登台,全国渠道运营负责人冯涛发表《智享未来,创领CRM新纪元》主题演讲,向华南区域伙伴全面传递纷享销客渠道…

el-upload上传图片

<el-upload上传图片1 官方文档文档2 说明这个组件提供了一种默认的上传模式,点击图片上传的时候就自动把图片发送到服务端,而不是在提交表单的时候上传。这钟模式不够灵活,也可以设置不自动上传到服务器,自己提…

wordpress 爱奇艺插件下载专业的网站优化公司

一、ADC简介 ADC是Analog-to-DigitalConverter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。 STM32f103 系列有3个ADC&#xff0c;精度为12位&#xf…

东莞网站建设企业营销型网站建设哪家好

1、第一步肯定是要新建自己还原的目标数据库&#xff0c;例如&#xff1a; 2、进入postgresql的安装目录下的bin目录下 然后地址栏输入cmd进入命令 输入以下 psql -h localhost -U postgres -p 5432 -d SamsinoYardStandard_karamay -f "D:\desktop\zk\20230628.bak&quo…