C++——list的了解和使用

目录

引言

forward_list与list

标准库中的list

一、list的常用接口

1.list的迭代器

2.list的初始化

3.list的容量操作

4.list的访问操作

5.list的修改操作

6.list的其他操作

二、list与vector的对比

结束语


引言

本篇博客要介绍的是STL中的list。

求点赞收藏评论关注!!!十分感谢!!!

forward_list与list

首先我们先简单了解一下forward_list与list:

forward_list与list都是C++标准模板库(STL)中的容器,它们提供了不同的链表实现,适用于不同的场景。

forward_list

定义与结构:

1.forward_list是C++11引入的一种容器,它提供了一种单向链表的数据结构。

2.它只维护一个指向下一个节点的指针,因此内存使用相对高效。

特点:

1.只能在单向遍历,即只能从前往后遍历,不能反向遍历。

2.在已知位置的情况下,插入和删除操作非常高效,时间复杂度为O(1)。

3.不支持通过索引访问元素,只能使用迭代器进行访问。

适用场景:

1.适用于需要频繁进行前向遍历和插入、删除操作的场景。

2.当内存使用要求较高,且不需要双向遍历时,forward_list是更好的选择。

list

定义与结构:

1.list是C++标准库中基于带头双向循环链表实现的容器。

2.它支持双向迭代器,可以从前往后和从后往前遍历。

特点:

1.在任何位置进行插入和删除操作的时间复杂度都是近似O(1)。

2.支持双向遍历,迭代器使用更灵活。

3.与forward_list相比,内存占用稍多,因为每个节点需要维护两个指针(一个指向前一个节点,一个指向下一个节点)。

适用场景:

1.适用于需要双向遍历和更灵活操作的场景。

2.当需要在列表中间频繁插入或删除元素时,list是更好的选择。

具体内容可以看看这两篇文章:

数据结构——单链表

数据结构——双向链表

本文的重点是list。

标准库中的list

一、list的常用接口

list接口

1.list的迭代器

list的迭代器访问元素与我们之前学习的其他容器的迭代器访问一样。

int main()
{list<int> li = { 1, 2, 3, 4, 5 };list<int>::iterator it = li.begin();cout << "顺序遍历:";while (it != li.end()){cout << *it << " ";++it;}cout << endl;cout << "逆序遍历:";list<int>::reverse_iterator rit = li.rbegin();while (rit != li.rend()){cout << *rit << " ";++rit;}return 0;
}

由于list的迭代器是双向迭代器,支持++和--操作,因此可以在list中向前和向后遍历。

2.list的初始化

list的初始化与我们之前学习的其他容器的初始化一样,我们直接看个简单的使用示例:

int main()
{// 默认构造函数list<int> numbers1;cout << "默认构造: ";for (const auto& num : numbers1) {cout << num << " ";}cout << endl;// n个val构造list<int> numbers2(5, 5);cout << "n个val构造: ";for (const auto& num : numbers2) {cout << num << " ";}cout << endl;int arr[] = { 1, 2, 3, 4, 5 };// 通过vector的迭代器初始化list<int> numbers3(arr, arr + sizeof(arr) / sizeof(arr[0]));cout << "迭代器区间构造: ";for (const auto& num : numbers3) {cout << num << " ";}cout << endl;list<int> numbers4 = { 6, 7, 8, 9, 10 };// 拷贝构造list<int> numbers5(numbers4);cout << "拷贝构造: ";for (const auto& num : numbers5) {cout << num << " ";}cout << endl;numbers1 = numbers2;// 赋值重载cout << "赋值重载: ";for (const auto& num : numbers1) {cout << num << " ";}cout << endl;return 0;
}

输出结果为:

3.list的容量操作
函数名称功能
size返回列表中元素的数量
max_size返回列表可容纳的最大元素数量
empty检查列表是否为空,是则返回 true,否则返回 false
resize重新设置列表中元素的数量,超过原来数量则用默认值填充
clear清空列表中的所有元素

