一文带你认识stl序列式容器--list(代码片段)

蚍蜉撼树谈何易 蚍蜉撼树谈何易     2022-12-07     734

关键词:

什么是list

list是序列式容器中的一种,底层是一个带头结点的双向循环链表。
在这里插入图片描述

list的使用

头文件#include
常用接口介绍

构造函数接口

构造方式作用
无参构造list<类型>name构建一个只含头结点的双向循环链表
list<类型>name(size_t n,type n)构建一个含有n个有效元素的带头结点的双向循环链表
list<类型>name(first,last)区间构造用区间[first,last)去初始化该链表
list<类型>name(list<类型>name&p)拷贝构造
list<类型>name数据C++11构造

测试用例:

void test_constructor()

	//1.无参构造
	list<int>vv1;
	//2.n个相同元素的构造
	list<int>vv2(5, 1);
	//3.区间构造
	int arr[] =  1,2,3,4,5 ;
	list<int>vv3(arr,arr+3);
	//4.拷贝构造
	list<int>vv4(vv3);


在这里插入图片描述

list相关迭代器使用

迭代器 类型相关函数
正向迭代器begin()/end()
反向迭代器rbegin()/rend()

测试用例:
通过迭代器实现元素访问:

void test_iterator()

	list<int>v1 1,2,3,4,5 ;
	auto it = v1.begin();
	while (it != v1.end())
	
		cout << *it << " ";
		++it;
	
	cout << endl;
	auto it1=v1.rbegin();
	while (it1!= v1.rend())
	
		cout << *it1 << " ";
		++it1;
	
	cout << endl;

在这里插入图片描述

容量相关的操作

需要获取的大小相关函数
链表判空操作empty()
有效元素的个数size()
调整有效元素个数resize(size_t n,T c=T());T为自定义类型或内置类型

测试用例:

void test_size()

	list<int>v1 1,2,3,4,5 ;
	if (v1.empty())
	
		cout << "v1 is empty" << endl;
	
	else
	
		cout << "v1 is not empty" << endl;
	
	cout << v1.size() << endl;
	v1.resize(10, 1);
	cout << v1.size();

在这里插入图片描述

测试链表的修改操作

相关函数作用
push_front(const T&x)/pop_front()头插与头删的操作
push_back(const T &x)/pop_back()尾插与尾删
iterator insert ( iterator position, const T& x ); 在某个位置插入一个元素,并返回该位置 void insert ( iterator position, size_type n, const T& x )//在某一位置前插入n个T类型的对象x;void insert ( iterator position, InputIterator first, InputIterator last );//在某一个位置前插入一段区间任意位置的插入
iterator erase ( iterator position )//删除某一位置的元素;iterator erase ( iterator first, iterator last );//删除一段区间的元素任意位置的删除,除了头结点
swap(list<类型>&name)交换两个链表
clear()清空链表,与销毁区分下,销毁会带着头结点一起删除,清空只是清空掉有效元素,保留头结点。
template<class T>
void Print(list<T>& P)

	auto it = P.begin();
	while (it != P.end())
	
		cout << *it << " ";
		it++;
	
	cout << endl;

void test_modoify()

	//push_back()/popback()
	list<int>vv1;
	vv1.push_back(1);
	vv1.push_back(2);
	vv1.push_back(3);
	vv1.push_back(4);
	Print(vv1);
	vv1.pop_back();
	Print(vv1);
	//push_front()与pop_front()
	vv1.push_front(5);
	Print(vv1);
	vv1.pop_front();
	Print(vv1);
	//测试insert()1.插入单个元素
	auto it=vv1.insert(find(vv1.begin(), vv1.end(), 2), 5);
	//插入多个元素
	vv1.insert(it, 5, 1);
	Print(vv1);
	int arr[] =  9,8,7,6 ;
	//插入一段区间
	vv1.insert(vv1.begin(), arr, arr + 3);
	Print(vv1);
	//测试erase 删除某一位置元素
	vv1.erase(vv1.begin());
	//删除一段区间
	vv1.erase(vv1.begin(), vv1.end());
	//验证swap
	list<int>vv2 1,2,3,4,5 ;
	vv1.swap(vv2);
	cout << vv1.size() << endl;
	cout << vv2.size() << endl;
	//验证clear
	vv1.clear();
	if (vv1.empty())
	
		cout << "vv1 is empty" << endl;
	
	else
	
		cout << "vv1 is not empty" << endl;
	

在这里插入图片描述

链表的一些其他操作

