C++【STL】之list的使用

文章目录:

  • 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的使用,到这里就介绍结束了,本篇文章对你由帮助的话,期待大佬们的三连,你们的支持是我最大的动力!

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java 版本企业电子招投标采购系统源码之登录页面

​ 信息数智化招采系统 服务框架&#xff1a;Spring Cloud、Spring Boot2、Mybatis、OAuth2、Security 前端架构&#xff1a;VUE、Uniapp、Layui、Bootstrap、H5、CSS3 涉及技术&#xff1a;Eureka、Config、Zuul、OAuth2、Security、OSS、Turbine、Zipkin、Feign、Monitor、…

轻量服务器架设网站打开速度慢,如何加速?

轻量服务器非常适合流量适中的小、中型网站&#xff0c;虽作为轻量级主机包&#xff0c;但它一般与云服务器使用同样的 CPU、内存、硬盘等底层资源。只是&#xff0c;轻量服务器的资源(可用的存储空间、RAM 和 CPU等硬件/内存容量)更低&#xff0c;虽然这些对于较中、小的网站来…

性能优化-内存优化

8-《内存优化》 一.基础知识1.Java的内存分配区域2.Java的引用类型3.Java的垃圾回收机制&#xff1a;三个问题4.Android的内存管理机制 二. Android的内存泄漏、内存溢出、内存抖动概念0.内存泄露1.内存溢出![在这里插入图片描述](https://img-blog.csdnimg.cn/8b73ef844f26470…

png转jpg,直接改后缀?

通过把.png改为.jpg可以改变图片的格式么&#xff1f; 将PNG文件扩展名改为JPEG的扩展名&#xff08;.jpg或.jpeg&#xff09;不会更改图像的格式。它只是更改了文件扩展名&#xff0c;这可能导致一些图像查看器和编辑器无法正确识别和处理该文件。 PNG和JPEG是两种不同的图像文…

Python自动人工智能训练数据增强工具 | DALI介绍(含代码)

Python自动人工智能训练数据增强工具 | DALI介绍(含代码) 文章目录 Python自动人工智能训练数据增强工具 | DALI介绍(含代码)自动数据增强方法DALI 和条件执行使用 DALI 自动增强使用 DALI 的自动增强性能尝试使用 DALI 进行自动增强 深度学习模型需要数百 GB 的数据才能很好地…

练习:逻辑回归

练习2&#xff1a;逻辑回归 介绍 在本练习中&#xff0c;您将实现逻辑回归并将其应用于两个不同的数据集。还将通过将正则化加入训练算法&#xff0c;来提高算法的鲁棒性&#xff0c;并用更复杂的情形来测试模型算法。 在开始练习前&#xff0c;需要下载如下的文件进行数据上…

研一,有点迷茫。

作者&#xff1a;阿秀 校招八股文学习网站&#xff1a;https://interviewguide.cn 这是阿秀的第「277」篇原创 小伙伴们大家好&#xff0c;我是阿秀。 最近回答了不少大一大二研一在读的学习圈中学弟学妹的咨询问题&#xff0c;基本都是计算机学习、进度、疑惑等等相关的问题&a…

Mock和Vite-plugin-Mock的区别是什么?

简介 我不知道大家和我是否有一样的疑问&#xff0c;之前Mock.js用的挺好&#xff0c;为啥又出现了一个vite-plugin-mock,而且这个插件还依赖于Mock.js.那么他的优势到底是什么呢&#xff1f;如果你也有这样的疑问&#xff0c;本文最后会给出答案解开这个谜底 前言 我之前已经…

MVC、MVP、MVVM:详解2

概述 MVC、MVP、MVVM 都是在 Android 开发中经常用到的架构思想&#xff0c;它们都是为了更好地分离代码、提高代码可复用性、方便维护等目的而设计的。下面对这三种架构思想进行简单的介绍和比较。 MVC MVC 架构是最早被使用的一种架构&#xff0c;它把程序分成了三个部分&…

EasyExcel实现execl导入导出

引言 在实际开发中&#xff0c;处理 Excel 文件是一个常见的需求。EasyExcel 是一个基于 Java 的开源库&#xff0c;提供了简单易用的 API&#xff0c;可以方便地读取和写入 Excel 文件。本文将介绍如何使用 EasyExcel 实现 Excel 导入功能&#xff0c;以及一些相关的技巧和注…