这些函数也是很容易理解的,我们还是直接看代码示例:

int main()
{list<int> li = { 1,2,3,4,5 };cout << "Size of list: " << li.size() << endl;cout << "Max size of list: " << li.max_size() << endl;if (li.empty()){cout << "empty" << endl;}else{cout << "not empty" << endl;}li.clear();if (li.empty()){cout << "empty" << endl;}else{cout << "not empty" << endl;}return 0;
}

输出结果为

与deque这一容器一样,list也没有reserve这一接口。

int main()
{list<int> li = { 1,2,3 };li.resize(5);for (auto& num : li){cout << num << " ";}cout << endl;li.resize(2);for (auto& num : li){cout << num << " ";}return 0;
}

输出结果为;

4.list的访问操作
函数名称功能
back返回列表最后一个元素
front返回列表第一个元素

由于list 是一个双向链表,不支持高效的随机访问。在链表中,访问某个元素需要从头节点开始顺序遍历,直到找到目标元素。因此,为 list 提供下标运算符或 at 方法并不合适。

访问操作的使用示例如下:

int main()
{list<int> li = { 1,2,3 };cout << li.front() << endl;cout << li.back() << endl;return 0;
}

输出结果为:

5.list的修改操作

常用的修改操作有如下几个:

函数名称功能
push_back在列表尾部添加元素
push_front在列表头部添加元素
pop_back删除列表最后一个元素
pop_front删除列表第一个元素
insert在指定位置插入元素
erase删除指定位置或区间的元素
swap交换两个列表
assign使用指定列表替换原列表

这些接口我们也是十分熟悉了,我们直接看代码示例:

尾删和尾插:

int main()
{list<int> li;li.push_back(1);li.push_back(2);li.push_back(3);li.push_back(4);for (auto& num : li) {cout << num << " ";}cout << endl;li.pop_back();for (auto& num : li){cout << num << " ";}cout << endl;return 0;
}

输出结果为:

头删和头插:

int main()
{list<int> li;li.push_front(1);li.push_front(2);li.push_front(3);li.push_front(4);for (auto& num : li){cout << num << " ";}cout << endl;li.pop_front();for (auto& num : li){cout << num << " ";}cout << endl;return 0;
}

输出结果为:

assign和swap:

int main()
{list<int> li1 = { 1,1,1,1,1 };li1.assign(3, 3);for (auto& num : li1){cout << num << " ";}cout << endl;list<int> li2 = { 2,2,2,2,2 };li1.swap(li2);for (auto& num : li1){cout << num << " ";}cout << endl;for (auto& num : li2){cout << num << " ";}return 0;
}

输出结果为:

insert:

int main()
{list<int> li = { 1,2,3,4,5 };list<int>::iterator it = li.begin();it = li.insert(it, 6);it = li.insert(it, 7);for (auto& num : li){cout << num << " ";}return 0;
}

输出结果为:

erase:

int main()
{list<int> li = { 1,2,3,4,5 };list<int>::iterator it = li.begin();it = li.erase(it);for (auto& num : li){cout << num << " ";}return 0;
}

输出结果为:

6.list的其他操作

接下来我们来学习list的其他操作:

函数名称功能描述
splice将元素从一个列表转移到另一个列表
remove移除具有特定值的元素
remove_if移除满足条件的元素
unique移除重复的值
sort对容器中的元素进行排序
merge合并已排序的列表
reverse反转元素的顺序

splice:

splice 是 list 提供的一个成员函数,用于将一个列表(list)中的元素移动到另一个列表中,而不需要进行元素复制或移动操作。

使用示例:

