C++中链表的底层迭代器实现

news2024/9/21 16:38:34

大家都知道在C++的学习中迭代器是必不可少的,今天我们学习的是C++中的链表的底层迭代器的实现,首先我们应该先知道链表的底层迭代器和顺序表的底层迭代器在实现上有什么区别,为什么顺序表的底层迭代器更加容易实现,而链表的底层迭代器不容易实现,接下来小编再来告诉大家如何来实现链表的底层迭代器,学完今天这篇我相信大家对C++中的迭代器一定会有一个更加深刻的认识!大家先看今天学习的内容:

一、顺序表和链表的底层迭代器的区别

为了知道它们两个的区别,先得告诉大家顺序表的底层迭代器是如何实现的,首先大家先得明白顺序表私有成员都有什么,好方便大家来理解它们的底层迭代器是如何实现的,请看下图顺序表的私有成员变量:

	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;

如图就是顺序表的私有成员变量 第一个 _start 是记录顺序表的起始位置的指针类型是 T*

_finish记录的是顺序表内末尾元素的下一个位置的指针类型是T*,_end_of_storage记录的是顺序表的目前的所有容量的下一个位置类型也是T*。

在明白了顺序表的私有成员变量的意义,并且顺序表的储存是连续的空间有点类似于数组的数据储存,所以大家也应该明白了顺序表的底层迭代器是如何实现的了吧,如果不懂请看下图操作及注释,如下图:

但是由于链表的物理结构不是连续的,所以想顺序表一样的底层迭代器实现方法是行不通的,这也是为什么在底层实现链表的迭代器中,不能通过给迭代器++来做到迭代器指向下一个元素的地址,因为链表的数据在空间中分布式随意的。那该如何去设计链表的底层迭代器呢,请大家继续往下看。

二、链表的底层迭代器该如何实现

首先先请大家看一下链表中的数据是如何分布的,如下图:

如图,可见链表中的数据是随意分布的,但是我们仍然可以用前一个节点找到下一个节点,但为什么这样子不行,不算迭代器呢,因为在C++中迭代器的定义就是通过 ++ 来找到下一个元素,接通过 * 号来拿到他这个位置的数据,这才是迭代器的规定,如下段代码的遍历效果:

如上链表的分布图,虽然我们可以拿到下一个节点的位置和这个节点的数据,但我们不是通过 ++ 和 * 来实现的,所以通过这样的方式做出的迭代器是不对的。那我们该如何实现呢,小编新学了一个方法,就是把迭代器底层封装成一个类,让它内部进项运算符重载来达到 ++ 实现像迭代器一样遍历的过程* 实现像迭代器一样拿出数据的过程,那么该如何实现呢,请大家继续往下看。

三、链表底层迭代器的实现

上面说到把迭代器封装成一个类,然后用运算符重载来达到 ++* 的过程,把它彻底改变为一个正规的迭代器,现在大家就和我一起实现这个迭代器的类:

1、首先大家要明白链表(带头双向循环链表)的结构,如下代码:

template<class T>
// 这里用结构体是因为ListNode中的每个成员都应该可以访问 没有私有成员
// 也可以使用友元来解决这个问题
struct ListNode
{
	T _data;
	ListNode* _next;
	ListNode* _prev;

	ListNode(const T& data = T())
		:_next(nullptr)
		,_prev(nullptr)
		, _data(data)
	{}
};
	template<class T>
	class list
	{
	public:
		typedef ListNode<T> Node;
	private:
		Node* _head;
	};

如上图代码,在这里我们已经知道下一步需要把链表独特的遍历方式(用前一个指针找到后一个指针)用运算符重载的改为 ++  来实现遍历和拿到数据,保证它和迭代器的实现和用法一模一样。那该如何实现这个类呢。

2、实现迭代器的类

