list的使用

news2025/1/17 0:58:17

前言

我们前面已经对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位置插入一个val

lt.insert(++lt.begin(), 5, -1);//在pos位置插入n个val

vector<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();
	// vector

	vector<int> v(lt2.begin(), lt2.end());
	// 
	sort(v.begin(), v.end());

	// lt2
	lt2.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.coloradmin.cn/o/1572481.html

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

相关文章

Flutter学习12 - SharedPreferences

1、shared_preferences 插件 类似于 Android 中的 SharedPreferences&#xff0c;键值对的形式进行本地存储 1.1、引入插件 在 pubspec.yaml 中引入 dependencies:shared_preferences: ^2.1.0在需要用到的文件中引入 import package:shared_preferences/shared_preference…

TAB标签美化 - SVG作为mask

今天觉得V3的标签不是很好看&#xff0c;忽然想起来之前看过Vue Admin Beautiful Pro的样式挺好的&#xff0c;顺手研究了一把。发现Vue Admin Beautiful是采用PNGmask css来解决的。于是乎打算把V3的标签页做点小美化&#xff0c;但是迁移过程发生些小插曲&#xff0c;在此记录…

蓝桥杯嵌入式(G431)备赛笔记——按键模块设计

cubeMX配置: 原理图 引脚配置为上拉模式 定时器 使用定时器3(通用定时器,使用外部晶振,内部时钟),分频系数为80(从0开始则为80-1),则每1s 1m次,定时评率为为10000,对应1s 1m/10000次,频率为10ms每次 一定记得开启NVIC使能中断 编写中断回调函数 void HAL_TIM_Per…

windows程序设计课程作业-1

目录 1、作业内容 2、主要思路 (1)写接口 (2)写类具体实现接口 (3)声明委托 (4)创建实例 (5)实例化委托 3、难点分析 1&#xff09;想明白接口的作用 2&#xff09;委托的作用 4、实现代码 5、运行结果 1、作业内容 使用 C# 编码&#xff08;涉及类、接口、委托等关…

Android Studio学习10——资源res的使用

一、String,StringArray的使用 一次修改&#xff0c;多出生效 String StringArray 二、color的使用 颜色代码对应表 和上面的相似用法 三、Dimen(尺寸)的使用 用的少&#xff0c;一般直接写尺寸 四、如何写一个drawable作为背景 五、如何写一个可以改变的drawable(按钮按下…

