list的使用

前言

我们前面已经对string和vector进行了学习使用,以及对他们的底层进行了模拟实现!本期我们继续学习STL的另外一个容器---list。

本期内容介绍

什么是list?

list的常用接口

什么是list?

还是来看看官方的文档说明!

这里通过官方文档我们可以知道!list是一个带头双向循环的链表!在插入和删除时,时间复杂度是常量级别的!

list常用接口

在正式的开始介绍接口使用前,我们还是来了解一下类型重命名!

这里主要用到的就是上面的三个! value_type 就是T, reference 是value_type&, size_type 就是size_t

构造、拷贝构造、赋值拷贝、析构

list<int> lt1;//空构造list<int> lt2(10, 6);//n 个 val构造vector<int> v = { 1, 2,4,56,7,8,-1 };list<int> lt3(v.begin(), v.end());//迭代器区间构造list<int> lt4(lt2);//拷贝构造

这里除了介绍这些常见的外!这里在穿插一个C++11引入的一个非常好用的,初始化序列初始化!

这个在上期vector的模拟实现已经介绍了,auto ret = {1,2,3};此时的ret就是initializer_list<int>。

list<int> lt5 = { 1,2,3,4,5 };//C++11的初始化序列初始化

list<int> lt4(lt2);//拷贝构造list<int> lt5 = { 1,2,3,4,5 };//C++11的初始化序列初始化lt5 = lt4;//赋值拷贝

析构还是一样的:清理资源、释放空间~!

迭代器

正向

list<int> lt = { 1,2,3,4,5 };//C++11的初始化序列初始化
const list<int> clt = { 10, 20,30, 40 };list<int>::iterator it = lt.begin();//正向
while (it != lt.end())
{cout << *it << " ";++it;
}
cout << endl;list<int>::const_iterator cit = clt.begin();//const正向
while (cit != clt.end())
{cout << *cit << " ";++cit;
}
cout << endl;

支持迭代器必然支持范围for,范围for就是傻傻的替换迭代器!

反向

list<int>::reverse_iterator it = lt.rbegin();//反向
while (it != lt.rend())
{cout << *it << " ";++it;
}
cout << endl;list<int>::const_reverse_iterator cit = clt.rbegin();//const反向
while (cit != clt.rend())
{cout << *cit << " ";++cit;
}
cout << endl;

const和非const的区别主要还是权限的问题~!如果不修改建议使用const的!!!

注意:这里的迭代器需要指定类域的原因是模板的原因,模板参数不一样就是一个类,为了让迭代器用法统且不冲突,需要指定是哪个类的迭代器~!

容量

empty

list<int> lt = { 1,2,3,4,5,6,7,8,9 };
bool ret = lt.empty();
cout << ret << endl;

size

list<int> lt = { 1,2,3,4,5,6,7,8,9 };
size_t sz = lt.size();
cout << sz << endl;

元素访问

这里文档上说的很清楚:如果是空链表的话,你去取头和尾的数据是未定义的行为!!因为当链表为空时,头尾就是哨兵位的头结点,我们只是规定头结点的next指向实际链表的第一个节点,_prev指向对后一个元素,并未规定头结点的数据域存的是啥,所以如果为空链表,你去取就是未定义行为!

这和begin迭代器不一样,迭代器是返回链表的元素,这里是返回引用!

list<int> lt = { 1,2,3,4,5,6,7,8,9 };
int front = lt.front();
int back = lt.back();cout << front << " " << back << endl;const list<int> clt = { 10, 20,30, 40 };
int cfront = clt.front();
int cback = clt.back();cout << cfront << " " << cback << endl;

修改

删除的这三个是涉及右值引用!在后面的C++11那一期会专门介绍~!

assign

list<int> lt = { 1,2,3,4,5,6,7,8,9,10 };
list<int> lt2;
list<int> lt3 = { 0, 2,4,6,8 };
lt.assign(5, 1);
for (auto& e : lt)
{cout << e << " ";
}
cout << endl;lt2.assign(++lt3.begin(), --lt3.end());
for (auto& e : lt2)
{cout << e << " ";
}
cout << endl;

这个和构造函数那里很像,但是不一样!这个是已经存的你再去把他的原来内容用指定的内容替换掉!

push_front

list<int> lt = { 1,2,3,4 };
lt.push_front(0);
for (auto& e : lt)
{cout << e << " ";
}
cout << endl;

