当前位置: 首页 > article >正文

【C++】容器list常用接口详解

目录

一.基本介绍

二.list的使用

1.构造函数

2.迭代器

3.遍历方式

4.容量相关操作

5.增删改查

三.list迭代器失效问题

四.算法库函数和list关系


一.基本介绍

  1. list是一个带头双向循环链表
  2. 由于是链表,物理空间不连续,不支持随机访问数据,因此和vector相比,少了[]访问和resize、reserve等容量相关的函数
  3. 与其他序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好

二.list的使用

1.构造函数

构造函数功能说明
list(size_type n, const value_type& val = value_type())构造一个包含n个val元素的列表
list()构造一个空列表
list(const list& x)拷贝构造函数,构造一个包含x中每个元素的列表
list(InputIterator first, InputIterator last)用区间 [ first , last ) 中的元素构造的一个列表
list<int> l1;//无参构造
list<int> l2(10, 1);//用10个1初始化链表

vector<int> v{ 1,2,3,4,5 };
list<int> l3(v.begin(), v.end());//用迭代器区间初始化

2.迭代器

list不支持随机访问, 其底层就不是指针了,但迭代器的底层我们并不关心,只需要将其视为指针使用就行。

 这四个函数都是老朋友了,不多介绍了,但是在带头双向循环链表中,它的位置值得注意不妨用这个代码测试一下:

 当然也有begin()就是rend(),end()是rbegin()这种,这个在后续实现反向迭代器的时候再谈。 

3.遍历方式

迭代器遍历

vector<int> v{ 1,2,3,4,5,6,7,8 };
list<int> l(v.begin(), v.end());
//list<int> l{ 1,2,3,4,5,6,7,8 };

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

 范围for遍历

vector<int> v{ 1,2,3,4,5,6,7,8 };
list<int> l(v.begin(), v.end());
//list<int> l{ 1,2,3,4,5,6,7,8 };

for (auto e : l)
{
	cout << e << " ";
}
cout << endl;

注意:list不支持随机访问,因此不能使用[ ] ,也就少了一种普通下标循环遍历 

4.容量相关操作

函数功能
empty检测列表是否为空。如果为空返回 true,否则返回 false。
size返回列表中元素的个数
函数功能
front返回list的第一个元素的引用。
back返回list的最后一个元素的引用。

5.增删改查

函数功能
push_front在list首元素前插入值为val的元素
pop_front删除list中第一个元素
push_back在list尾部插入值为val的元素
push_front删除list中最后一个元素
insert在list position 位置中插入值为val的元素
erase删除list position位置的元素
swap交换两个list中的元素
clear清空list中的有效元素

大致都和之前的string,vector差不多,不过由于list不像vector一样具有size和capacity,list的clear就是直接清空链表(除头结点外)

三.list迭代器失效问题

由于list底层是带头双向循环链表,因此在插入操作时,pos指向的始终是同一个位置,它们只改变链接关系,并不连续,因此插入操作并不会导致list迭代器失效

但在erase删除操作时list迭代器会失效。erase删除的位置在空间上是唯一的,这个位置的数据被删除后,只是改变了原有的链接关系,此位置已经不在原链表中了,再次使用就会出错 

STL库中的erase使用返回值来解决迭代器失效,返回被删除位置的下一个位置的迭代器 

list<int> l{ 1,2,3,4,5,6,7,8,9 };
auto it = l.begin();
while (it != l.end())
{
	if (*it % 2 == 0)
	{
		it = l.erase(it);
	}
	else
	{
		++it;
	}
}
for (auto e : l)
{
	cout << e << " ";
}
cout << endl;

 四.算法库函数和list关系

迭代器从功能角度可以分为三种:

  1. 正向迭代器:forward_iterator ,只支持++
  2. 双向迭代器:bidirectional_iterator ,支持++和--
  3. 随机迭代器:random_iterator ,支持++,--,+,-
常见的容器以及它们的迭代器类型
容器迭代器类型
vector随机迭代器
list双向迭代器
stack不支持迭代器
queue不支持迭代器
deque随机迭代器
set / multiset双向迭代器
map / multimap双向迭代器
priority_queue不支持迭代器

在算法库中常见的函数,例如sort,它的函数模板支持的就是随机迭代器,reverse支持双向迭代器

三类迭代器支持向上兼容,也就是说

  • 函数模板给的随机迭代器:只允许随机迭代器
  • 函数模板给的双向迭代器:允许随机和双向迭代器 
  • 函数模板给的单向迭代器:允许随机、双向和单向迭代器

可见list是双向迭代器,那么它就不能使用库里的sort函数(要求随机迭代器),因此list类自己实现了一个不同于算法库的排序,专门用来排序list的数据 虽然list有自己的sort函数来排序,但当数据很多时,效率低得惊人,因此有了另一种排序list的方法:先将list的数据导入vector容器,再在vector容器中使用算法库的sort排序,排完再导回list中


本文就到这里,下一章将对list进行模拟实战,欢迎持续关注


http://www.kler.cn/a/298770.html

相关文章:

  • 如何从 0 到 1 ,打造全新一代分布式数据架构
  • 在 RK3568 Linux 系统上使用 TUN 设备:详细教程
  • MySQL 锁概述
  • 设计模式的主要分类是什么?请简要介绍每个分类的特点。
  • 实现点击表格中的邀请码并复制到剪贴板的功能
  • QT笔记- QTreeView + QFileSystemModel 当前位置的保存与恢复 #选中 #保存当前索引
  • vue3 嵌套iframe 通讯
  • Docker 安装FileBeat、Elasticsearch及Kibana详细步骤
  • 基于Pinia和Compute的持久化localStorage登录态管理Vuejs 源码教学
  • 服务网关工作原理,如何获取用户真实IP?
  • Android Radio2.0——公告监听设置(四)
  • 表连接查询之两个left join与递归SQL
  • 使用Python本地搭建http.server文件共享服务并实现公网环境远程访问——“cpolar内网穿透”
  • 党务政务服务|基于SprinBoot+vue的党务政务服务热线系统(源码+数据库+文档)
  • Swagger UI 无法发送 Cookie
  • FFmpeg读取文件列表
  • FunASR搭建语音识别服务和VAD检测
  • GPT-4o mini轻量级大模型颠覆AI的未来
  • 软件测试学习笔记丨Vim编辑器的常用命令
  • 挂轨巡检机器人在发电厂与煤矿皮带机场景的应用
  • C语言猜数字小游戏(6)
  • Tensorflow2如何读取自制数据集并训练模型?-- Tensorflow自学笔记13
  • 如何在 Nuxt 3 中有效使用 TypeScript
  • TCP-IP5层模型
  • Hadoop命令
  • 【鸿蒙 HarmonyOS NEXT】使用屏幕属性display:获取屏幕宽高