int main()
{list<int> li1 = { 1,2,3 };list<int> li2 = { 4,5,6 };list<int> li3 = { 7,8,9 };list<int> li4 = { 0 };// 将 li2 的所有元素拼接到 li1 的末尾// li1 现在包含 {1, 2, 3, 4, 5, 6}// li2 现在为空 {}li1.splice(li1.end(), li2);for (auto num : li1){cout << num << " ";}cout << endl;// 获取 li3 的迭代器,指向第一个元素(7)auto begin1 = li3.begin();// 将迭代器向前移动一位,指向第二个元素(8)++begin1;// 将 li3 的第一个元素(7)移动到 li4 的末尾// li4 现在包含 {0, 7}// li3 现在包含 {8, 9}li4.splice(li4.end(), li3, li3.begin(), begin1);for (auto num : li4){cout << num << " ";}return 0;
}

输出结果为:

remove:

用于从容器中移除所有等于指定值的元素。

与成员函数 erase 不同,成员函数 erase 按元素的位置擦除元素(使用迭代器),此函数  按元素的值删除元素。

int main()
{list<int> li = { 1,2,3,3,4,5 };li.remove(3);for (auto num : li){cout << num << " ";}cout << endl;return 0;
}

输出结果为:

remove_if:

用于从容器中移除满足特定条件的元素。

bool fun(int num)
{return num == 3;
}int main()
{list<int> li = { 1,2,3,3,4,5 };li.remove_if(fun);for (auto num : li){cout << num << " ";}cout << endl;return 0;
}

输出结果为:

unique:

用于移除容器中连续重复的元素。

int main()
{list<int> li = { 1,2,3,3,4,5 };li.unique();for (auto num : li){cout << num << " ";}return 0;
}

输出结果为:

sort:

用于对容器中的元素进行排序。

int main()
{list<int> li = { 9,1,5,3,2,4,8,0,7,6 };li.sort();for (auto num : li){cout << num << " ";}return 0;
}

输出结果为:

merge:

用于将两个已排序的范围合并成一个有序范围。

要求输入的两个范围必须是有序的(通常是升序)。它会将两个范围中的元素按顺序合并到目标范围中。目标范围必须有足够的空间来存储合并后的结果。

int main()
{list<int> li1 = { 1,3,2,5,7 };list<int> li2 = { 2,3,4,6,8 };li1.sort();li2.sort();li1.merge(li2);for (auto num : li1){cout << num << " ";}return 0;
}

输出结果为:

reverse:

用于反转容器中元素的顺序。

int main()
{list<int> li = { 9,1,5,3,2,4,8,0,7,6 };li.reverse();for (auto num : li){cout << num << " ";}return 0;
}

输出结果为:

二、list与vector的对比

vectorlist
底层结构动态顺序表,一段连续空间带头结点的双向循环链表
随机访问支持随机访问,访问某个元素效率O(1)不支持随机访问,访问某个元素效率O(N)
插入和删除任意位置插入和删除效率低,需要搬移元素,时间复杂度为O(N),插入时有可能需要增容,增容:开辟新空间,拷贝元素,释放旧空间,导致效率更低任意位置插入和删除效率高,不需要搬移元素,时间复杂度为0(1)
空间利用率底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高底层节点动态开辟,小节点容易造成内存碎片,空间利用率低,缓存利用率低
迭代器原生态指针对原生态指针(节点指针)进行封装
迭代器失效在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效插入元素不会导致选代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响
使用场景需要高效存储,支持随机访问,不关心插入删除效率大量插入和删除操作,不关心随机访问

结束语

求点赞收藏评论关注!!!

感谢各位大佬的支持!!!

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

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

相关文章

Charles 4.6.7 浏览器网络调试指南:HTTPS抓包(三)

概述 在现代互联网应用中&#xff0c;网络请求和响应是服务交互的核心。对于开发者和测试人员来说&#xff0c;能够准确捕获并分析这些请求&#xff0c;是保证系统稳定性和性能的关键。Charles作为一个强大的网络调试工具&#xff0c;不仅可以捕获普通的HTTP请求&#xff0c;还…