pop_front

list<int> lt = { 1,2,3,4 };lt.pop_front();
for (auto& e : lt)
{cout << e << " ";
}
cout << endl;

push_back

list<int> lt = { 1,2,3,4 };lt.push_back(-5);
for (auto& e : lt)
{cout << e << " ";
}
cout << endl;

pop_back

list<int> lt = { 1,2,3,4 };lt.pop_back();
for (auto& e : lt)
{cout << e << " ";
}
cout << endl;

insert

list<int> lt = { 1,2,3,4 };
lt.insert(lt.begin(), 0);//在pos位置插入一个vallt.insert(++lt.begin(), 5, -1);//在pos位置插入n个valvector<int> v = { 90, 98, 23,34,56 };
lt.insert(lt.begin(), v.begin(), v.end());//在pos位置插入一个迭代器区间

erase

list<int> lt = { 1,2,3,4 };
lt.erase(lt.begin());//删除pos位置的元素lt.erase(++lt.begin(), lt.end());//删除一段迭代器区间

resize

由于是链表,所以不用考虑扩容的问题!这里的resize就要变成了尾插和尾插了!

list<int> lt = { 1,2,3,4 };lt.resize(3);//相当于尾删,只保留前n个元素lt.resize(10, 0);//相当于尾插到节点数目为10,不够的就是0

swap

还是和前面的两个容器的一样,他这里的是对list对象的属性进行交换!

list<int> lt1 = { 1,2,3,4 };
list<int> lt2 = { 10,20,30,40 };lt1.swap(lt2);

clear

list<int> lt = { 1,2,3,4 };lt.clear();
cout << lt.size() << endl;

其他操作

splice

splice是粘结,结合的意思!这个接口的作用是转移链表的元素!重载了三个:

将一个链表的数据转移到另一个链表的pos位置

将一个链表的i位置的元素转移到另一个链表的pos位置

将一个链表的一个迭代器区间转移到另一个链表的pos位置

list<int> lt1 = { 1,2,3,4,5,6,7,8,9 };
list<int> lt2 = { 0, -1,-2 };lt1.splice(lt1.begin(), lt2);//在pos位置,将x转移过来lt2.splice(lt2.end(), lt1, ++lt1.begin());//在pos位置将x的i位置的一个元素转移过来lt2.splice(++lt2.begin(), lt1, ++lt1.begin(), --lt1.end());//在pos位置将x的一段迭代器区间给转移过来

remove

这个函数的作用是:删除所有特定的值!

list<int> lt = { 2,3,2,2,2,4,5,6,1,2 };
lt.remove(2);
print(lt);

remove_if

这个函数的作用是删除符合条件的元素,这里的形参可以是一个对象,也可以是一个函数指针!

bool is_odd(const int& val)
{return val % 2 == 0;
}struct single_digit
{bool operator() (const int& val){return val < 10;}
};void test_list7()
{list<int> lt = { 2,3,2,2,2,4,5,6,1,2,21,11,23 };lt.remove_if(is_odd);print(lt);lt.remove_if(single_digit());print(lt);
}

unique

一看名字就知道这是去重的,但是这个去重是去重连续相邻的重复元素

list<int> lt = { 2,3,2,2,2,2,4,5,6,1,2,21,11,23 };lt.unique();
print(lt);

merge

这接口的作用就是:合并两个链表!但注意:这两个链表必须是有序的!!!!

list<int> lt1 = { 1,3,7,8,9 };
list<int> lt2 = { 2,4,5,7,9 };lt1.merge(lt2);
print(lt1);
print(lt2);//此时lt2是空的

sort

这个接口的作用是:对链表进行排序!它的底层是归并排序!

list<int> lt = { 1,3,2,1,-1,7,8,9 };lt.sort();
print(lt);

但是这个效率就很,,,不太好~!不是归并不行,是链表排序不太行!

OK,举个例子:

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

这个代码是将同样的数据插入到一个vector和一个list,分别对他们排序,看他们排序花费的时间!

差了两倍多!!!再来看一个:

void test_op2()
{srand(time(0));const int N = 1000000;list<int> lt1;list<int> lt2;for (int i = 0; i < N; ++i){auto e = rand();lt1.push_back(e);lt2.push_back(e);}int begin1 = clock();// vectorvector<int> v(lt2.begin(), lt2.end());// sort(v.begin(), v.end());// lt2lt2.assign(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf("list copy vector sort copy list sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);
}

