【C++进阶】STL容器--list使用迭代器问题分析

目录

前言

1. list的基本使用

1.1 list构造函数

1.2 list迭代器

 1.3 list capacity

1.4 list元素访问

 1.5 list 修改操作

insert

erase

 swap

 resize

 clear

2. list失效迭代器问题

3. list使用算法库函数问题

 总结


前言

        list(链表)在C++中非常重要的容器,它本质是一个带头双向循环链表。本文的主要内容是介绍list的基本使用以及对list迭代器问题。

在这里插入图片描述

1. list的基本使用

 学习一种新的容器,首先我们需要先了解它的接口;

 在C++的STL标准库中,list是一个带头双向循环链表;

 list和vector不同,它不支持[ ]下标随机访问;

list是一个双向链表,它的元素在内存中不是连续存储的,因此并不需要像vector一样预留容量或者调整容量

1.1 list构造函数

 C++98中默认有4中构造函数:

 有四种构造方法:

  • 默认无参构造
list<int> lt1;//无参构造
  • n个val构造
list<int> lt2(10,0); // 10个0初始化
  •  迭代器区间构造
vector<int> v{1,2,3,4,5};
list<int> lt3(v.begin(),v.end());
  •  拷贝构造
list<int> lt4(10,0);
list<int> lt5(lt4);

 除此之外还有比较常用的初始值设定项列表构造;

  •  initializer list构造(初始值设定项列表构造)
list<int> lt = {1, 2, 3, 4, 5};

1.2 list迭代器

 list迭代器本质并不是指针,为了方便理解,可暂时将迭代器理解成一个指针,该指针指向list中的某个节点;

 这4个迭代器接口大家都很熟悉,但需要注意的是list中它们的指向;

  •  list迭代器遍历
list<int> lt = { 1, 2, 3, 4, 5 };
list<int>::iterator it = lt.begin();
while (lt.end() != it)
{
	cout << *it << ' ';
	it++;
}
  •  范围for遍历
for (auto e : lt)
{
	cout << e << ' ';
}

范围for循环确实是本质上是迭代器遍历,在执行时会被替换成迭代器;

注意:

         在使用list迭代器时,我们往往使用的是it!=l.end(),而不是it<l.end(),因为list空间并不连续,每个节点的地址都不同(无法确认大小关系),在string和vector中,空间是连续的,可以使用;

 1.3 list capacity

 

 使用操作较为简单,使用list对象即可调用:

lt.empty();
lt.size();

1.4 list元素访问

 

 使用操作较为简单,使用list对象即可调用:

lt.front();
lt.back();

 1.5 list 修改操作

这里我们可以参考cplusplus上边的接口;

 这里我就介绍一些比较常用的,其他的接口使用可以去查阅;

头插、头删、尾插、尾删我就不再详细介绍;注意这些操作只能插入删除一个元素!

assign接口功能是新元素替换列表中的内容,它的功能我们完全可以使用list的构造函数替代,这里不再详细介绍;

insert

 

  •  使用单个值插入
list<int> mylist = {1, 2, 3, 4, 5};
auto it = mylist.begin();
it++; // 将迭代器it移动到第二个位置
mylist.insert(it, 10); // 在it位置插入值为10的元素
  • 使用相同值填充插入
list<int> mylist = {1, 2, 3, 4, 5};
auto it = mylist.begin();
it++; // 将迭代器it移动到第二个位置
mylist.insert(it, 3, 10); // 在it位置插入3个值为10的元素
  • 迭代器区间插入
list<int> mylist = {1, 2, 3, 4, 5};
auto it = mylist.begin();
it++; // 将迭代器it移动到第二个位置
vector<int> vec = {7, 8, 9};
mylist.insert(it, vec.begin(), vec.end()); // 在it位置插入vector中的元素
erase

 

  •  删除单个元素
list<int> mylist = {1, 2, 3, 4, 5};
auto it = mylist.begin();
it++; // 将迭代器it移动到第二个位置
mylist.erase(it); // 删除it位置的元素
  • 删除范围内的元素:
list<int> mylist = {1, 2, 3, 4, 5};
auto it1 = mylist.begin();
auto it2 = mylist.begin();
advance(it1, 1); // 将迭代器it1移动到第二个位置
advance(it2, 3); // 将迭代器it2移动到第四个位置
mylist.erase(it1, it2); // 删除从it1到it2范围内的元素

 注意list迭代器不支持使用+或-的操作来进行移动;所以这里使用advance函数来移动迭代器;

 swap

swap函数交换两个list的内容:

list<int> list1 = {1, 2, 3};
list<int> list2 = {4, 5, 6};
list1.swap(list2); // 交换list1和list2的内容
 resize

 resize函数调整list的大小:

list<int> mylist = {1, 2, 3, 4, 5};
mylist.resize(3); // 将mylist的大小调整为3,删除多余的元素
mylist.resize(5, 100); // 将mylist的大小调整为5,多出的元素用100填充

 list没有reserve接口

 clear

clear函数清空list的内容:

