(笔记)List

一、List的介绍和使用

1.List的介绍

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

1.2 list底层是双向链表结构,双向链表中每个元素都储存在互不相关的独立节点中,在节点中通过指针指向前其前一个元素和后一个元素。

1.3 list和forward_list非常相似,不同的是forward_list是单链表,只能向前迭代,能让其更简单高效。

1.4 与其他容器(array,vector,deque)相比,list通常在任意位置插入,移除元素的执行效率更好。

1.5 与其他容器相比,list和forward_list最大的缺陷是不能支持任意位置的随机访问,比如:要访问list的第六个位置的元素,必须从已知的位置迭代到该位置,在这段位置迭代需要线性的的时间开销,list还需要一些额外空间开销,以保存每个节点的关联信息

2.List的使用

2.1 list的构造

构造函数接口说明
list(size_type n,const value_type& val=value_type())构造的list包括n个位val的值
list()构造空的list
list(const list& x)拷贝构造函数
list(InputIterator first,InputIterator last)用[fisrt,last)区间的元素构造list

构造函数的使用:

//list的构造
void test1()
{list<int> l1;		//构造空的listlist<int> l2(5, 10);//用5个10来构造listlist<int> l3(l2.begin(), l2.end());	//用l2的begin和end迭代器构造listlist<int> l4(l3);	//拷贝构造//有数组的迭代器构造listint array[] = { 10,20,30,40,50 };list<int> l5(array, array + (sizeof(array) / sizeof(int)));//用迭代器的方式打印list<int>::iterator it = l5.begin();while (it != l5.end()){cout << *it << " ";it++;}cout << endl;//直接用列表初始化构造listlist<int> l6{ 1,2,3,4,5,6 };//用范围for的方式进行打印for (auto e : l6){cout << e << " ";}cout << endl;}

运行结果:

10 20 30 40 50
1 2 3 4 5 6

2.2 list iterator的使用

此处,可以吧iterator理解成为一个指针,指向list的一个节点

函数声明接口说明
begin+end返回第一个节点的迭代器和最后一个位置的下一个节点的迭代器
rbegin+rend返回最后一个节点的迭代器和第一个节点的前一个迭代器

迭代器的使用:

//list的迭代器的使用
void test2()
{list<int> l1{ 1,2,3,4,5,6,7,8 };list<int>::iterator it = l1.begin();//auto it=l1.begin();//用迭代器打印l1while (it != l1.end()){cout << *it << " ";it++;}cout << endl;//用范围for打印l1//范围for的底层也是迭代器for (auto e : l1){cout << e << " ";}cout << endl;//反向迭代器的使用list<int>::reverse_iterator rit = l1.rbegin();while (rit != l1.rend()){cout << *rit << " ";rit++;}cout << endl;}

运行结果:

1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
8 7 6 5 4 3 2 1

begin和end为正向迭代器,对迭代器进行++操作,迭代器向后移动;

rbegin和rend为反向迭代器,对迭代器进行++操作,迭代器向前移动;

2.3 list capacity

函数声明接口说明
empty检测list是否为空,是空则返回true,不是空则返回false
size返回list中有效节点的个数
max_size返回列表容器可以存储最大元素的个数

capacity的使用:

void test3()
{list<int> l1(6, 2);cout << l1.empty() << endl;cout << l1.size() << endl;cout << l1.max_size() << endl;
}

运行结果:

0
6
768614336404564650

2.4 list element access

函数声明接口说明
front返回list第一个节点的值的引用
back返回list最后一个节点的值的引用

element access的使用:

//element access
void test4()
{list<string> l1{ "123","234","345","456","567" };cout << l1.front() << endl;cout << l1.back() << endl;l1.front() = "111";l1.back() = "777";cout << l1.front() << endl;cout << l1.back() << endl;
}

运行结果:

123
567
111
777

2.5 list modifiers

函数声明接口说明
push_front(const value_type& val)在list首元素前插入值为val的元素
pop_front()删除list的第一个元素
push_back(const value_type& val)在list尾部插入值为val的元素
pop_back()删除list尾部的元素
insert(const_iterator position,const value_type& val)在position位置插入值为val的元素
erase(const_iterator position)删除position位置的元素
swap(list& x)交换两个list的元素
clear()清空list中的有效元素

push_front、push_back、pop_front、pop_back的使用:

template<class T>
void Printlist(const list<T>& l)
{for (auto e : l){cout << e << " ";}cout << endl;
}
//push_front、pop_front、push_back、pop_back
void test5()
{list<int> l1;l1.push_front(1);l1.push_front(2);l1.push_front(3);l1.push_front(4);Printlist(l1);l1.push_back(1);l1.push_back(2);l1.push_back(3);l1.push_back(4);Printlist(l1);l1.pop_front();l1.pop_front();l1.pop_back();l1.pop_back();Printlist(l1);
}

运行结果:

4 3 2 1
4 3 2 1 1 2 3 4
2 1 1 2

insert、erase的使用:

//insert、earse
void test6()
{list<int> l1{ 1,2,3,4 };//获取l1第二个元素的位置list<int>::iterator pos = ++l1.begin();cout << *pos << endl;//在pos位置之前插入值为5的元素l1.insert(pos, 5);Printlist(l1);//此时的pos位置还是指向2的位置cout << *pos << endl;//在pos位置前插入6个值为6的元素//insert(const_iterator position,size_t n,value_type& val)l1.insert(pos, 6, 6);Printlist(l1);//在pos位置插入一段迭代器指向的内容int array[] = { 7,8,9 };l1.insert(pos, array, array + (sizeof(array) / sizeof(int)));Printlist(l1);//删除pos位置上的值l1.erase(pos);Printlist(l1);//删除一段迭代器区间的值l1.erase(++l1.begin(), --l1.end());Printlist(l1);
}

运行结果:

2
1 5 2 3 4
2
1 5 6 6 6 6 6 6 2 3 4
1 5 6 6 6 6 6 6 7 8 9 2 3 4
1 5 6 6 6 6 6 6 7 8 9 3 4
1 4

swap和clear的使用:

//swap和clear
void test7()
{list<int> l1{ 1,2,3,4 };list<int> l2;Printlist(l1);Printlist(l2);//交换l1和l2的元素l1.swap(l2);Printlist(l1);Printlist(l2);//清空l2l2.clear();Printlist(l2);
}

运行结果:

1 2 3 41 2 3 4

2.6 list的迭代器失效

list底层结构为带头双向循环链表,因此在list中插入是不会导致迭代器失效的,只有在删除时才会失效,而且失效的只是被删除的节点处的迭代器,其他位置的迭代器不会被影响。

void test8()
{list<int> l1{ 1,2,3,4,5,6,7 };list<int>::iterator it = l1.begin();//while (it != l1.end())//{//	//当删除迭代器it位置上的元素后,it就已经失效了,接下来对it进行操作会导致报错//	l1.erase(it);//	it++;//}while (it != l1.end()){//因此要对it进行重新赋值it = l1.erase(it);}
}

三、list和vector的比较

vectorlist
底层结构动态顺序表,一段连续的空间带头结点的双向循环链表
随机访问支持随机访问,访问数据的效率为O(1)不支持随机访问,访问某个数据的效率为O(N)
插入和删除任意位置的插入和删除效率低,需要移动数据,效率为O(N),插入时可能会扩容,存在扩容的情况的话效率会更低任意位置插入和删除效率高,不需要搬移数据
空间利用率底层为连续空间,不存在空间碎片,空间利用率高,缓存利用率高底层节点动态开辟,小节点容易造成空间碎片,空间利用率低,缓存利用率低
迭代器原生态指针对原生态指针进行封装
迭代器失效插入需要扩容时迭代器会失效,删除任意位置元素时迭代器也会默认失效,删除时当前位置和后面的迭代器都会失效删除元素时迭代器会失效,但只是当前迭代器失效,其他位置的迭代器不受影响
使用场景需要高速缓存,支持随机访问,不需要考虑插入和删除效率的场景大量插入和删除,不考虑随机访问的场景

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

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

相关文章

重载和覆写有什么区别?

重载&#xff08;Overload&#xff09;和覆写&#xff08;Override&#xff0c;也叫重写 &#xff09;是面向对象编程中的重要概念&#xff0c;它们有以下区别&#xff1a; 定义 - 重载&#xff1a;在同一类中&#xff0c;允许存在多个方法名相同&#xff0c;但参数列表&#x…

flask 获取各种请求数据:GET form-data x-www-form-urlencoded JSON headers 上传文件

在 Flask 里&#xff0c;能使用多种方法获取不同类型的请求数据&#xff0c;下面详细介绍常见请求数据的获取方式。 获取查询字符串参数&#xff08;GET 请求&#xff09; 查询字符串参数一般在 URL 里&#xff0c;以 ?key1value1&key2value2 这种形式存在。可通过 requ…

人工智能助力工业制造:迈向智能制造的未来

在当今数字化转型的浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;技术正逐渐成为推动工业制造领域变革的核心力量。智能制造作为工业 4.0 的重要组成部分&#xff0c;通过将 AI 技术与传统制造工艺深度融合&#xff0c;正在重塑整个生产流程&#xff0c;提高生产效率、…

【java八股文】深入浅出synchronized优化原理

&#x1f50d; 开发者资源导航 &#x1f50d;&#x1f3f7;️ 博客主页&#xff1a; 个人主页&#x1f4da; 专栏订阅&#xff1a; JavaEE全栈专栏 synchronized优化原理 synchronized即使悲观锁也是乐观锁&#xff0c;拥有自适应性。 jvm内部会统计每个锁的竞争激烈程度&…

生成式 AI 的重要性

在科技飞速发展的今天,我们正站在一个前所未有的变革节点上。生成式 AI,宛如一颗突然划破夜空的耀眼流星,以其强大的创造力和无限的可能性,迅速成为全球瞩目的焦点。它究竟有何等魔力,能在如此短的时间内引发如此巨大的轰动?这背后又隐藏着怎样的时代密码,等待着我们去解…

生成式 AI 的阐释

在科技浪潮的汹涌推动下,一个全新的时代正以前所未有的速度向我们奔来,生成式 AI 无疑是这股浪潮中最耀眼的浪尖。它究竟是什么?又将如何重塑我们的世界?这不仅是科技爱好者们热衷探讨的话题,更是关乎每一个人未来发展的重要命题。 生成式 AI,从本质上来说,是一种能够自…

C++ 中 virtual 的作用

文章目录 1. 用于虚继承2. 用于抽象基类3. 用于多态 C 的 virtual 关键字&#xff0c;常见有 3 种用途&#xff1a;虚继承、抽象基类和多态。 1. 用于虚继承 virtual 用于虚继承时&#xff0c;主要是为了解决菱形继承中的重复继承同名成员问题。使用形式如下 class Derived:…

软件测试52讲学习分享:深入理解单元测试

课程背景 最近我在学习极客时间的《软件测试52讲》课程&#xff0c;这是由腾讯TEG基础架构部T4级专家茹炳晟老师主讲的认证课程。作为数字化转型与人工智能(DTAI)产业人才基地建设中心的认证课程&#xff0c;内容非常专业实用。今天想和大家分享第3讲"什么是单元测试&…

Java SE(7)——类和对象(二)

1.包(package) 1.1 包的定义 在Java中&#xff0c;包是一种用于组织和管理类&#xff0c;接口和其他包的机制。主要作用是防止命名冲突&#xff0c;并提供一种访问控制机制 1.2 package关键字 package关键字的主要作用是声明当前类在哪个包里面。 当然&#xff0c;用户也可以…

Manus联合创始人:公司产品基于Claude和阿里千问大模型开发

3月11日消息&#xff0c;日前&#xff0c;Manus官方在社交平台转发了公司联合创始人、首席科学家季逸超对Manus的技术解读&#xff0c;季逸超在评论区回复网友关于“Manus使用了哪一个基础大模型”这一问题时回复称&#xff0c;“我们用过Claude&#xff0c;也用过不同版本的Qw…

欺骗单页应用(SPA)渲染隐藏路由 -- trouble at the spa b01lersCTF

题目信息&#xff1a;I had this million-dollar app idea the other day, but I can’t get my routing to work! I’m only using state-of-the-art tools and frameworks, so that can’t be the problem… right? Can you navigate me to the endpoint of my dreams? 题目…

大数据引领行业革命:深度解析与未来趋势

📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 在信息化、数字化、智能化日益发展的今天,大数据技术已经成为推动产业变革的重要引擎。它不仅仅是一个技术工具,更是各行各业创新和优化的核心动力。无论是大企业还是初创公司,大数据的应用已经成为提升效…

[machine learning] Transformer - Attention (二)

本文介绍带训练参数的self-attention&#xff0c;即在transformer中使用的self-attention。 首先引入三个可训练的参数矩阵Wq, Wk, Wv&#xff0c;这三个矩阵用来将词向量投射(project)到query, key, value三个向量上。下面我们再定义几个变量&#xff1a; import torch inpu…

施磊老师rpc(三)

文章目录 mprpc框架项目动态库编译框架生成动态库框架初始化函数-文件读取1. 为什么要传入 argc, argv2. 读取参数逻辑3. 配置文件设计 init部分实现 mprpc配置文件加载(一)配置文件加载类成员变量主要方法**src/include/mprpcconfig.h** 配置文件**bin/test.conf** 实现配置文…

文献分享:通过简单的生物偶联策略将肽双特异性抗体(pBsAbs)应用于免疫治疗

背景 双特异性抗体是将单克隆抗体的两个不同抗原结合位点融合成一个单一实体的人工分子。它们已经成为一种很有前景的下一代抗癌治疗方法。尽管双特异性抗体的应用令人着迷&#xff0c;但双特异性抗体的设计和生产仍然繁琐而富有挑战性&#xff0c;导致研发过程漫长&#xff0…

二、shell脚本--变量与数据类型

1. 变量的定义与使用 定义变量&#xff1a;简单直接 在 Shell 里定义变量相当容易&#xff1a; 基本格式: variable_namevalue关键点 ❗&#xff1a;赋值号 的两边绝对不能有空格&#xff01;这绝对是初学者最容易踩的坑之一 &#x1f628;&#xff0c;务必留意&#xff01…

java_Lambda表达式

1、背景 lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。lambda表达式就和方法一样样&#xff0c;它提供了一个正常的参数列表和一个使用这些参数的主体&#xff08;body&#xff0c;可以是一个表达式和一个代码块&#xff09;。La…

给QCustomPlot添加一个QScrollBar滚动条、限制缩放范围、自动设置大小和右边栏垂直缩放

实现效果 实现思路 从QCustomPlot类派生一个类,进行个性化设置,在轴矩形的上边设置Margin,放一个滚动条,设置滚动条的样式 常量定义 #define NQSCRB 1000构造函数初始化 // 设置QScrollBar的样式// 顶部空--5,左侧空--6

实验-组合电路设计1-全加器和加法器(数字逻辑)

目录 一、实验内容 二、实验步骤 2.1 全加器的设计 2.2 加法器的设计 三、调试过程 3.1 全加器调试过程 2.加法器的调试过程 四、实验使用环境 五、实验小结和思考 一、实验内容 a) 介绍 在这次实验中&#xff0c;你将熟悉 Logisim 的操作流程&#xff0c;并且学习…

Linux进程控制与替换详解

进程创建 fork函数初识 在linux中fork函数是非常重要的函数,它从已存在进程中创建⼀个新进程。新进程为子进程,而原进程为父进程。 进程调用fork,当控制转移到内核中的fork代码后,内核做: • 分配新的内存块和内核数据结构给子进程 • 将父进程部分数据结构内容拷贝至…