【问题记录】Visual Studio 下的Qt工程无法打开 “xxx.ui“ 文件和LNK1104 无法打开文件“Qt5Cored.lib”错误

环境 Windows 11 家庭中文版Microsoft Visual Studio Community 2022 (64 位) - Current 版本 17.5.3qt-vsaddin-msvc2022-2.9.1-rev.06 问题产生 VS下Qt环境准备好后&#xff0c;创建了Qt工程然后点击 Form Files 下的 “xxx.ui” 文件&#xff0c;在弹出 Qt 设计师 界面后…

电脑出现MSVCP100.dll丢失错误怎么办?

MSVCP100.dll是一个Windows系统文件&#xff0c;它可以确保Windows程序正确平稳运行&#xff0c;如果该文件安装不正确、丢失或损坏&#xff0c;则使用该文件的应用程序将无法正常启动&#xff0c;会出现“无法启动此程序&#xff0c;因为计算机中丢失MSVCP100.dll”的错误提示…

从零开始 Spring Boot 42:异步执行

从零开始 Spring Boot 42&#xff1a;异步执行 图源&#xff1a;简书 (jianshu.com) 在之前的文章中&#xff0c;我多次介绍过在 Spring 中如何使用Async注解让方法调用变成“异步执行”&#xff1a; 在这篇文章中&#xff0c;介绍了如何让定时任务使用Async变成异步执行。在…

数据结构——图

文章目录 **一 图的基本概念****1 定义** **二 图的存储及基本操作****1 邻接矩阵法****2 邻接表法****3 十字链表****4 邻接多重表****5 图的基本操作** **三 图的遍历****1 广度优先搜索BFS****2 深度优先搜索DFS****3 图的遍历与连通性** **四 图的应用****1 最小生成树****…

Kendo UI for jQuery---03.组件___网格---02.开始

网格入门 本指南演示了如何启动和运行 Kendo UI for jQuery Grid。 完成本指南后&#xff0c;您将能够实现以下最终结果&#xff1a; 1. 创建一个空的 div 元素 首先&#xff0c;在页面上创建一个空元素&#xff0c;该元素将用作 Grid 组件的主容器。 <div id"my-…

Chat2DB:阿里巴巴开源的聊天数据管理工具--实践

Chat2DB&#xff1a;阿里巴巴开源的聊天数据管理工具–实践 简介 ​ Chat2DB 是一款有开源免费的多数据库客户端工具&#xff0c;支持windows、mac本地安装&#xff0c;也支持服务器端部署&#xff0c;web网页访问。和传统的数据库客户端软件Navicat、DBeaver 相比Chat2DB集成了…

Android音视频开发实战01-环境搭建

一,FFmpeg介绍 FFmpeg 是一款流行的开源多媒体处理工具&#xff0c;它可以用于转换、编辑、录制和流式传输音视频文件。FFmpeg 具有广泛的应用场景&#xff0c;包括视频编解码、格式转换、裁剪、合并、滤镜等等。官网:https://ffmpeg.org/ FFmpeg 支持各种常见的音视频格式&a…

计算机视觉-目标检测(二):从R-FCN到YOLO-v3

文章目录 1. R-FCN1.1 动机1.2. R-FCN 网络结构1.3. R-FCN 的损失函数1.4. R-FCN的训练及性能 2. YoLO-v12.1 简介2.2 YOLO-v1网络结构2.3 目标函数2.4 YOLO-v1的优缺点 3. YOLO-v23.1 YOLO-v2相比v1的优化 4. YOLO-v3参考 1. R-FCN 论文链接&#xff1a;R-FCN:Object Detecti…

在提交代码时有哪些注意事项

分享 10 种适合初学者的技术&#xff0c;这些技术将帮助您立即编写更好的代码。因此&#xff0c;如果您准备好将您的编码技能提升到一个新的水平&#xff0c;请继续阅读&#xff01; 1. 从计划开始 编写更好代码的最佳方法之一是从计划开始。在开始编码之前&#xff0c;请花几…

Nginx+Tomcat负载均衡、动静分离

Nginx应用 Nginx是一款非常优秀的HTTP服务器软件 支持高达50000个并发连接数的响应拥有强大的静态资源处理能力运行稳定内存、CPU等系统资源消耗非常低 目前很多大型网站都应用Nginx服务器作为后端网站程序的反向代理及负载均衡器&#xff0c;提升整个站点的负载并发能力 反向…