函数作用
remove(const T&t)删除某一元素
remove_if(函数名)根据传入值满足与否决定是否执行删除操作
sort()按照元素从小到大排序
unique()去重操作,去重建立在排序的基础上
merge()合并两个双向链表,建立在排序基础上
void test_operation()

	list<int>vv1 1,2,3,4,5,5,2,4,1,3 ;
	vv1.remove(2);
	cout << "删除2元素后" << endl;
	Print(vv1);
	vv1.unique();
	cout << "未排序去重后" << endl;
	Print(vv1);
	vv1.sort();
	vv1.unique();
	cout << "排序去重后" << endl;
	Print(vv1);
	//传递函数参数去除偶数操作
	vv1.remove_if(is_ood);
	cout << "去除偶数时" << endl;
	Print(vv1);
	list<int>vv2 3,1,5 ;
	list<int>vv3 2,8,6 ;
	//vv2.merge(vv3);
	//cout << "未排序合并" << endl;
	//Print(vv2);
	vv2.sort();
	vv3.sort();
	vv2.merge(vv3);
	cout << "排序合并" << endl;
	Print(vv2);

在这里插入图片描述

在这里插入图片描述

list中的赋值运算符

void test_operator()

	list<int>vv1(5, 0);
	list<int>vv2(3, 0);
	cout << "before the =" << endl;
	cout << "size of vv1 is " << vv1.size() << endl;
	cout << "size of vv2 is " << vv2.size() << endl;
	vv1 = vv2;
	cout << "after the =" << endl;
	cout << "size of vv1 is " << vv1.size() << endl;
	cout << "size of vv2 is " << vv2.size() << endl;

在这里插入图片描述

list中的迭代器失效问题

1.当删除迭代器位置上的元素时,迭代器失效
在这里插入图片描述
解决方法:

void test_iteratoruseless()

	list<int>vv1 1,2,3,4,5 ;
	auto it = vv1.begin();
	//1.删除所引起的迭代器失效
	while (it != vv1.end())
	
		//解决方式1.后置++解决。后置++指先拷贝it的一个副本,然后对it执行++操作,然后返回it的副本。
		//vv1.erase(it++);
		//解决方式2:利用返回值来解决
		it=vv1.erase(it);
		
	
	cout << vv1.size() << endl;

2.swap所引起的迭代器失效

//迭代器失效的第二种情况
void test_iteratoruseless1()

	list<int>vv1 1,2,3,4,5 ;
	auto it = vv1.begin();
	list<int>vv2 2,3,4,5 ;
	vv1.swap(vv2);
	while (it != vv1.end())
	
		cout << *it << " ";
		++it;
	
	cout << endl;

在这里插入图片描述
在这里插入图片描述

vector与list区别(重点)

1.在底层。vector底层是通过数组,也就是一块连续的空间实现的,list底层是一个带头结点的双向循环链表。
2.元素的随机访问。 vector支持元素的随机访问,时间复杂度为O(1),list不支持随机访问,访问某个元素的时间复杂度O(n);
3.插入与删除。 vector任意位置元素的插入与删除效率低,因为涉及到搬移元素,插入元素时可能还需要扩容,开辟新空间,拷贝元素,释放旧空间的操作,导致效率降低。而list任意位置的插入与删除效率高,不需要搬移元素,时间复杂度为O(1).
4.在空间利用率方面。vector底层是一段连续的空间,不容易造成内存碎片,空间利用率高,缓存利用率高。(就是将内存的数据放到寄存器里,因为底层是连续的,所以少去了寻找下一个值的开销).。list底层为动态开辟的,小节点容易造成内存碎片,空间利用率低,缓存利用率低。
5,迭代器。vector为原生态指针,list底层对原生态指针进行了封装。
6.迭代器失效。vector在插入元素时,需要给迭代器重新赋值来避免插入引起扩容操作导致迭代器失效的问题。在删除时,当前迭代器也会失效,也必须重新赋值,而list,插入元素不会导致迭代器的失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响。
使用场景说明:
list适用于大量的插入与删除操作,不关心随机访问的情况。而vector适用于高效的存储,支持随机访问,不关心插入、删除效率。

stl序列式容器之list

一,list容器基本概念1.list容器基本知识list容器的底部数据结构为双向链表,可以高效的进行插入和删除元素。list因为底层数据结构是双向链表,因此不支持下标操作和.at()函数的操作。要获取元素,必须从头到尾遍历。使用list... 查看详情

stl详解——setmapmultisetmultimap的介绍及使用(代码片段)

...历map的其他成员函数multimap关联式容器C++STL包含了序列式容器和关联式容器:序列式容器里面存储的是元素本身,其底层为线性序列的数据结构。比如:vector,list,deque,forward_list(C++11)等。关... 查看详情

