C++【STL】之list的使用

news2024/11/16 21:36:45

文章目录:

  • list介绍
  • list使用
    • 1. 默认成员函数
      • 1.1 构造函数
      • 1.2 拷贝构造
      • 1.3 赋值重载
      • 1.4 析构函数
    • 2. 迭代器
    • 3. 容量操作
    • 4. 数据访问
    • 5. 数据修改
      • 5.1 插入删除
      • 5.2 交换调整清理
    • 6. 其他操作
      • 6.1 链表拼接
      • 6.2 链表移除
      • 6.3 排序
      • 6.4 链表逆置

list介绍

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。

  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。

  3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。

  4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。

  5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

list使用

本文介绍的是list的部分常用接口,大佬们想了解更多关于list类的细节,一定要请前往官方文档(点击跳转)查阅学习

1. 默认成员函数

1.1 构造函数

list支持三种构造方式:

  • 默认构造:构造一个list对象,此时只有一个哨兵位节点
  • 带参构造:构造一个list对象,初始化对象有nval值的节点
  • 迭代器区间构造:根据传入的迭代器区间,构造出目标区间值的list对象
int main()
{
	vector<int> arr = { 1,2,3,4,5,6 };
	list<int> l1; //默认构造
	list<int> l2(8, 1); //带参构造,8个val值为1的节点
	list<int> l3(arr.begin(), arr.end()); //迭代器区间构造
	return 0;
}

1.2 拷贝构造

拷贝已有的list对象来构造出一个新的相同值对象

int main()
{
	list<int> l1(3, 6);
	list<int> l2(l1);

	cout << "l1: ";
	for (auto e : l1) cout << e << " ";
	cout << endl;

	cout << "l2: ";
	for (auto e : l2) cout << e << " ";
	return 0;
}

1.3 赋值重载

将原有list对象的值赋值给另一个已存在的对象

int main()
{
	const char* ps = "happy new year";
	list<char> l1(ps, ps + strlen(ps)); //源对象
	list<char> l2; //目标对象
	l2 = l1;
	for (auto e : l2) cout << e;
	return 0;
}

注意: 即使目标对象比源对象小,也能进行赋值

1.4 析构函数

析构函数会在对象生命周期结束时自动调用,进行内存释放,调用后哨兵位也将被释放

2. 迭代器

由于list的空间不是连续的,所以它的迭代器是不同于stringvector的随机迭代器的,list类中使用的是双向迭代器,只能做单纯的双向移动

list中的迭代器

  • 正向迭代器iterator
  • 反向迭代器reveser_iterator
  • const版本正反迭代器
int main()
{
	string str = "hello world";
	list<char> l1(str.begin(), str.end()); //迭代器区间构造
	//正向遍历
	list<char>::iterator it = l1.begin();
	while (it != l1.end())
	{
		cout << *it;
		it++;
	}
	cout << endl;
	//反向遍历
	list<char>::reverse_iterator rit = l1.rbegin();
	while (rit != l1.rend())
	{
		cout << *rit;
		rit++;
	}
	return 0;
}

因为list 的空间不是连续的,所以不支持下标的随机访问,对 list 对象进行遍历时,只能使用迭代器

3. 容量操作

empty()接口:判空

size()接口:查看大小

max_size()接口:检查大小调整时的合法性

int main()
{
	list<int> l1(88, 6);
	cout << l1.size() << endl; 
	cout << l1.empty() << endl;
	cout << l1.max_size() << endl;
	return 0;
}

4. 数据访问

front()接口:访问哨兵位的下一个节点

back()接口:访问链尾数据

int main()
{
	vector<int> v = { 4,1,2 };
	list<int> l1(v.begin(), v.end()); //迭代器区间构造
	cout << "front: " << l1.front() << endl;
	cout << "back: " << l1.back() << endl;
	return 0;
}

5. 数据修改

5.1 插入删除

assign()接口:赋值

push_front()接口:头插

pop_front()接口:头删

push_back()接口:尾插

pop_back()接口:尾删

int main()
{
	vector<int> vs = { 4,1,2 };
	list<int> l1(vs.begin(), vs.end());
	for (auto e : l1) cout << e << " "; //4 1 2
	cout << endl;

	l1.assign(3, 6); //赋值为3个6
	for (auto e : l1) cout << e << " "; //6 6 6
	cout << endl;

	l1.push_front(12); //头插12
	for (auto e : l1) cout << e << " "; //12 6 6 6
	cout << endl;

	l1.pop_front(); //头删
	for (auto e : l1) cout << e << " "; //6 6 6
	cout << endl;

	l1.push_back(24); //尾插24
	for (auto e : l1) cout << e << " "; //6 6 6 24
	cout << endl;

	l1.pop_back(); //尾删
	for (auto e : l1) cout << e << " "; //6 6 6 
	cout << endl;
	return 0;
}

