【c++进阶[五]】list相关接口介绍及list和vector的对比

news2024/11/13 15:37:43

💓博主CSDN主页::Am心若依旧💓

⏩专栏分类c++从入门到精通⏪
🚚代码仓库:青酒余成🚚

🌹关注我🫵带你学习更多c++
  🔝🔝  

1.前言

本章重点

本章重点讲解list的接口函数的熟悉,并且讲解list迭代器失效的特性和迭代器的功能分类以及算法库函数中谁能用谁不能用,最后比较一下list和vector的优势和劣势

2.list的介绍

对上诉大致理解如下:

1.list是一种可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
2.list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立结点当中,在结点中通过指针指向其前一个元素和后一个元素。
3.list与forward_list非常相似,最主要的不同在于forward_list是单链表,只能进行单方向迭代。
与其他容器相比,list通常在任意位置进行插入、删除元素的执行效率更高。
4.list和forward_list最大的缺陷是不支持在任意位置的随机访问,其次,list还需要一些额外的空间,以保存每个结点之间的关联信息(对于存储的类型较小元素来说这可能是一个重要的因素)。

更加具体的学习可以参考如下链接:list - C++ Reference (cplusplus.com)

3.list的使用

构造函数

在这里主要介绍四种构造函数

1.是无参构造,一眼就能看懂。

2.构造n个值为val的双向链表。

3.迭代器区间构造。

4.用一个初始值构造,也称之为拷贝构造函数。

上述四个构造的方法都是以int为类型,也可以使用其他的类型。具体视情况而

list<int> l1;//无参构造
list<int> l2(10,5);//用10个5初始化链表

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

//拷贝构造函数
list<char> l4('a');//用一个字符来初始化

迭代器

list底层实现迭代器的不是指针,但是可以把他当成指针来理解。list中的迭代器在底层重新封装了*,->,++,--,!=,==这几个函数。这样我们就能够像vector那样的把迭代器当成指针来使用了

这四个函数在前面讲解string和vector的时候都讲过,就不过多的叙述了。

但是一定要搞清楚这几个函数分别指向什么位置,下面用一张图帮助大家理解

begin()和rend()指向的位置相同

end()和rbegin()指向的位置相同

迭代器来遍历链表

vector<int> vv{1,3,5,7,9,11,13,15};
list<int> l(vv.begin(),vv.end());

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

值得注意的是:这里用的是!=而没有使用等于,而在vector中使用的是<。这是为什么呢?

这是因为在list中元素都是不连续的,如果用<的话非常有可能是错误的。而在vector中由于空间都是连续的,地址前面的一定是比后面的小的。

同时还要注意的是:这里没有使用[]来进行读取元素的值,而是使用了解引用,那是因为list不能支持随机访问,只支持解引用来读取元素。


与容量相关的函数 

 

这四个都是常见的函数了。resize在list中使用的不多,就不拿出来介绍了,有想法的可以参考上面提供的网站自己阅读。

增删查改相关函数

这几个函数一看就知道什么意思了,就不多叙述

insert插入重点讲解

使用insert函数时可以使用在某个位置插入某个值,也可以在某个位置插入n个值,也可以在某个位置前面插入一段区间大小的值

#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
using namespace std;

int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	list<int>::iterator pos = find(lt.begin(), lt.end(), 2);
	lt.insert(pos, 9); //在2的位置插入9
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl; //1 9 2 3
	pos = find(lt.begin(), lt.end(), 3);
	lt.insert(pos, 2, 8); //在3的位置插入2个8
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl; //1 9 2 8 8 3
	vector<int> v(2, 7);
	pos = find(lt.begin(), lt.end(), 1);
	lt.insert(pos, v.begin(), v.end()); //在1的位置插入2个7
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl; //7 7 1 9 2 8 8 3
	return 0;
}

注: find函数是头文件“algorithm”当中的一个函数,该函数在指定迭代器区间寻找指定值的位置,并返回该位置的迭代器

erase函数

list当中的erase函数支持两种删除方式:

  1. 删除指定迭代器位置的元素。
  2. 删除指定迭代器区间(左闭右开)的所有元素。
#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
using namespace std;

int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);
	list<int>::iterator pos = find(lt.begin(), lt.end(), 2);
	lt.erase(pos); //删除2
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl; //1 3 4 5
	pos = find(lt.begin(), lt.end(), 4);
	lt.erase(pos, lt.end()); //删除4及其之后的元素
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl; //1 3
	return 0;
}

clear函数

清空双向链表中除了头结点以外的所有节点

vector<int> vv{1,5,10,15,20,100,120};
list<int> ll(vv.begin(),vv.end());
auto pos = find(ll.begin(),ll.end(),20);
ll.insert(pos,250);
ll.erase(ll.begin()+2);
ll.clear();