我们需要定义一个迭代器的类,因为有普通迭代器和不可修改的迭代器,它们两个的函数大多数相同,为了减少代码量,我们加入两个模板参数来帮我们减轻代码量

	// 这里加入 Ref 和 Ptr 是为了区分普通迭代器和const迭代器的区别
	// 本来要写两份迭代器,一份可修改,一份不可修改 现在直接交给编译器去做
	template<class T , class Ref, class Ptr>
	struct ListIterator
	{
		typedef ListNode<T> Node;
		typedef ListIterator<T, Ref, Ptr> Self;

		// 链表的迭代器应该是 Node* 类型的指针
		Node* _node;

		ListIterator(Node* node)
			:_node(node)
		{}
		// 前置++
		Self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		//前置--
		Self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		Self operator++(int)
		{
			Self tem(*this);
			_node = _node->_next;
			return tem;
		}
		Self operator--(int)
		{
			Self tem(*this);
			_node = _node->_prev;
			return tem;
		}
		Ptr operator->()
		{
			return &(_node->_data);
		}
		Ref operator*()
		{
			return _node->_data;
		}
		bool operator!=(const Self& it)
		{
			return _node != it._node;
		}

		bool operator==(const Self& it)
		{
			return _node == it._node;
		}
	};

以上就是今天的所有内容,希望大家会喜欢!!!

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

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

相关文章

Ubuntu20.04 编译安装FFmpeg,出错分析以及解决方案

最近工程上需要对FFmpeg底层源码进行修改&#xff0c;需要重新编译&#xff0c;遇见不少坑&#xff0c;出篇教程记录一下。 文章目录 1.FFmpeg源码下载地址2.编译环境配置3.编译FFmpeg4.配置FFmpeg运行环境 1.FFmpeg源码下载地址 官方下载地址:Index of /releases (ffmpeg.or…

使用MovaXterm连接VMware的centos

一、确认局域网ip 检查虚拟机分配的网段是否一致 二、确认centos的ip 输入 ip addr 获得设备ip为192.168.153.130 三、用MovaXterm建立ssh连接 有同行可能会问&#xff0c;直接使用VMware操作centos系统不行吗&#xff1f;为什么要再多一步。 理由&#xff1a;1、测试环境c…

Zabbix6.0使用自带模板(MySQL by Zabbix agent 2)监控MySQL数据库

注意&#xff1a;Zabbix6.0使用MySQL by Zabbix agent 2 模板可直接监控MySQL数据库&#xff0c;只需要创建监控用户&#xff0c;模板宏中填写数据库账号信息即可&#xff0c;只需要3步&#xff0c;特简单&#xff01; 1、MySQL创建用户&#xff0c;用于收集数据库信息 creat…

HarmonyOS 界面开发基础篇

一、布局思路 ArkUI(方舟开发框架)是一套 构建 鸿蒙应用 界面 的框架。 构建页面的最小单位就是“组件”。 组件分类 基础组件&#xff1a;界面呈现的基础元素。 如&#xff1a;文字、图片、按钮等。容器组件&#xff1a;控制布局排布。 如&#xff1a;Row行、Column列等。…

MySQL篇:日志

前言 MySQL中常见的日志&#xff1a; 重做日志&#xff08;Redo Log&#xff09;&#xff1a; 用途&#xff1a; 保证事务的持久性&#xff0c;记录事务对数据库所做的所有修改。 内容&#xff1a; 记录事务对数据页的物理修改&#xff0c;而不是逻辑修改。 配置&#xff1a; …

一款IM即时通讯聊天系统源码,包含app和后台源码

一款IM即时通讯聊天系统源码 聊天APP 附APP&#xff0c;后端是基于spring boot开发的。 这是一款独立服务器部署的即时通讯解决方案&#xff0c;可以帮助你快速拥有一套自己的移动社交、 企业办公、多功能业务产品。可以 独立部署&#xff01;加密通道&#xff01;牢牢掌握通…

《C专家编程》杂谈

库函数调用和系统调用的区别 系统调用比函数调用要慢很多&#xff0c;因为还要切换到内核模式。

防火墙综合实验之NAT和智能选路

目录 前言&#xff1a; 一、实验题目 二、实验操作 需求一 需求二 需求三 需求四、需求五 需求六 需求七 ​编辑 需求八 需求九 需求十 需求十一 三、需求测试 前言&#xff1a; 本篇文章是延续上一篇文章&#xff0c;简单来说就是防火墙实验的完善和延续&#…

【CUDA】CUDA中缓存机制对计时的影响

笔者在阅读知乎上一个关于CUDA编程的专栏时&#xff0c;发现作者写的很多文章中都会附带计时的模块用于评估程序的运行效率&#xff0c;然而笔者发现&#xff0c;在运行这篇文章中的代码时时&#xff0c;得到的结果和作者的结果有较大差异&#xff0c;主要体现在&#xff1a;使…