list<int> mylist = {1, 2, 3, 4, 5};
mylist.clear(); // 清空mylist的内容,mylist现在为空

2. list失效迭代器问题

         前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,list的底层结构为带头结点的双向循环链表,在list中进行插入时是不会导致list的迭代
器失效;

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

删除节点后,节点的数据就会被释放,再使用迭代器访问这个节点,此时节点已经失效;

前边我们也提到过,可以通过返回值的方法来避免迭代器的非法访问;

 节点被删除后,自动返回下一个位置的迭代器;

3. list使用算法库函数问题

 如果要对链表进行排序呢?

其实list自己封装的有sort接口,list链表的sort函数使用的是归并排序算法;那它为什么不用算法库里的sort;

原因很简单,其实就是迭代器不兼容;

 算法库里的sort它的参数是RandomAccessIterator,也就是随机访问迭代器;

这里就要补充一点知识,从不同容器的迭代器出发,容器不同迭代器实现也不同,那么迭代器的特性也不同;

根据迭代器的特性大致可以先分为三类: 

  • 单向迭代器(Forward Iterator) 
  • 双向迭代器(Bidirectional Iterator)
  • 随机访问迭代器(Random Access Iterator)

 单向迭代器: 迭代器仅++操作,单链表

 双向迭代器:迭代器支持++、--操作,双向链表

 随机访问迭代器:迭代器支持++/--/+/-操作,vector、string

 怎么分辨是否可以使用算法接口?

单向迭代支持++操作,满足所有迭代器的操作,三种类型的迭代器类型接口函数都可以使用;

 双向迭代器支持++/--操作,满足随机访问迭代器的操作,那它就可以使用参数类型为双向迭代器类型的接口函数,参数类型为随机访问迭代器类型的接口;

它就有向上兼容的特性;

 总结:

  • 单向迭代器可以使用三种迭代器类型的接口;
  • 双向迭代器可以使用:双向迭代器、随机迭代器类型的接口;
  • 随机迭代器仅可以使用随机迭代器类型的接口;

 虽然list自己实现的有sort接口,但还是不建议使用,它的效率非常的低;

它甚至还没有这样操作的速度快:

将list数据拷贝到vector中排序,然后将排序好的数据拷贝回list;


 总结

         本文主要介绍的是list的一些基本使用,以及list迭代器问题和list使用算法库函数的问题。list的接口函数不多,但是在使用算法库函数时需要注意迭代器的类型;以上便是本期的全部内容,希望对你有所帮助,感谢阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分享7种SQL的进阶用法

分享7种SQL的进阶用法 前言 还只会使用SQL进行简单的insert、update、detele吗&#xff1f;本文给大家带来7种SQL的进阶用法&#xff0c;让大家在平常工作中使用SQL简化复杂的代码逻辑。 1.自定义排序&#xff08;ORDER BY FIELD&#xff09; 在MySQL中ORDER BY排序除了可以…

vue模拟聊天页面列表:滚动到底部,滚动到顶部触发加载更多

先看下效果&#xff1a; 代码&#xff1a; <template><div><div style"text-align: center"><button click"scrollTop">滚动到顶部</button><button click"scrollBottom">滚动到底部</button></d…

GitHub Copilot 与 ChatGPT:哪种工具更适合软件开发?

GitHub Copilot 与 ChatGPT&#xff1a;哪种工具更适合软件开发&#xff1f; 比较 ChatGPT 与 GitHub Copilot编程语言功能性定制化训练数据上下文准确性 ChatGPT 与 GitHub Copilot&#xff1a;哪个更适合软件开发&#xff1f;常见问题解答&#xff1a; 不断发展的编程世界正在…

基数排序算法

1. 排序算法分类 十种常见排序算法可以分为两大类&#xff1a; 比较类排序&#xff1a; 通过比较来决定元素间的相对次序&#xff0c;由于其时间复杂度不能突破O(nlogn)&#xff0c;因此也称为非线性时间比较类排序。比较类排序算法包括&#xff1a;插入排序、希尔排序、选择…

matlab绘图杂谈-stem函数和plot函数

出发点 今天在论文中看到一副这样的图&#xff0c;它既有曲线&#xff0c;又有点&#xff0c;并且对两者都添加了图例。三条曲线应该是用plot函数绘制的&#xff0c;而target哪个绿色的圆圈&#xff0c;我的理解是用stem函数绘制的。它只是1个点&#xff0c;并且没有竖线&…

Ps:可选颜色

可选颜色 Selective Color命令可以按指定的颜色&#xff08;范围&#xff09;进行单独的调整&#xff0c;且不会影响图像中的其他颜色。 Ps菜单&#xff1a;图像/调整/可选颜色 Adjustments/Selective Color Ps菜单&#xff1a;图层/新建调整图层/可选颜色 New Adjustment Laye…

Qt 基于海康相机 的视频标绘