list对于首尾数据的操作效率很高

insert()接口:任意位置插入

erase()接口:任意位置删除

任意位置的操作需要配合迭代器和全局查找函数find()使用,一段数据中如果有相同值,find()会返回第一次找到的位置

int main()
{
	vector<int> vv = { 4,1,2 };
	list<int> l1(vv.begin(), vv.end());
	for (auto e : l1) cout << e << " "; //4 1 2
	cout << endl;

	auto poss = find(l1.begin(), l1.end(), 2);
	l1.insert(poss, 6); //指定位置插入6
	for (auto e : l1) cout << e << " "; //4 1 6 2
	cout << endl;

	l1.insert(poss, 3, 8); //指定位置插入3个8
	for (auto e : l1) cout << e << " "; //4 1 6 8 8 8 2
	cout << endl;

	l1.insert(poss, vv.begin(), vv.end()); //指定位置插入一段数据
	for (auto e : l1) cout << e << " "; //4 1 6 8 8 8 4 1 2 2
	cout << endl;

	poss = find(l1.begin(), l1.end(), 1);
	l1.erase(poss); //删除指定位置的值
	for (auto e : l1) cout << e << " "; //4 6 8 8 8 4 1 2 2
	cout << endl;

	l1.erase(l1.begin(), l1.end()); //全删
	for (auto e : l1) cout << e << " ";
	return 0;
}

注意:

erase后会存在迭代器失效问题,需要及时更新迭代器位置!!!

5.2 交换调整清理

swap()接口:list对象交换

resize()接口:调整大小,若调整后的大小大于原大小,会尾插T()的值

clean()接口:清理

void Print(list<int>& l1, list<int>& l2)
{
	cout << "l1 size(): " << l1.size() << endl;
	for (auto e : l1) cout << e << " ";
	cout << endl;

	cout << "l2 size(): " << l2.size() << endl;
	for (auto e : l2) cout << e << " ";
	cout << endl;
	cout << "--------------------" << endl;
}

int main()
{
	vector<int> vc = { 4,1,2 };
	list<int> l1(vc.begin(), vc.end());
	list<int> l2(vc.rbegin(), vc.rend());
	Print(l1, l2);

	l1.swap(l2); //交换l13和l14
	Print(l1, l2);

	l1.resize(1); //调整大小为1
	l2.resize(12); //调整大小为12
	Print(l1, l2);

	l2.clear(); //清理l13
	Print(l2, l2);
	return 0;
}

6. 其他操作

list类中还有诸如拼接、移除、逆置等操作,特殊场景使用起来很方便

6.1 链表拼接

splice()接口:对原链表中指定区间进行拼接,拼接后,原位置处的节点(区间)不再有,已被拼接到其他地方

void Print(list<int>& l1, list<int>& l2)
{
	cout << "l1: ";
	for (auto e : l1) cout << e << " ";
	cout << endl;

	cout << "l2: ";
	for (auto e : l2) cout << e << " ";
	cout << endl;
	cout << "--------------------" << endl;
}

int main()
{
	vector<int> vx = { 1, 2, 3, 4, 5, 6 };
	list<int> l1(vx.begin(), vx.begin() + 3); //123
	list<int> l2(vx.begin() + 3, vx.end()); //456
	Print(l1, l2);

	l1.splice(l1.end(), l2);	//l2拼接到l1的结尾
	Print(l1, l2);

	l1.splice(l1.end(), l1, l1.begin()); //拼接到结尾
	Print(l1, l2);

	auto first = l1.begin();
	first++;	//指向第二个节点
	auto last = l1.end();	//指向最后一个节点
	l1.splice(l1.begin(), l1, first, last);	//拼接到开头
	Print(l1, l2);
	return 0;
}

6.2 链表移除

remove()接口:这个接口就是find() + erase()的封装版,使用起来非常方便

int main()
{
	vector<int> va = { 4,1,2 };
	list<int> l1(va.begin(), va.end());
	for (auto e : l1) cout << e << " ";
	cout << endl;

	l1.remove(2); //移除元素2
	for (auto e : l1) cout << e << " ";
	cout << endl;
	return 0;
}

6.3 排序

由于库中的排序std::sort使用的是快排,需要支持下标随机访问,所以list对象不能使用,list类自己也提供了排序算法,不过效率较低,还不如先将数据拷贝到vector中,排序完后再拷贝回来的效率高

下面一段代码就是测试两种排序方法的效率:

