一.list的介绍:

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

  2.list的底层是双向链表结构,带有哨兵位的头结点 。

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

  4.由于底层是链表结构,list通常在任意位置进行插入,删除元素的执行效率更好。

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

  6.在list这个容器里面,是不支持[]等操作的。

list的底层:(双向带头循环链表)

二.list的使用:

1.list的构造:

(1)empty container constructor (default constructor):构造空的list。

list<int> mylist;

(2) fill constructor:构造一个有n个元素的链表,每个元素的值都是val。

list<int> list4(10, 1);
for (auto e : list4) {cout << e << " ";
}
//如上代码就成功构造了一个有10个1的链表

(3) range constructor:使其元素数量与区间 [first,last) 内的元素数量相同,并且每个元素都是根据该区间内对应位置的元素原位构造(emplace-constructed)而成,保持相同的顺序。

vector<int> t1 = { 1,2,3,4,5,6,7,8,9 };
int a[] = { 1,2,3,4 };
list<int> list2(t1.begin(), t1.end());
list<int> list3(a, a + 4);
//值得关注的是,要求传递的是迭代器,但是也可以传数组的指针

(4)copy constructor (and copying with allocator):拷贝构造。(同其他的容器一模一样,不多介绍如何使用)

(5)暂时不介绍,后面再介绍。

(6)initializer list constructor:简单点来说就是把想存进list的值全部用一个花括号括起来,每个值用逗号分隔开,然后用这些值构造一个list。

list<int> list1 = { 1,2,3,4,5,6,7,8,9 };

2.capacity:

其中max_size其实用的不多,这点在vector里面也一样,上面两个和其他容器的用法一模一样。

3.element access:

这两个函数返回的分别是链表的第一个元素和最后一个元素。

4.Modifiers:

 (挑一些特殊和重要的讲不讲的和其他容器使用差不多)

(1)assign:在 C++ 标准库中,std::list 的 assign() 方法用于替换链表中的所有元素,支持多种赋值方式。它会清空原链表,再将新元素赋值给链表。

list<int> numbers;
numbers.assign(3, 100);
 std::vector<int> src = {1, 2, 3, 4};std::list<int> numbers;numbers.assign(src.begin(), src.end()); // 链表变为 {1, 2, 3, 4}
 std::list<char> chars;chars.assign({'a', 'b', 'c'}); // 链表变为 {'a', 'b', 'c'}

(2)emplace_front:在链表的首部直接构造一个新元素,跟push_front的功能差不多,但是二者的效率可能会有一些不同。

(3)insert:提供了很多不同的版本:

分别举例:


int main ()
{std::list<int> mylist;std::list<int>::iterator it;// set some initial values:for (int i=1; i<=5; ++i) mylist.push_back(i); // 1 2 3 4 5it = mylist.begin();++it;       // it points now to number 2           ^mylist.insert (it,10);                        // 1 10 2 3 4 5//在pos位置insert一个val// "it" still points to number 2                      ^mylist.insert (it,2,20);                      // 1 10 20 20 2 3 4 5//在pos位置insert指定数目的val--it;       // it points now to the second 20            ^std::vector<int> myvector (2,30);mylist.insert (it,myvector.begin(),myvector.end());// 1 10 20 30 30 20 2 3 4 5//在pos位置inset一段迭代器区间所对应的值std::cout << "mylist contains:";for (it=mylist.begin(); it!=mylist.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

list里面的list由于不会扩容,所以没有迭代器失效的问题,但是返回值也是迭代器。

(4)erase:

erase提供了两种方式,在pos位置删除和删除一段迭代器区间。如同vector一样,erase有迭代器失效的效果,所以返回的是pos位置的下一个迭代器位置。

(5)swap:交换两个链表的内容:

int main() {std::list<int> a = {1, 2, 3};std::list<int> b = {4, 5};a.swap(b); // 交换 a 和 b 的内容std::cout << "a: ";for (int x : a) std::cout << x << " "; // 输出: 4 5std::cout << "\nb: ";for (int x : b) std::cout << x << " "; // 输出: 1 2 3
}

5.operations:

(1)splice:

 std::list 的 splice() 方法用于将一个链表的元素转移到另一个链表中,且不会导致元素的复制或移动,而是直接修改链表的内部指针,因此效率极高(时间复杂度为 O (1))。这个函数用到的地方不是很多,但是后面会有大用处。将一个链表的元素转移到另一个链表中,另一个链表也可以是自己本身。

(2)remove:

  std::list 的 remove() 方法用于删除链表中所有等于特定值的元素。它会遍历整个链表,移除所有匹配的元素,并自动调整链表结构,保持元素间的连续性。需要传递的参数就是要删除的值val

  remove_if就是和上面的作用差不多,但是需要满足一定的条件。

(3)unique:

std::list 的 unique() 方法用于移除链表中相邻的重复元素,只保留其中一个。它会遍历链表,将相邻且值相等的元素压缩为单个元素,从而使链表中的元素唯一(仅针对相邻元素)。

(4)merge:

std::list 的 merge() 方法用于将另一个有序链表合并到当前链表中,合并后当前链表仍保持有序。使用这个函数的前提是,两个链表必须已经按相同顺序排序

int main() {std::list<int> a = {1, 3, 5};std::list<int> b = {2, 4, 6};// 将 b 合并到 a 中,a 仍保持有序a.merge(b);// 输出: 1 2 3 4 5 6for (int num : a) {std::cout << num << " ";}// b 变为空链表std::cout << "\nb size: " << b.size(); // 输出: 0
}

合并之后被合并的那个链表会变成空的链表。

(5)sort:

由于迭代器类型的原因,sort不能使用<algorithm>头文件里面的sort,所以单独写了一个sort,但是在list里面的这个sort是归并排序,在进行大量数据排序的时候效率并没有算法库里面的sort效率高,因此使用的时候经常将list里面的元素放到vector里面,如何排好序后再assign回list里面。

原因在下面解释。

(6)reverse:

不能使用算法库里面的reverse的原因和sort一样。

三.迭代器类型:

 迭代器有很多种,是根据容器的底层来决定的。inputiterator(输入迭代器),forwarditerator(前向迭代器),bidirectioniterator(双向迭代器),randmaccessiterator(随机访问迭代器)。

 inputiterator迭代器和forwarditerator都是只支持++,*的操作,双向迭代器支持++,--,*的操作,随机迭代器支持不仅支持前面所有的,还支持额外的随机访问,比如+n,> , <, 迭代器之间的减法等操作。

一个容器是否能使用算法库里面的函数,需要看迭代器类型,在前面列举的类型里面,按顺序是包含关系。这是按照迭代器的功能来划分的。

那么为什么list容器不能调用sort函数呢,list容器是双向迭代器,而sort要求的是随机迭代器,所以不能调用,反之,如果有一个随机迭代器的容器,那么它是可以取使用要求是双向迭代器的函数的。

四.补充一些知识:

---->   计算机的存储体系如图所示:

              

     ->平时最关注的就是主存以及本地磁盘。

     ->其中主存是带电的,存储速度很快,没有电就不能存储数据,一旦断电,RAM (主存一般指ram,然后ram又分为dram和sram)中存储的数据就会立即丢失,这就是为什么主存是易失性存储器。而本地磁盘是不带电的,没有电它也可以存储数据,在断电后仍能保存数据,属于非易失性存储器。

    ->我们书写一个顺序表或者链表,它都是存放在主存(也就是通常说的内存)里面的,数据结构就是在内存中对数据进行管理,所以当然是在主存上的。我们对顺序表,链表的数据进行遍历和修改的时候,是cpu来完成的,但是cpu是不能直接访问内存的,形象一点说,这是因为它太“快”了,而它觉得内存太慢了。这时候就有一个cpu高速缓存的概念了:      

cpu的机制是这样的,比如说我要访问一个指针,cpu先进缓存,如果这个指针在缓存里面,那么就叫做“命中”,这样cpu就可以直接访问了。如果“不命中”的情况下,内存的数据(当然不可能是内存的全部数据)会先进入缓存里面,然后再让cpu去“命中”。在这样的条件下就有一个缓存命中率的概念产生,对于顺序表和链表先说结论就是顺序表的缓存命中率高,而链表的缓存命中率低。内存在把数据给缓存的时候,假设要用的数据是4个字节,它就会从内存里面多拿连续的一部分给缓存(这是局部性原理预取相邻的数据的效果,但是具体多取多少,这是又是硬件等多方面因素决定的)。稍微应用一下豆包的话来类比一下这个局部性原理:

由于顺序表的结构优势,使得在上述原理下“命中率”变高,虽然在链表的一个节点的后面会多拿一些数据,但是包含下一个节点的概率不大,所以链表的“命中率低”。

--------取自《深度理解计算机系统》--------。

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

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

相关文章

Ntfs!LfsUpdateLfcbFromRestart函数分析之Ntfs!LfsFindOldestClientLsn

第0部分&#xff1a;//// Find the oldest client Lsn. Use the last flushed Lsn as a starting point.//Lfcb->OldestLsn Lfcb->LastFlushedLsn;LfsFindOldestClientLsn( RestartArea,Add2Ptr( RestartArea, Lfcb->ClientArrayOffset, PLFS_CLIENT_RECORD ),&…

「日拱一码」021 机器学习——特征工程

目录 特征选择 过滤法&#xff08;Filter Methods&#xff09; 方差选择法 相关系数法 卡方检验 包裹法&#xff08;Wrapper Methods&#xff09; 递归特征消除&#xff08;RFE&#xff09; 嵌入法&#xff08;Embedded Methods&#xff09; L1正则化&#xff08;Lasso…

k8s:安装 Helm 私有仓库ChartMuseum、helm-push插件并上传、安装Zookeeper

ChartMuseum 是 Kubernetes 生态中用于存储、管理和发布 Helm Charts 的开源系统&#xff0c;主要用于扩展 Helm 包管理器的功能 核心功能 ‌集中存储‌&#xff1a;提供中央化仓库存储Charts&#xff0c;支持版本管理和权限控制。 ‌ ‌跨集群部署‌&#xff1a;支持多集群环境…

C++编程学习(第二天)

1、求a和b两个数之和。#include <iostream> using namespace std;int main() {int a, b, sum; //定义变量a、b、sumcout << "请输入第一个数字a: "; //打印需要显示的字符串cin >> a; // >&…

毫米波雷达守护银发安全:七彩喜跌倒检测仪重构居家养老防线

在老龄化加速与独居老人数量攀升的背景下&#xff0c;跌倒已成为威胁老年人生命安全的“隐形杀手”。七彩喜跌倒检测仪以毫米波雷达技术为核心&#xff0c;通过“非接触式监测智能预警”重塑居家安全防护体系&#xff0c;为银发群体构建起全天候、无感化的数字守护网。技术突破…

面试复盘:节流中第二次触发的事件?答错补课

面试复盘&#xff1a;节流中第二次触发的事件&#xff1f;答错补课 背景描述 今天面试时被问到一个看似基础但暗藏玄机的问题&#xff1a;“节流&#xff08;Throttle&#xff09;函数中&#xff0c;第二次触发的那一帧事件是否会被丢掉&#xff1f;” 我基于对经典节流实现的…

Spark伪分布式集群搭建(Ubuntu系统)

环境准备 系统要求&#xff1a;Ubuntu 20.04/22.04 LTS 软件版本&#xff1a; Hadoop 3.3.5 JDK 8 Spark-3.5.6-bin-hadoop3 硬件要求&#xff1a;至少4GB内存&#xff0c;20GB磁盘空间 以下是基于Ubuntu系统的Spark伪分布式集群搭建全流程。以Spark 3.5.6 Hadoop 3.3.…

【快手】数据挖掘面试题0001:查找连续三天登录的用户

文章大纲一、测试数据构建二、自连接方案三、窗口函数方案一张用户表&#xff0c;uer_id&#xff0c;signin_date&#xff0c;大概是这么几项&#xff0c;查找连续三天登录的用户。 比如说&#xff0c;1,2两天登录不是连续三天&#xff0c;456登录为连续三天登录&#xff0c;56…

简说scp命令

简单介绍 scp的全称是&#xff1a;Secure Copy Protocol&#xff08;安全复制协议&#xff09;&#xff0c;是Linux中用于在网络中安全传输文件的命令行工具。它基于SSH协议&#xff0c;用于在本地服务器和远程服务器之间&#xff0c;或者两台远程服务器之间复制文件或目录。 s…

自动化测试解决方案Parasoft SOAtest无脚本UI测试实践指南

传统UI自动化测试常面临技术门槛高、维护成本大、稳定性差等挑战。尤其在页面频繁变更时&#xff0c;测试脚本的更新和维护会显著降低测试效率。 自动化测试解决方案Parasoft SOAtest通过可视化操作和智能元素定位技术&#xff0c;无需编写代码&#xff0c;让测试人员能够像真…

vscode配置头文件和编译器

在 VS Code 中配置编译器和头文件路径需要修改两个核心文件&#xff1a;c_cpp_properties.json&#xff08;用于智能提示&#xff09;和 tasks.json&#xff08;用于构建&#xff09;。以下是详细步骤&#xff1a; —### 1. 配置智能提示和头文件路径 (c_cpp_properties.json)作…

HTML+JS+CSS制作一个数独游戏

闲来无事&#xff0c;用HTMLJSCSS制作了一个数独游戏消遣。其实主要是自己做题的时候用笔画删除数字太容易出错&#xff0c;所以想搞一个程序稍微辅助一下。通过制作这个程序&#xff0c;反而提高了手工做题的水平&#xff0c;至少学会了记录步数以便于回退。 20250710功能更新…

嵌入式硬件中电容的基本原理与实现详解02

我们今天重点讨论点知识点如下: 1.各种种类的电容优缺点对比讲解 2.电容的标称值介绍 3.电容的单位介绍 4.常见的电压信号有哪些? 5. 电容的耐压值讲解 6.电容的容值有哪些? 7.12pF、15pF 电容常用在什么场合? 8. 振荡电路中使用的电容常常需要使用什么材质的电容? 9.100n…

Python训练打卡DAY46

DAY46&#xff1a;通道注意力&#xff08;SE注意力&#xff09; 恩师浙大疏锦行 知识点&#xff1a; 不同CNN层的特征图&#xff1a;不同通道的特征图什么是注意力&#xff1a;注意力家族&#xff0c;类似于动物园&#xff0c;都是不同的模块&#xff0c;好不好试了才知道。通…

fastadmin_php专项

1.时间的判断,还有就是在php这边如何去拿前端html元素上面的值input($row.borrowtime);// 创建两个 DateTime 对象$row_expecttime new \DateTime(input($row.borrowtime));$par_expecttime new \DateTime( $params[expecttime]); // // 计算两个日期之间的差异 // …

如何在MySQL中选择使用InnoDB还是MyISAM引擎?

在 MySQL 中选择 InnoDB 还是 MyISAM 存储引擎时&#xff0c;需根据应用场景的需求权衡功能、性能和数据完整性。以下是具体的选择指南&#xff1a; 1. 优先考虑事务和外键需求必须使用 InnoDB&#xff1a; 若应用需要 事务支持&#xff08;如金融转账、订单处理&#xff09;或…

邀请函 | 知从科技邀您共赴2025 RISC-V 中国峰会

第五届RISC-V中国峰会将于2025年7月16至19日在上海张江科学会堂隆重举办&#xff0c;本届峰会由上海开放处理器产业创新中心&#xff08;SOPIC&#xff09;主办&#xff0c;RISC-V国际开源实验室&#xff08;RIOS实验室&#xff09;和上海张江高科技园区开发股份有限公司联合主…

企业数字化转型规划和建设方案(管理架构、应用架构、技术架构)PPT

一、战略定位与核心目标以 “技术赋能业务&#xff0c;数据驱动创新” 为核心思路&#xff0c;构建 “三步走” 战略演进路径&#xff0c;实现 IT 从 “基础支撑” 到 “战略引擎” 的升级&#xff1a;IT1.0&#xff08;1-2 年&#xff09;&#xff1a;夯实基础能力定位 “稳健…

基于Uniapp+MySQL+PHP的景区多商户小程序源码系统 带完整的搭建指南

温馨提示&#xff1a;文末有资源获取方式该系统采用 PHP MySQL 的经典开发组合。PHP 作为一种广泛使用的开源脚本语言&#xff0c;具有简单易学、运行速度快、跨平台性强等优点&#xff0c;能够快速开发出功能强大的 Web 应用程序。MySQL 则是一款稳定可靠的关系型数据库管理系…

阿里云和腾讯云RocketMQ 发消息和消费消息客户端JAVA接口

一、RocketMQ 概述RocketMQ 是阿里巴巴开源的一款分布式消息中间件&#xff0c;后捐赠给 Apache 基金会成为顶级项目。它具有低延迟、高并发、高可用、高可靠等特点&#xff0c;广泛应用于订单交易、消息推送、流计算、日志收集等场景。核心特点分布式架构&#xff1a;支持集群…