这个代码是:先将两个链表插入相同的数据,在将一个放到vector中排序,然后再拷回来,一个是直接调用链表的sort!

直接差了4倍!所以,list的这个sort效率真不咋地,建议少用~!

reverse

这个函数的作用就是反转链表!

list<int> lt = { 1,2,3,4,5,6,7,8 };
lt.reverse();
print(lt);

非成员函数swap

有这个接口的原因和前面的几个容器一样!防止调到标准库里面的那个!

list<int> lt1 = { 1,2,3};
list<int> lt2 = { 10,20,30, 50};swap(lt1, lt2);
print(lt1);
print(lt2);

OK,本期内容就分享到这里,我们下期再见~!

结束语:不要因为别人的三言两语就打破你的深思熟虑!

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

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

相关文章

网络网络层之(3)IPv6地址

网络网络层之(3)IPv6协议 Author: Once Day Date: 2024年4月2日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day的…

RabbitMQ3.13.x之十_流过滤的内部结构设计与实现

RabbitMQ3.13.x之十_流过滤的内部结构设计与实现 文章目录 RabbitMQ3.13.x之十_流过滤的内部结构设计与实现1. 概念1. 消息发布2. 消息消费 2. 流的结构1. 在代理端进行过滤2. 客户端筛选3. JavaAPI示例4. 流过滤配置5. AMQP上的流过滤6. 总结 3. 相关链接 1. 概念 流过滤的思…

实战篇04:获取用户详细信息

实战篇04&#xff1a;获取用户详细信息 一、接口信息 1.1 基本信息 请求路径&#xff1a;/user/userInfo 请求方式&#xff1a;GET 接口描述&#xff1a;该接口用于获取当前已登录用户的详细信息 1.2 请求参数 无 1.3 响应数据 响应数据类型&#xff1a;application/json …

基于圆柱体镜子和光线跟踪实现镜反射观测全景观图的matlab模拟仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 光线与圆柱镜面的交点计算&#xff1a; 反射光线计算&#xff1a; 全景图坐标转换&#xff1a; 5.完整程序 1.程序功能描述 基于圆柱体镜子和光线跟踪实现镜反射观测全景观图.模拟的场景…

SV学习笔记(七)

文章目录 类型转换写在前面动态转换子类句柄赋值于父类句柄父类句柄转换为子类句柄 虚方法写在前面非虚函数的调用虚函数的调用虚方法的建议为什么使用虚方法 对象拷贝写在前面赋值和拷贝总结 回调函数写在前面实例完成回调函数功能需要三步&#xff1a; 参数化类写在前面实现一…

如何使用极狐GitLab Maven 仓库?

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了如何使用极狐GitLa…

TPAMI:计算机学会像人脑一样“听话”了!清华团队实现混合语音分离技术突破

我们的大脑在处理声音信息时有一个特长&#xff1a;可以将注意力集中在感兴趣的对话或声音上&#xff0c;忽略其它无关的声音或者噪音。我们每天都在不知不觉地运用这种特长&#xff0c;在通勤的地铁上、嘈杂的餐厅里&#xff0c;广播声、音乐声、多人同时说话的声音&#xff0…

Redis中的持久化

持久化 .RDB手动触发save命令bgsave命令 自动触发bgsave的具体流程RDB的处理保存压缩校验 RDB的优缺点 AOF命令写入文件同步重写机制启动时恢复数据 本章重点回顾 . RDB RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发 手动触发…

【Java+Springboot】----- 通过Idea快速创建SpringBoot项目操作方法

一、第一步&#xff1a; 点击选择【File】->【New】-> 【Project】 最后弹出[new Project]界面。 二、第二步&#xff1a; 1. 选择【Spring Initializr】 2. 然后选择【Project SDK】的版本 3. 然后 Choose Initializr Service URL 选择默认&#xff08;Default&#x…

JAVA8 新特性StreamAPI使用(二)

一、使用StreamAPI&#xff0c;&#xff08;基于数据模型——客户、订单和商品&#xff0c;实体关系图如下&#xff0c;客户可以有多个订单&#xff0c;是一对多的关系&#xff0c;而产品和订单的关系是多对多的&#xff09;需求如下&#xff1a; 二、Stream API思维导图 三、需…