clear之后就会把所有的值全部清空。(除了头结点之外,头结点可以把他理解为哨兵卫,里面的值无效)。

4.关于迭代器的问题

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

list迭代器失效只在erase删除时才会发生

erase删除的位置在空间上是唯一的,这个位置的数据被删除后,只是改变了数据的链接关系,然而此位置已经不在原先的链表中了,再次使用会出错!

例如你删除了最后一个元素位置的值,你再对最后一个元素的迭代器位置进行解引用,那么就会报错。这就是迭代器失效的问题

因此在设计删除erase函数的时候,每当删除一个位置的时候,他都会给你返回一个有效元素的位置。

举个例子,你要把所有的偶数全部删除。按照如下的方法写就不会出现问题了。

list<int> ll{1,2,3,4,5,6,7,8};
auto it=ll.begin();
while(it!=ll.end())
{
	if((*it)%2==0)
	{
		it=erase(it);
	}
	else
	{
		it++;
	}
}

5.各种迭代器的介绍

迭代器从功能可以大体分为三种:

  1. 正向迭代器: forward_iterator
  2. 双向迭代器: bidirectional_iterator
  3. 随机迭代器: random_iterator

他们分别支持++,++、--,++和--以及+和-

常见的容器以及它们的迭代器类型:

结论:

  1. 若函数模板给的随机迭代器
    则只能传有随机迭代器的容器

  2. 若函数模板给的双向迭代器
    则可以传有随机或者双向迭代器的容器

  3. 若函数模板给的单向迭代器
    则三种迭代器都可以传进来!

可以看出迭代器的优先级是:单向,双向,随机。分别依次向前兼容

6.vector与list的对比

好啦,list的相关接口就介绍到这里了,本篇文章主要介绍的是博主认为比较重要的接口,其他接口可以去下面网站自行阅读。

list::insert - C++ Reference (cplusplus.com)

                                下期预告:list的模拟实现

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

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

相关文章

W11系统电脑便捷设置

1【win11】取消右键菜单“更多选项”&#xff0c;直接展示完整右键菜单 取消右键菜单“更多选项”&#xff0c;直接展示完整右键菜单 (本质上是修改注册表&#xff0c;通过命令行的方式更加直接快捷) 只需要使用 winR 输入cmd 打开命令行&#xff0c;然后输入以下指令&#xf…

使用ChatGPT润色论文的10大分步技巧,效果立竿见影

大家好,感谢关注。我是七哥,一个在高校里不务正业,折腾学术科研AI实操的学术人。关于使用ChatGPT等AI学术科研的相关问题可以和作者七哥(yida985)交流,多多交流,相互成就,共同进步,为大家带来最酷最有效的智能AI学术科研写作攻略。 撰写学术论文确实是一项非常具有挑…

HTML 转 PDF API 接口

HTML 转 PDF API 接口 网络工具 / 文件处理 支持网页转 PDF 高效生成 PDF / 提供永久链接。 1. 产品功能 超高性能转换效率&#xff1b;支持将传递的 HTML 转换为 PDF&#xff0c;支持转换 HTML 中的 CSS 格式&#xff1b;支持传递网站 URL&#xff0c;直接转换页面成对应的 …

C++笔记20•数据结构:哈希(Hash)•

哈希 1.无序的关联式容器&#xff08;unordered_map&unordered_set&#xff09; unordered_map与unordered_set几乎与map与set是一样的&#xff0c;只是性能unordered_map与unordered_set比map与set更优一些。还有就是unordered_map与unordered_set是无序的&#xff0c;…

梳理2024年,螺丝钉们爱用的3款剪辑软件

这年头&#xff0c;视频到处都是&#xff0c;就跟天上的星星一样数不清。不管你是公司里的新面孔&#xff0c;还是职场上的老狐狸&#xff0c;学会怎么剪视频&#xff0c;就好比找到了赢的秘诀。不管是给上司汇报工作&#xff0c;展示你的产品&#xff0c;还是自己搞点小视频记…

C#顺序万年历自写的求余函数与周位移算法