python爬虫———post请求方式(第十四天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

【Qt 学习笔记】如何在Qt中打印日志 | qDebug的使用 | Assistant的使用

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 如何在Qt中打印日志 | qDebug的使用 文章编号&#xff1a;Qt 学习笔记…

全文更新:什么是Power Path?充电时是充电器供电还是电池供电?

原文来自微信公众号&#xff1a;工程师看海&#xff0c;与我联系&#xff1a;chunhou0820 看海原创视频教程&#xff1a;《运放秘籍》 昨天的文章误删了一部分&#xff0c;很多同学留言想看全文&#xff0c;现补充、更新如下&#xff1a; 前段时间&#xff0c;交流群里有位同学…

【群智能算法改进】一种改进的鹦鹉优化算法 鹦鹉优化器 IPO算法【Matlab代码#73】

文章目录 【获取资源请见文章第5节&#xff1a;资源获取】1. 原始鹦鹉优化算法PO2. 改进后的IPO算法2.1 自适应切换因子2.2 混合柯西和高斯变异 3. 部分代码展示4. 仿真结果展示5. 资源获取 【获取资源请见文章第5节&#xff1a;资源获取】 1. 原始鹦鹉优化算法PO 鹦鹉优化算法…

由王雅贤带你深入《DBWGLX vs Ethan_Wang》

vs是versus。 &#xff08;百度收录我DBWG&#x1f64f;&#x1f64f;&#x1f64f;&#xff09; 算来篇自传吧。像自我介绍和简历我是完全没写过喵~ 2024年4月6日12:44:53書 本命王雅贤&#xff0c;DBWGLX我的微信号&#xff0c;至于什么意思&#xff0c;吊臂王锅的意思&am…

ARM FVP平台的terminal窗口大小如何设置

当启动ARM FVP平台时&#xff0c;terminal窗口太小怎么办&#xff1f;看起来非常累眼睛&#xff0c;本博客来解决这个问题。 首先看下ARM FVP平台对Host主机的需求&#xff1a; 通过上图可知&#xff0c;UART默认使用的是xterm。因此&#xff0c;我们需要修改xterm的默认字体设…

sql语句如何在MySQL中执行?

我们先来对MySQL的基础结构进行分析 一、 MySQL 基础架构分析 1.1 MySQL 基本架构概览 下图是 MySQL 的一个简要架构图&#xff0c;从下图你可以很清晰的看到用户的 SQL 语句在 MySQL 内部是如何执行的。 简单来说 MySQL 主要分为 Server 层和存储引擎层&#xff1a; Server…

性能分析--内存知识

内存相关知识 计算机中与CPU进行数据交换的桥梁。内存的速度&#xff0c;比CPU的速度要慢很多。比磁盘速度要快很多。内存中存放数据&#xff0c;一旦断电就会消失。linux系统的 /proc路径下的文件&#xff0c;都是内存文件。内存大小&#xff0c;一般 是GB为单位。 现在都操作…

【Pt】马灯贴图绘制过程 04-玻璃脏迹

目录 效果 步骤 一、透明玻璃 二、烟熏痕迹 三、粗糙 四、浮尘 效果 步骤 一、透明玻璃 1. 打开纹理集设置&#xff0c;着色器链接选择“新的着色器链接” 在着色器设置中可以看到此时名称为“Main shader &#xff08;Copy&#xff09;” 这里修改名称为“玻璃” 在…

【加密周报】比特币“强烈看涨”信号来了!巨鲸们正疯狂囤积稳定币!SEC呼吁公众对以太币ETF提供意见!

在过去一周里&#xff0c;比特币价格经历了一段下跌&#xff0c;并在随后出现了一些反弹迹象。与此同时&#xff0c;链上数据显示&#xff0c;巨鲸们在囤积稳定币&#xff0c;预示着“强烈的看涨情绪”。以太坊方面&#xff0c;美国证券交易委员会&#xff08;SEC&#xff09;已…

异常练习题

第一题&#xff1a;分析题 package chapter09_exception_teacher.src.com.atguigu05.exer.exer2;/*** 输出结果&#xff1a;* 进入方法A* 用A方法的finally* 制造异常* 进入方法B* 调用B方法的finally** author shkstart* create 0:57*/ public class ReturnExceptionDemo {sta…

【算法题】树节点的第 K 个祖先

题目&#xff1a; 给你一棵树&#xff0c;树上有 n 个节点&#xff0c;按从 0 到 n-1 编号。树以父节点数组的形式给出&#xff0c;其中 parent[i] 是节点 i 的父节点。树的根节点是编号为 0 的节点。 树节点的第 k 个祖先节点是从该节点到根节点路径上的第 k 个节点。 实现…

算法 ST表

思想&#xff08;本质为dp&#xff09;&#xff1a; 题目AcWing1270. 数列区间最大值&#xff1a; 1270. 数列区间最大值 - AcWing题库 输入一串数字&#xff0c;给你 M 个询问&#xff0c;每次询问就给你两个数字 X,Y要求你说出 X到 Y这段区间内的最大数。 输入格式 第一…

Java数据结构队列

队列(Queue) 概念 队列的使用 注意&#xff1a;Queue是个接口&#xff0c;在实例化时必须实例化LinkedList的对象&#xff0c;因为LinkedList实现了Queue接口。 import java.util.LinkedList; import java.util.Queue;public class Test {public static void main(String[]…

初识二叉树和二叉树的基本操作

目录 一、树 1.什么是树 2. 与树相关的概念 二、二叉树 1.什么是二叉树 2.二叉树特点 3.满二叉树与完全二叉树 4.二叉树性质 相关题目&#xff1a; 5.二叉树的存储 6.二叉树的遍历和基本操作 二叉树的遍历 二叉树的基本操作 一、树 1.什么是树 子树是不相交的;…