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.mzph.cn/news/795693.shtml

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

相关文章

钉钉事件订阅前缀树算法gin框架解析

当钉钉监测到发生一些事件&#xff0c;如下图 此处举例三个事件user_add_org、user_change_org、user_leave_org&#xff0c;传统的做法是&#xff0c;我们写三个if条件&#xff0c;类似下图 这样字符串匹配效率比较低&#xff0c;于是联想到gin框架中的路由匹配算法&#xff0…

jangow-01-1.0.1 靶机渗透

信息收集部分&#xff1a; 1.nmap存活探测&#xff1a; 2.nmap端口探测&#xff1a; 3.nmap服务探测&#xff1a; 这里应该是21和80端口&#xff0c;&#xff0c;但21需要登陆访问&#xff0c;用不了&#xff0c;问题不大。 web&#xff1a; 页面&#xff1a; 发现RCE: 1.we…

docker容器环境安装记录(MAC M1)(完善中)

0、背景 在MAC M1中搭建商城项目环境时&#xff0c;采用docker统一管理开发工具&#xff0c;期间碰到了许多环境安装问题&#xff0c;做个总结。 1、安装redis 在宿主机新建redis.conf文件运行创建容器命令&#xff0c;进行容器创建、端口映射、文件挂载、以指定配置文件启动…

【SCI绘图】【曲线图系列1 python】绘制扫描点平滑曲线图

SCI&#xff0c;CCF&#xff0c;EI及核心期刊绘图宝典&#xff0c;爆款持续更新&#xff0c;助力科研&#xff01; 本期分享&#xff1a; 【SCI绘图】【曲线图1 python】绘制扫描点平滑曲线图 1.环境准备 python 3 import numpy as np import pandas as pd import proplot …

win10上一个详细的Django开发入门例子

1.Django概述 Django是一个开放源代码的Web应用框架&#xff0c;由Python写成。采用了MTV的框架模式&#xff0c;即模型M&#xff0c;视图V和模版T。 Django 框架的核心组件有&#xff1a; 用于创建模型的对象关系映射&#xff1b; 为最终用户设计较好的管理界面&#xff1b…

使用Arcpy进行数据批处理-批量裁剪

时空大数据使我们面临前所未有的机遇和挑战&#xff0c;尤其在地学、遥感或空间技术等专业领域&#xff0c;无疑是一个全新的时代。 伴随着时空大数据的到来&#xff0c;海量数据的处理是一个所有科研工作者都无法忽视的重要问题。传统的数据&#xff08;主要指空间数据&#x…

Docker实战教程 第1章 Linux快速入门

2-1 Linux介绍 为什么要学Linux 三个不得不学习 课程需要&#xff1a;Docker开发最好在Linux环境下。 开发需要&#xff1a;作为一个后端程序员&#xff0c;是必须要掌握Linux的&#xff0c;这是找工作的基础门槛。 运维需要&#xff1a;在服务器端&#xff0c;主流的大型服…

SDWebImage源码解析---疑难问题解答

SDWebImage的简单流程图&#xff1a; 上图大致流程是对的&#xff0c;有几个没写到的地方&#xff1a; 首先判断url的类型是不是URL类型或string类型&#xff0c;判断url是否为nil占位图更早一些&#xff0c;在url判断后&#xff0c;就行显示占位图加载沙盒中对应的图片后&…

Premiere Pro 2024:赋予创意翅膀,让你的视频飞翔 mac/win版

Premiere Pro 2024&#xff0c;作为Adobe旗下的旗舰视频编辑软件&#xff0c;自推出以来&#xff0c;一直在视频制作领域占据着重要的地位。随着技术的不断进步和创新&#xff0c;Premiere Pro 2024为用户带来了前所未有的编辑体验&#xff0c;重新定义了视频制作的标准。 Pre…

数字逻辑分析仪初体验