int main()
{
	srand((size_t)time(NULL)); //随机数
	int n = 10000000;
	vector<int> tmp;
	tmp.reserve(n);
	list<int> l1;
	list<int> l2;
	int val = 0;
	int i = 0;
	while (i < n)
	{
		//放入随机数
		val = rand() % 100 + 1;
		l1.push_back(val);
		l2.push_back(val);
		i++;
	}
	//使用list::sort 排序
	int begin1 = clock();
	l1.sort();
	int end1 = clock();
	
	int begin2 = clock();
	//先拷贝到vector中
	for (auto e : l2)
	{
		tmp.push_back(e);
	}
	//使用std::sort 排序(快排)
	std::sort(tmp.begin(), tmp.end());
	//再拷贝回去
	int pos = 0;
	for (auto& e : l2)
	{
		e = tmp[pos++];
	}
	int end2 = clock();
	cout << "list::sotr time is: " << end1 - begin1 << endl;
	cout << "std::sort time is: " << end2 - begin2 << endl;

	return 0;
}

6.4 链表逆置

reverse()接口:将list对象逆置

int main()
{
	string ss = "happy";
	list<char> l1(ss.begin(), ss.end());
	for (auto e : l1) cout << e;
	cout << endl;

	l1.reverse();
	for (auto e : l1) cout << e;
	cout << endl;
	return 0;
}


C++【STL】之list的使用,到这里就介绍结束了,本篇文章对你由帮助的话,期待大佬们的三连,你们的支持是我最大的动力!

文章有写的不足或是错误的地方,欢迎评论或私信指出,我会在第一时间改正!

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

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

相关文章

STM32软件定时器

目录 什么是定时器&#xff1f; 软件定时器优缺点 软件定时器原理 软件定时器相关配置 单次定时器和周期定时器 软件定时器相关 API 函数 1. 创建软件定时器 2. 开启软件定时器 3. 停止软件定时器 4. 复位软件定时器 5. 更改软件定时器定时时间 实操 cubeMX配置 …

chatgpt赋能python:Python设置画布背景颜色

Python设置画布背景颜色 Python语言是一种广泛应用于科学计算、数据处理和数据可视化的高级脚本语言。它之所以如此流行&#xff0c;主要是因为它简单易学&#xff0c;并且具有很强的灵活性。在Python中&#xff0c;我们可以使用各种库来创建图形化界面、游戏和数据可视化应用…

C高级 day35

1、ubuntu的网络配置 1、查看网络是否连接 ping baidu.com 2、保证虚拟机有桥接网络 虚拟机---->设置---->网络适配器------>选择桥接或者是Vmnet0 给虚拟机添加桥接网络&#xff0c;如果没有vmnet0&#xff0c;添加网络 3、配置虚拟机的桥接网络 右上角网络图标-----…

RunCat 自定义动图

下载资源 下载资源 Runners Store 在商店购买 Self-Made Runner 设置 添加多张图片 下载 zhiyin_basketball 图片 zhiyin_basketball 下载 更新版本 设置图片 Format: PNGHeight: 36pxWidth: 10~100px 调整图片大小 使用convert命令查看图片宽和高 convert 0.png -print …

MFC视类和框架类学习1

VC6新建一个单文档工程&#xff0c;名称为test&#xff1b;将会生成如下的类&#xff1b; 这里说的框架类是指CMainFrm类&#xff1b; 视类是指CxxxxView类&#xff1b; 生成的视类公共继承自CView类&#xff0c; class CTestView : public CView { ...... CView类继承自CWnd…

安装ps出现计算机丢失d3dcompiler_47.dll缺失的解决方法

本教程操作系统&#xff1a;Windows系统、 d3dcompiler_47.dll是电脑文件中的dll文件&#xff08;动态链接库文件&#xff09;。如果计算机中丢失了某个dll文件&#xff0c;可能会导致某些软件和游戏等程序无法正常启动运行&#xff0c;并且导致电脑系统弹窗报错。 在我们打开…

局域网视频会议系统相较于SaaS会议系统的优势

局域网视频会议系统和SaaS会议系统都是远程协作和视频通讯的应用技术&#xff0c;各自有各自的特点和功能。 局域网视频会议系统相较于SaaS会议系统可以具备以下一些优势&#xff1a; 1. 安全性更高&#xff1a;局域网视频会议系统在企业内部进入&#xff0c;采用专属的内外网安…

Win10电脑C盘爆红了可以删除哪些文件?

Win10电脑C盘爆红了可以删除哪些文件&#xff1f;Win10电脑中用户发现C盘爆红了&#xff0c;想通过删除C盘内的文件来解决C盘爆红的问题&#xff0c;那么哪些文件可以删除呢&#xff0c;用户可以打开Temp、Help、Prefectch等文件夹进行删除&#xff0c;以下就是Win10电脑C盘爆红…

Python入门基本练习题(54题)

Python入门基本练习题&#xff08;54题&#xff09; 目录 第一节 、Python基础关键字和语法 1、 用单引号括出需要打印输出的内容 2、 用双引号括出需要打印输出的内容 3、 用三引号括出需要打印输出的内容 4、 \n&#xff08;换行符&#xff09;的使用 5、 \t&#xff0…