❤️stl序列式容器vector超硬核源码剖析❤️(代码片段)

目录前言第4章序列式容器4.1容器的概念与分类4.1.1序列式容器4.2vector4.2.1vector概述4.2.2vector定义摘要4.2.3vector的迭代器4.2.4vector的数据结构4.2.5vector的构造与内存管理4.2.6vector的元素操作前言国庆七天假宛如一天假,定睛一看又... 查看详情

stl之序列式容器list与forward_list

 List(双向链表)与forwardlist(单向链表)算是非常基础的数据结构了,这里只是简单介绍下其结构及应用。 以list为例:        其节点模板:template<classT>struct_list_node{_list_node<T>*prev;_list 查看详情

map和set等关联式容器的使用(代码片段)

...list、deque、forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。那什么是关联式容器?它与序列式容器有什么区别?关联式容器也是用来存储数... 查看详情

一文带你快速掌握fastjson的使用(代码片段)

1.FastJson序列化API方法:JSON.toJSONString序列化:是指将Java对象转成json格式字符串的过程。JavaBean对象、List集合对象、Map集合为应用最广泛的。1.1序列化Java对象Java中的Student对象序列化为JSON格式字符串@TestpublicvoidobjectToJson()Studentstude... 查看详情

《stl源码剖析》——第四章序列容器(代码片段)

 1、容器的概观与分类    所谓序列式容器,其中的元素都可序(ordered)【比如可以使用sort进行排序】,但未必有序(sorted)。C++语言本身提供了一个序列式容器array,STL另外再提供vector,list,deque,stack,queue... 查看详情

一文带你认识springaop(代码片段)

SpringAOP简介AOP(Aspect-OrientedProgramming:面向切面编程)是对OOP(Object-OrientedProgramming:面向对象编程)的补充和完善。OOP引入封装、继承和多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。封装就要求将功能分散到... 查看详情

c++:stl中list的模拟实现(代码片段)

...点list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。list的底层是带头双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一... 查看详情

laocat带你认识容器与镜像(实践篇二下)(代码片段)

...践篇主要以各容器的挂载和附加命令为主。系列目录LaoCat带你认识容器与镜像(一)LaoCat带你认识容器与镜像(二【一章】)LaoCat带你认识容器与镜像(二【二章】)LaoCat带你认识容器与镜像(二【三... 查看详情

[c/c++]详解stl容器8-mapmultimapsetmultiset的介绍和使用(代码片段)

...,比如:vector、list、deque等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key... 查看详情

[c/c++]详解stl容器8-mapmultimapsetmultiset的介绍和使用(代码片段)

...,比如:vector、list、deque等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key... 查看详情

stl序列容器(代码片段)

...家最耳熟能详的可能就是容器,容器大致可以分为两类,序列型容器(SequenceContainer)和关联型容器(AssociativeContainer)这里介绍STL中的各种序列型容器和相关的容器适配器。主要内容包括std::vectorstd::arraystd::dequestd::queuestd::stackst... 查看详情

一文带你理解对象流序列化机制(代码片段)

目录对象流对象序列化机制对象流的使用字符串的序列化与反序列化自定义类的序列化与反序列化对象流ObjectInputStream和ObjectOutputStream:用于存储和读取基本数类型数据或对象的处理流。它的强大之处就是可以把Java中的对象... 查看详情

c++/stl0.容器概述

文章目录​​一、容器分类​​​​(1)序列性容器​​​​(2)关联式容器​​​​(3)容器适配器​​​​二、容器共性​​​​三、容器比较​​一、容器分类(1)序列性容器​​序列式容器​​:按线性排列来存储... 查看详情

序列式容器(代码片段)

目录容器结构分类通过萃取机traits萃取迭代器的型别容器listlist的定义list的node定义list的iterator容器vectorvector的定义vector的iteratorvector的大小arrayarray的定义forward_listforward_list与list的区别dequedeque的定义deque的iterator容器结构分类这... 查看详情

云原生一文带你搞懂docker容器的核心基石cgroups(代码片段)

目录大家好,本文是对Docker容器的核心基石Cgroups的详细讲解,讲解了Cgroups的相关概念、Cgroups的构成与作用、如何查看和使用Cgroups等,对大家后续理解容器有很大的帮助~1、为什么要了解Cgroups2、Cgroups简介3、什么是Cg... 查看详情

带你深入理解stl之list容器

上一篇博客中介绍的vector和数组类似,它拥有一段连续的内存空间,并且起始地址不变,很好的支持了随机存取,但由于是连续空间,所以在中间进行插入、删除等操作时都造成了内存块的拷贝和移动,另... 查看详情