《战甲神兵》开发者报告:游戏崩溃问题80%发生在Intel可超频酷睿i9处理器上——酷睿i7 K系列CPU也表现出高崩溃率

在Intel持续面临第13代和第14代CPU崩溃问题的背景下&#xff0c;近日&#xff0c;《战甲神兵》(Warframe)的开发者们于7月9日披露了游戏崩溃的统计数据&#xff0c;并描述了诊断该问题的过程。根据开发团队的说法&#xff0c;一名未进行超频且使用全新PC的员工&#xff0c;即便…

网络安全设备——EDR

网络安全中的EDR&#xff08;Endpoint Detection and Response&#xff0c;端点检测与响应&#xff09;是一种主动式的端点安全解决方案&#xff0c;它专注于监控、检测和响应计算机和终端设备上的安全威胁。以下是EDR的详细解释&#xff1a; 一、定义与功能 EDR是一种网络安…

【C++】入门基础(引用、inline、nullptr)

目录 一.引用 1.引用的定义 2.引用的特性 3.引用的使用场景 4.const引用 5.引用和指针的区别 二.inline 三.nullptr 一.引用 1.引用的定义 引用不是新定义一个变量&#xff0c;而是给已经存在的变量取一个别名&#xff0c;编译器不会给引用变量开辟内存空间&#xff0c…

(实测可用)(3)Git的使用——RT Thread Stdio添加的软件包,github与gitee冲突造成无法上传文件到gitee

★硬件资源&#xff1a;本文章以STM32L431RCT6做主控芯片做验证&#xff1b; ★IDE开发环境&#xff1a;RT Thread stdio&#xff1b; ★RT Thread 版本&#xff1a;V4.0.3 一、RT Thread Stdio加载软件包 1、如下图所示&#xff0c;通过RT Thread Stdio加载的软件包&#…

[FPGA]-时序传输模型分析

时序传输模型分析 FPGA内部时钟树 clk到达每个寄存器的时间不一致。 内部时钟树内部示意图如下所示&#xff1a; 在实际FPGA芯片内部&#xff0c;时钟到达每个寄存器的时钟偏差很小&#xff0c;但仍然存在&#xff1b;比如clk到达REG1花费时间0.2ns&#xff0c;到达REG6花费…

【Linux】基于环形队列RingQueue的生产消费者模型

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 环形队列的概念及定义 POSIX信号量 RingQueue的实现方式 RingQueue.hpp的构建 Thread.hpp Main.cc主函数的编写 Task.hpp function包装器的使用 总结 前言…

Torch-Pruning 库入门级使用介绍

项目地址&#xff1a;https://github.com/VainF/Torch-Pruning Torch-Pruning 是一个专用于torch的模型剪枝库&#xff0c;其基于DepGraph 技术分析出模型layer中的依赖关系。DepGraph 与现有的修剪方法&#xff08;如 Magnitude Pruning 或 Taylor Pruning&#xff09;相结合…

Python:setattr()函数和__setattr__()魔术方法

相关阅读 Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 setattr()是一个python内置的函数&#xff0c;用于设置一个对象的属性值&#xff0c;一般情况下&#xff0c;可以通过点运算符(.)完成相同的功能&#xff0c;但是getat…

[激光原理与应用-112]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 16 - 常见的产品指标

目录 一、光学传感器技术指标&#xff1a;实时信号采集与信号处理 &#xff08;1&#xff09;适用激光器的功率范围宽&#xff1a; &#xff08;2&#xff09;感光范围&#xff1a;350nm~1750nm&#xff1a;从可见光到红外光 &#xff08;3&#xff09;信号类型&#xff1a…

NSSCTF_RE(二)暑期

[CISCN 2021初赛]babybc LLVM是那个控制流平坦化混淆&#xff0c;bc是IR指令文件 得到64位elf文件 然后就慢慢分析&#xff0c;感觉太妙了我靠 一个数独游戏&#xff0c;用二个二维数组添加约束&#xff0c;一个二维数组作地图&#xff0c;慢慢看 最后用 z3 来解数独&#xf…

k8s快速部署一个网站

1&#xff09;使用Deployment控制器部署镜像&#xff1a; kubectl create deployment web-demo --imagelizhenliang/web-demo:v1 kubectl get deployment,pods[rootk8s-matser ~]# kubectl get pods NAME READY STATUS RESTARTS A…