chatgpt赋能python:Python词云入门:构建你自己的词云图

Python词云入门&#xff1a;构建你自己的词云图 如果你是一个数据科学家或者是数据分析师&#xff0c;那么你肯定已经听过了“词云图”这个词。词云图是数据可视化的一种方式&#xff0c;用于呈现文本数据中最频繁出现的词汇。在这篇文章中&#xff0c;我将提供一个详细的教程…

前端怎么使用node-input-validator给接口添加参数校验(以strapi 4.9为例)

node-input-validator是什么&#xff1f; 简称NIV (Node Input Validator)用于node.js的验证库使用它可以扩展库以添加自定义规则。npm NIV文档 使用方法 我们以strapi 4.9 版本项目为例&#xff0c;来试用一下它对我们接口的校验规则 下载依赖 npm i node-input-validat…

【人工智能】人工智能和双曲几何

一、说明 作为人工智能技术的理论支撑&#xff0c;几何学是必不可少的&#xff1b;目前直接的几何技术有&#xff1a;计算几何--对集合体如点云处理有用&#xff1b;射影几何--对3d重构有用&#xff1b;双曲几何--在自然语言的词嵌入做基础数学模型&#xff0c;另外深度学习国外…

Intellij IDEA编写Spark应用程序的环境配置和操作步骤

本文介绍如何在win系统中使用IDEA开发spark应用程序&#xff0c;并将其打成jar包上传到虚拟机中的三个Ubuntu系统&#xff0c;然后在分布式环境中运行。 主要步骤包括&#xff1a; 安装Scala插件&#xff1a;在Intellij IDEA中安装Scala插件&#xff0c;并重启IDEA。创建Mave…

航空保障装备虚拟3d展览展示仿真系统助力企业降本增效

航空装备被认为是一个现代化国家核心竞争力的集中体现。航空装备制造业不仅是维护发展环境稳定的重要保障&#xff0c;也是推动经济转型升级的战略性产业。 3D虚拟展示技术是数字化转型中一项不可或缺的技术手段&#xff0c;将3D虚拟现实技术与工业制造业的有机融合&#xff0c…

chatgpt赋能python:Python第三方包安装方法详解

Python第三方包安装方法详解 为什么要安装第三方包&#xff1f; 在Python编程中&#xff0c;常常需要使用到一些额外的功能模块&#xff0c;但是Python自身不具备这些功能&#xff0c;需要通过安装第三方包来实现。例如&#xff0c;Python标准库中没有Jupyter Notebook工具&a…

T5、RoBERTa、悟道·天鹰、紫东太初、CPM作者谈基础模型前沿技术丨大模型科研、创业避坑指南...

导读 大语言模型日益火爆&#xff0c;学者们的研究方向是指明灯。那么相关大模型重要项目的主要贡献者怎么看&#xff1f;6月9日的北京智源大会“基础模型前沿技术”论坛邀请了T5、RoBERTa、悟道天鹰、紫东太初、CPM等重要模型工作作者出席。 图注&#xff1a;五位嘉宾现场讨论…

chatgpt赋能python:Python如何设置画布颜色:一份详尽指南

Python如何设置画布颜色&#xff1a;一份详尽指南 在计算机图形学中&#xff0c;画布颜色是指画布的背景颜色。当然&#xff0c;通过Python设置画布颜色非常简单&#xff0c;本篇文章将为您提供一份详尽指南。 什么是画布颜色&#xff1f; 在Python中创建一个画布时&#xf…

MySQL 官方示例数据库如何下载

文章结构 下载 MySQL 的示例数据库示例数据库介绍以及安装后续就是自己使用了参考网址 MySQL 提供了一些非常好的用来演示 MySQL 各项功能的示例数据库&#xff0c;同 Oracle 也提供了示例数据库。但是很少有人知道 MySQL 也提供&#xff0c;或许是因为它没有像 Oracle 一样在安…

chatgpt赋能python:Python教程:如何设置画布大小?

Python教程&#xff1a;如何设置画布大小&#xff1f; 在Python中&#xff0c;我们可以使用各种图形库来创建各种类型的图。有时&#xff0c;我们需要调整图像的大小以适应我们的需求。所以&#xff0c;在这篇文章中&#xff0c;我将介绍如何使用Python来设置画布大小。 什么…

cocos creator 帧同步游戏示例

最近闲来无事重新研究一下同步策略里面的帧同步&#xff0c;首先说下帧同步与状态同步的区别&#xff0c; 1&#xff1a;帧同步&#xff1a; 帧同步是一种多人游戏中常用的网络同步技术&#xff0c;用于确保不同玩家之间的游戏状态保持一致。在帧同步中&#xff0c;所有玩家通…