需求&#xff1a; 基于 视频 进行 标注&#xff0c;从而进行测量。 曾经搞在线教育时&#xff0c;尝试在视频上进行文字或者图形的绘制&#xff0c;但是发现利用Qt widget 传sdk 句柄的方式&#xff0c;只能使用窗口叠加的方式&#xff08;Qt 基于海康相机的视频绘图_海康相…

【WPF.NET开发】WPF 中的 Layout

本文内容 元素边界框布局系统测量和排列子元素面板元素和自定义布局行为布局性能注意事项子像素渲染和布局舍入 本主题介绍 Windows Presentation Foundation (WPF) 布局系统。 了解布局计算发生的方式和时间对于在 WPF 中创建用户界面非常重要。 1、元素边界框 在 WPF 中构…

React中使用LazyBuilder实现页面懒加载方法一

前言&#xff1a; 在一个表格中&#xff0c;需要展示100条数据&#xff0c;当每条数据里面需要承载的内容很多&#xff0c;需要渲染的元素也很多的时候&#xff0c;容易造成页面加载的速度很慢&#xff0c;不能给用户提供很好的体验时&#xff0c;懒加载是优化页面加载速度的方…

算法基础之树状数组

文章目录 树状数组 树状数组 树状数组能解决的最关键的问题就是能够 O ( log ⁡ n ) O(\log n) O(logn)内&#xff0c;给某个位置上的数&#xff0c;加上一个数&#xff0c;或者求前缀和 他和前缀和数组的区别就是&#xff0c;树状数组支持修改原数组的内容&#xff0c;而前缀…

前端学习之——react篇(渲染列表)

你将依赖 JavaScript 的特性&#xff0c;例如 for 循环 和 array 的 map() 函数 来渲染组件列表。 假设你有一个产品数组&#xff1a; const products [{ title: Cabbage, id: 1 },{ title: Garlic, id: 2 },{ title: Apple, id: 3 }, ]; 在你的组件中&#xff0c;使用 map…

视频尺寸魔方:分层遮掩3D扩散模型在视频尺寸延展的应用

▐ 摘要 视频延展(Video Outpainting)是对视频的边界进行扩展的任务。与图像延展不同&#xff0c;视频延展需要考虑到填充区域的时序一致性&#xff0c;这使得问题更具挑战性。在本文中&#xff0c;我们介绍了一个新颖的基于扩散模型的视频尺寸延展方法——分层遮掩3D扩散模型(…

linux conda 配置 stable video diffusion

安装教程 1 下载仓库源码 git clone https://github.com/Stability-AI/generative-models.git2 创建conda环境 conda create -n svd python3.10 conda activate svd3 安装pytorch gpu cuda和cudnn请参考其他链接配置&#xff0c;使用 conda 或者 pip 安装 pytorch # 使用c…

Linux 驱动开发基础知识——编写LED驱动程序(三)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

Vue开发之proxy代理的配置(附带uniapp代理配置)

vue 1.在vue.config.js中添加 devServer 属性中配置 proxy 属性 module.exports {productionSourceMap: false,publicPath: /,devServer: {port: 8085,proxy: {/api/admin: {target: http://10.58.104.70:6111,changeOrigin: true,pathRewrite: {/api/: /}},/api: {target: …

NIO-Channel详解

NIO-Channel详解 1.Channel概述 Channel即通道&#xff0c;表示打开IO设备的连接&#xff0c;⽐如打开到⽂件、Socket套接字的连接。在使⽤NIO时&#xff0c;必须要获取⽤于连接IO设备的通道以及⽤于容纳数据的缓冲区。通过操作缓冲区&#xff0c;实现对数据的处理。也就是说…

从源头到成品:精酿啤酒原料的完整追踪

对于追求品质的Fendi Club啤酒来说&#xff0c;从源头到成品的完整原料追踪是确保其品质的关键。这种追踪不仅涉及原料的采购&#xff0c;还包括其在生产过程中的处理和产品的质量控制。下面&#xff0c;我们将详细探讨Fendi Club啤酒如何实现从源头到成品的完整原料追踪。 首先…

安全用电管理平台方案介绍——Acrelcloud-6000

安全用电管理平台是一个针对电力系统安全管理的平台&#xff0c;旨在提供对电力设备和用电行为进行监控、分析和管理的解决方案。该平台结合了物联网技术、数据分析和远程监控等技术手段&#xff0c;能够实时监测、分析和预警电力系统的安全状况&#xff0c;以便及时采取措施防…

电气火灾监控探测器的种类有哪些?

随着电力行业的快速发展&#xff0c;电气火灾的威胁也越来越突出。为了有效预防和及时发现电气火灾&#xff0c;电气火灾探测器成为了不可或缺的重要设备。本文将详细介绍电气火灾探测器的定义、工作原理、应用场景以及安装和维护方法&#xff0c;旨在帮助大家更好地了解和使用…

爬取第一试卷网高三数学试卷并下载到本地

import requests import re import os filename 试卷\\ if not os.path.exists(filename):os.mkdir(filename) url https://www.shijuan1.com/a/sjsxg3/list_727_1.html headers {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.…