js手撕 | 使用css画一个三角形 使用js修改元素样式 驼峰格式与“-”格式相互转化

1.使用css画一个三角形 借助 border 实现&#xff0c;在 width 和 height 都为 0 时&#xff0c;设置 border&#xff0c;便会呈现三角形。想要哪个方向的三角形&#xff0c;设置其他三边为 透明即可。同时&#xff0c;可以通过调整不同边的宽度&#xff0c;来调整三角形的高度…

六、深入了解DI

依赖注入是⼀个过程&#xff0c;是指IoC容器在创建Bean时,去提供运⾏时所依赖的资源&#xff0c;⽽资源指的就是对象. 在上⾯程序案例中&#xff0c;我们使⽤了 Autowired 这个注解&#xff0c;完成了依赖注⼊的操作. 简单来说,就是把对象取出来放到某个类的属性中。 关于依赖注…

Doris Schema Change 常见问题分析

1. 什么是 Schema Change Schema Change 是在数据库中修改表结构的一种操作&#xff0c;例如添加列、删除列、更改列类型等。 ⚠️Schema Change 限制⚠️ 一张表在同一时间只能有一个 Schema Change 作业在运行。分区列和分桶列不能修改。如果聚合表中有 REPLACE 方式聚合的…

Qt Designer and Python: Build Your GUI

1.install pyside6 2.pyside6-designer.exe 发送到桌面快捷方式 在Python安装的所在 Scripts 文件夹下找到此文件。如C:\Program Files\Python312\Scripts 3. 打开pyside6-designer 设计UI 4.保存为simple.ui 文件&#xff0c;再转成py文件 用代码执行 pyside6-uic.exe simpl…

Centos7系统php8编译安装ImageMagick/Imagick扩展教程整理

Centos7系统php8编译安装ImageMagick/Imagick扩展教程整理 安装php8安装ImageMagick1、下载ImageMagick2、解压并安装3、查看是否安装成功 安装imagick扩展包 安装php8 点我安装php8 安装ImageMagick 1、下载ImageMagick wget https://www.imagemagick.org/download/ImageMa…

数据中台解决方案

数据中台概述 数据中台是数字化转型的基础&#xff0c;它不仅仅是一个平台&#xff0c;而是一套可持续让企业数据用起来的机制。这套机制涵盖了数据的采集、治理、开发到数据服务的全过程&#xff0c;旨在通过数据复用能力的提升&#xff0c;灵活支撑前端业务。数据中台通过“…

Linux——rzsz工具

rzsz这个工具用于 windows 机器和远端的 Linux 机器通过 XShell 传输文件. 安装完毕之后可以通过拖拽的方式将文件上传过去. 安装rzsz工具 rz&#xff1a;从Windows机器上传到远程Linux机器&#xff08;或者直接把文件托进Xshell中&#xff09; sz&#xff1a;将文件从Linux远…

SpringBoot基础概念介绍-数据源与数据库连接池

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 毛毛张今天介绍的SpringBoot中的基础概念-数据源与数据库连接池&#xff0c;同时介绍SpringBoot整合两种连接池的教程 文章目录 1 数据库与数据库管理系统2 JDBC与数…

MyBatis框架基础学习及入门案例(2)

目录 一、数据库建表(tb_user)以及添加数据。 &#xff08;1&#xff09;数据库与数据表说明。 &#xff08;2&#xff09;字段与数据说明。 二、创建模块(或工程)、导入对应所需依赖坐标。 三、编写MyBatis核心主配置文件。(解决JDBC中"硬编码"问题) &#xff08;1&…

js小游戏---2048(附源代码)

一、游戏页面展示 开始游戏&#xff1a; 游戏结束&#xff1a; 二、游戏如何操作 通过监听键盘的操作&#xff0c;进行移动变化 键盘上下左右键控制页面中所有模块同时向键入的方向移动&#xff0c;如果有两块一样的方块&#xff0c;就进行合并&#xff0c;并且在键盘每操作…