【Java EE】SpringBoot的创建与简单使用

文章目录 &#x1f340;环境准备&#x1f333;Maven&#x1f332;SpringBoot是什么&#x1f384;Spring Boot 项目创建&#x1f338;使用Idea创建&#x1f338;创建SpringBoot项⽬&#x1f338;SpringBoot项目的运行 ⭕总结 &#x1f340;环境准备 如果你的IDEA是专业版&#…

六、从零实战企业级K8S本地部署ThingsBoard专业版集群

1、从 docker hub 拉取 ThingsBoard PE 映像(所有节点) 1.1、查看k8s信息(主节点) kubectl cluster-info #查看k8s集群信息 kubectl get node #查看节点信息 kubectl get pod -A #查看内部组件1.2、从 docker hub 拉取 ThingsBoard PE 映像(所有…

SYS-2722音频分析仪SYS2722

181/2461/8938产品概述&#xff1a; Audio Precision 2722 音频分析仪是 Audio Precision 屡获殊荣的 PC 控制音频分析仪的旗舰型号&#xff0c;长期以来一直是音频设备设计和测试的全球公认标准。功能齐全的 SYS-2722 提供了测试转换器技术最新进展所需的无与伦比的失真和噪声…

Linux云计算之网络基础9——园区网络架构项目

要求构建大型园区网络架构&#xff0c;方案如下&#xff1a; 园区A 园区c 公司B 要求&#xff1a; 1、A公司园区网络 一台汇聚层三层交换机&#xff0c;两台接入层二层交换机。 出口有一台路由器。 2、A园区有五台服务器。 分别为两台 WEB 服务器&#xff0c;…

专注项目管理的Mac工具 - Project Office Pro 最新版

Project Office Pro for Mac是一款功能强大的项目管理软件&#xff0c;旨在帮助用户更好地管理和跟踪项目进展&#xff0c;提高工作效率和质量。以下是该软件的主要功能介绍&#xff1a; 项目创建与编辑&#xff1a;用户可以根据自己的需求自定义项目计划&#xff0c;包括设置…

C#手术麻醉信息系统源码,技术框架:Vue,Ant-Design+百小僧开源框架

C#手术麻醉信息系统源码&#xff0c;技术框架&#xff1a;Vue&#xff0c;Ant-Design百小僧开源框架 手术麻醉系统主要用于在手术过程中监测和控制患者的状态&#xff0c;确保手术的顺利进行并保障患者的生命安全。该系统通过一系列先进的医疗设备和技术&#xff0c;为手术患者…

玩机进阶教程-----高通9008线刷XML脚本修改备份 檫除的操作步骤解析

在高通9008官方固件中我们可以看到刷写需要的脚本rawprogram0.xml和辅助脚本patch0.xml&#xff0c;脚本的作用在于将固件内各个分区对应写入手机内。根据分区地址段。然后判断脚本中那些分区不写入。以下步骤将分析emmc字库为例来讲解如何将默认刷入脚本修改为备份 檫除脚本。…

C++——栈和队列容器

前言&#xff1a;这篇文章我们将栈和队列两个容器放在一起进行分享&#xff0c;因为这两个要分享的知识较少&#xff0c;而且两者在结构上有很多相似之处&#xff0c;比如栈只能在栈顶操作&#xff0c;队列只能在队头和队尾操作。 不同于前边所分享的三种容器&#xff0c;这篇…

搭建电商购物独立站抓取主流电商产品数据的方法:工具+电商数据采集API接口

分享一个抓取数据产品的方法&#xff0c;也是别人给我说的。 想做一个联盟产品相关的网站&#xff0c;然后需要采集电商网站的产品。咨询大佬告诉我&#xff0c;大量级电商商品数据的采集可以接入专业的电商数据采集API接口&#xff0c;也可以用webscrsper&#xff0c;于是乎就…

bootstrap+thymeleaf 页面多选回显时莫名其妙多了

bootstrapthymeleaf 页面多选回显时莫名其妙多了 问题现象问题分析问题处理总结 问题现象 今天遇到的问题的描述正如标题中的一样&#xff0c;就是后台管理系统在配置完内容后点击保存&#xff0c;回显时发现页面竟然莫名其妙多了一些数据。项目整体后台管理系统采用的是boots…