static int 返回月的天数(int 年, int 月){return (月 2 ?(((年 % 4 0 && 年 % 100 > 0) || 年 % 400 0) ? 29 : 28) :(((月 < 7 && 月 % 2 > 0) || (月 > 7 && 月 % 2 0)) ? 31 : 30));}static int 返回年总天数(int 年, int 标 …

Mac设置文件夹的显示方式:独立窗口显示或者标签页显示

目录 00 Mac文件夹的两种显示方式  0.1 独立窗口显示   0.2 标签页显示 01 独立窗口显示  02 标签页显示 00 Mac文件夹的两种显示方式 0.1 独立窗口显示 0.2 标签页显示 01 独立窗口显示 系统偏好设置System Setting -> 程序坞Desktop & Dock -> 窗口W…

【一文读懂】北斗卫星导航系统介绍

前言 本文来自鲜枣课堂。 本文是关于北斗卫星导航系统的详细介绍&#xff0c;主要阐述了北斗系统的组成、功能、发展历程以及在全球范围内的应用和影响。以下是文件的核心内容提炼&#xff1a; 系统概述&#xff1a; 二级要点关键短语&#xff1a;全球卫星导航系统 北斗卫星…

Learn ComputeShader 11 Star Glow Effect

这次要使用到顶点和片段着色器。同样是制作屏幕后处理效果。 下面是一开始的效果&#xff0c;只是一个循环播放的粒子系统。 我们首先要对源图像的亮部区域进行提亮&#xff0c;然后进行模糊添加光芒。然后进行混合&#xff0c;最后进行一次合成 我们需要创建一些临时纹理来存…

基于Java+SpringBoot+Vue+MySQL的智能菜谱推荐管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于SpringBootVue的智能菜谱推荐管理系统【附源码文档】、…

ML18_EM(Expectation-Maximization)算法详解

1. 梯度上升法和坐标上升法的比较 “梯度上升法”&#xff08;Gradient Ascent Method&#xff09;和“坐标上升法”&#xff08;Coordinate Ascent Method&#xff09;都是优化算法的一部分&#xff0c;用于求解优化问题中的最大值。它们分别基于不同的思路来更新参数以达到目…

51单片机的倒车雷达测距设计【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块温度传感器模块超声波模块按键等模块构成。适用于倒车雷达测距、超声波测距、汽车防撞报警等相似项目。 可实现功能: 1、LCD1602实时显示环境温度和距离&#xff1b; 2、温度传感器DS18B20采集温度信息&#xff1…

【扇贝编程】使用Selenium模拟浏览器获取动态内容笔记

文章目录 selenium安装 selenium下载浏览器驱动 获取数据处理数据查找一个元素查找所有符合条件的元素 控制浏览器 selenium selenium是爬虫的好帮手&#xff0c; 可以控制你的浏览器&#xff0c;模仿人浏览网页&#xff0c;从而获取数据&#xff0c;自动操作等。 我们只要让…

Bitvise——进入服务器的快捷方式

第一步&#xff1a;在连接进服务器后&#xff0c;点击左侧的保存配置文件&#xff0c;保存至桌面。 第二步&#xff1a;将保存的配置文件&#xff08;后缀为 .tlp&#xff09;打开方式改为bitvise。 第三步&#xff1a;双击配置文件&#xff08;后缀为 .tlp&#xff09;&#…

Redis Sentinel(哨兵)详解

目录 一&#xff1a;什么是Sentinel&#xff08;哨兵&#xff09; 二&#xff1a;Sentinel有什么用 1.监控 2.故障转移 3通知 4.配置提供 三&#xff1a;Sentinel如何检测master节点宕机 1.主观下线 2.客观下线 四&#xff1a;Sentinel是如何选举出新的master 1.s…

树莓派3B串口通信

树莓派3B串口通信 文章目录 树莓派3B串口通信一、串口的基本认知1.1 关于电器标准和协议&#xff1a;RS232RS422RS485 1.2 关于串口的电平&#xff1a;UARTRS232电平TTL电平 1.3 串口通信引脚接线&#xff1a;1.4 串口的通信协议&#xff1a; 二、树莓派串口通信开发2.1 树莓派…

乐凡北斗 | 手持北斗智能终端的作用与应用场景

在科技日新月异的今天&#xff0c;北斗智能终端作为一项融合了北斗导航系统与现代智能技术的创新成果&#xff0c;正悄然改变着我们的生活方式和工作模式。 ​北斗智能终端&#xff0c;是以北斗卫星导航系统为核心&#xff0c;集成了高精度定位、导航、授时等功能的智能设备。它…

JavaEE:多线程进阶(JUC [java.util.concurrent] 的常见类)

文章目录 JUC什么是JUCCallable 接口理解 Callable理解FutureTask ReentrantLock信号量 SemaphoreCountDownLatch JUC 什么是JUC JUC的全称为: java.util.concurrent. JUC是Java并发工具包的一部分。它提供了一组并发编程工具和类&#xff0c;用于处理多线程编程和并发任务。…

SprinBoot+Vue校园数字化图书馆系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

Linux 操作系统 进程(1)

什么是进程 想要了解什么是进程&#xff0c;或者说&#xff0c;为什么会有进程这个概念&#xff0c;我们就需要去了解现代计算机的设计框架(冯诺依曼体系)&#xff1a; 计算机从设计之初就以执行程序为核心任务&#xff0c;也就是运算器从内存中读取&#xff0c;也只从内存中…