美格智能AIMO智能体+DeepSeek-R1模型,AI应用的iPhone时刻来了

导语&#xff1a; 当AI大模型从云端下沉至终端设备&#xff0c;一场关于效率、隐私与智能化的革命悄然展开。作为全球领先的无线通信模组及解决方案提供商&#xff0c;美格智能凭借其高算力AI模组矩阵与端侧大模型部署经验&#xff0c;结合最新发布的AIMO智能体产品&#xff0…

C语言的灵魂——指针(1)

指针是C语言的灵魂&#xff0c;有了指针C语言才能完成一些复杂的程序&#xff1b;没了指针就相当于C语言最精髓的部分被去掉了&#xff0c;可见指针是多么重要。废话不多讲我们直接开始。 指针 一&#xff0c;内存和地址二&#xff0c;编址三&#xff0c;指针变量和地址1&#…

物业巡更系统助推社区管理智能化与服务模式创新的研究与应用

内容概要 在现代社区管理中&#xff0c;物业巡更系统扮演着至关重要的角色。首先&#xff0c;我们先来了解一下这个系统的概念与发展背景。物业巡更系统&#xff0c;顾名思义&#xff0c;是一个用来提升物业管理效率与服务质量的智能化工具。随着科技的发展&#xff0c;传统的…

关于CAN(FD)转以太网详细介绍

一、功能描述 CANFD 完全向下兼容 CAN &#xff0c;以下统称 CAN(FD) 。 SG-CAN(FD)NET-210 是一款用来把 CANFD 总线数据转为网口数据的设备。 网口支持 TCP Sever 、 TCP Client 、 UDP Sever 、 UDP Client 四种模式。 可以通过软件配置和 Web 网页配置。 两路…

用Python和PyQt5打造一个股票涨幅统计工具

在当今的金融市场中&#xff0c;股票数据的实时获取和分析是投资者和金融从业者的核心需求之一。无论是个人投资者还是专业机构&#xff0c;都需要一个高效的工具来帮助他们快速获取股票数据并进行分析。本文将带你一步步用Python和PyQt5打造一个股票涨幅统计工具&#xff0c;不…

Centos类型服务器等保测评整/etc/pam.d/system-auth

修改服务器配置文件/etc/pam.d/system-auth&#xff0c;但是&#xff0c;把一下配置放在password的配置第一行才会生效 执行命令&#xff1a;配置口令要求&#xff1a;大小写字母、数字、特殊字符组合、至少8位&#xff0c;包括强制设置root口令&#xff01; sed -i 14a pas…

At coder beginner contest 290AB

A12435 思路&#xff1a;只有4中情况:A1,A2翻转&#xff0c;其他正常&#xff0c;A2A3翻转其他正常.....为了下标与数字对应我开了6个空间&#xff0c;然后从1开始循环&#xff0c;到4截止&#xff0c;因为循环中有i1害怕数组越界&#xff0c;如果索引出的数与下标不相等了&…

Vue3 + TS 实现批量拖拽 文件夹和文件 组件封装

一、html 代码&#xff1a; 代码中的表格引入了 vxe-table 插件 <Tag /> 是自己封装的说明组件 表格列表这块我使用了插槽来增加扩展性&#xff0c;可根据自己需求&#xff0c;在组件外部做调整 <template><div class"dragUpload"><el-dial…

STM32完全学习——RT-thread在STM32F407上移植

一、写在前面 关于源码的下载&#xff0c;以及在KEIL工程里面添加操作系统的源代码&#xff0c;这里就不再赘述了。需要注意的是RT-thread默认里面是会使用串口的&#xff0c;因此需要额外的进行串口的初始化&#xff0c;有些人可能会问&#xff0c;为什么不直接使用CubMAX直接…