为啥会用到这玩意儿&#xff0c;要从一个荒诞的需求开始。想在市面上找一款特别低空飞行的监控&#xff0c;而且不想它一直开着监控&#xff0c;最好是我在外面远程指挥它起飞&#xff0c;飞去厨房&#xff0c;飞去洗手间&#xff0c;甚至飞去阳台&#xff0c;查看水龙头情况啊…

Nuxt 项目的创建

中文文档&#xff1a;https://nuxt.com.cn/docs/getting-started/installation#%E6%96%B0%E9%A1%B9%E7%9B%AE Nuxt 项目创建的先决条件&#xff1a; Node.js 版本 18.0.0 及以上文本编辑器&#xff1a;VS Code Volar 插件 或 Webstorm 执行如下命令&#xff0c;创建 Nuxt 项目…

【Canvas技法】用椭圆绘制经纬线

【图示】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>用椭圆绘制经纬线</title><style type"text/css"…

相对论中关于光速不变理解的补充

近几个月在物理直播间聊爱因斯坦相对论&#xff0c;发现好多人在理解爱因斯坦相对论关于基本假设&#xff0c;普遍认为光速是不变的&#xff0c;质能方程 中光速的光速不变的&#xff0c;在这里我对这个假设需要做一个补充&#xff0c;他是基于质能方程将光速C 在真是光速变化曲…

Allavsoft for Mac v3.27.0.8852注册激活版 优秀的视频下载工具

Allavsoft for Mac是一款功能强大的多媒体下载和转换工具&#xff0c;支持从各种在线视频网站和流媒体服务下载视频、音频和图片。它具备批量下载和转换功能&#xff0c;可将文件转换为多种格式&#xff0c;以适应不同设备的播放需求。此外&#xff0c;Allavsoft还提供视频编辑…

最新版两款不同版SEO超级外链工具PHP源码

可根据个人感觉喜好自行任意选择不同版本使用&#xff08;版V1或版V2&#xff09; 请将zip文件全部解压缩即可访问&#xff01; 源码全部开源&#xff0c;支持上传二级目录访问 #已更新增加大量高质量外链&#xff08;若需要增加修改其他外链请打开txt文件&#xff09; #修…

贪心算法|53.最大子序和

力扣题目链接 class Solution { public:int maxSubArray(vector<int>& nums) {int result INT32_MIN;int count 0;for (int i 0; i < nums.size(); i) {count nums[i];if (count > result) {result count;}if (count < 0) count 0;}return result;} …

SpringBoot+ECharts+Html 字符云/词云案例详解

1. 技术点 SpringBoot、MyBatis、thymeleaf、MySQL、ECharts 等 2. 准备条件 在mysql中创建数据库echartsdb&#xff0c;数据库中创建表t_comment表&#xff0c;表中设置两个字段word与count&#xff0c;添加表中的数据。如&#xff1a;附件中的 echartsdb.sql 3. SpringBoot…

CAD Plant3D 2024 下载地址及安装教程

CAD Plant3D是一款专业的三维工厂设计软件&#xff0c;用于在工业设备和管道设计领域进行建模和绘图。它是Autodesk公司旗下的AutoCAD系列产品之一&#xff0c;专门针对工艺、石油、化工、电力等行业的设计和工程项目。 CAD Plant3D提供了一套丰富的工具和功能&#xff0c;帮助…

水泥5G智能制造工厂数字孪生可视化平台,推进水泥行业数字化转型

水泥5G智能制造工厂数字孪生可视化平台&#xff0c;推进水泥行业数字化转型。水泥5G智能制造工厂数字孪生可视化平台&#xff0c;是水泥行业数字化转型的关键推手。数字孪生平台运用先进的信息技术和数字化手段&#xff0c;实现水泥生产过程的数字化模拟、可视化监控和智能化管…

常见的线程安全类

线程安全&#xff01;线程安全&#xff01;&#xff01;线程安全&#xff01;&#xff01;&#xff01; 鼠鼠我最近被线程安全这个词弄得好烦啊&#xff0c;那既然如此就来写一篇常见的线程安全类防止以后鼠鼠我的大脑又宕机了忘记了....... 这里我们讨论的线程安全的是指&am…