C++中链表的底层迭代器实现
大家都知道在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;}};
以上就是今天的所有内容,希望大家会喜欢!!!
相关文章:
C++中链表的底层迭代器实现
大家都知道在C的学习中迭代器是必不可少的,今天我们学习的是C中的链表的底层迭代器的实现,首先我们应该先知道链表的底层迭代器和顺序表的底层迭代器在实现上有什么区别,为什么顺序表的底层迭代器更加容易实现,而链表的底层迭代器…...
3.5、matlab打开显示保存点云文件(.ply/.pcd)以及经典点云模型数据
1、点云数据简介 点云数据是三维空间中由大量二维点坐标组成的数据集合。每个点代表空间中的一个坐标点,可以包含有关该点的颜色、法向量、强度值等额外信息。点云数据可以通过激光扫描、结构光扫描、摄像机捕捉等方式获取,广泛应用于计算机视觉、机器人…...
Qt-事件与信号
事件和信号的区别在于,事件通常是由窗口系统或应用程序产生的,信号则是Qt定义或用户自定义的。Qt为界面组件定义的信号往往通常是对事件的封装,如QPushButton的clicked()信号可以看做对QEvent::MouseButtonRelease类事件的封装。 在使用界面组…...
数据结构 day3
目录 思维导图: 学习内容: 1. 顺序表 1.1 概念 1.2 有关顺序表的操作 1.2.1 创建顺序表 1.2.2 顺序表判空和判断满 1.2.3 向顺序表中添加元素 1.2.4 遍历顺序表 1.2.5 顺序表按位置进行插入元素 1.2.6 顺序表任意位置删除元素 1.2.7 按值进…...
Kubernetes面试整理-如何进行滚动更新和回滚?
在 Kubernetes 中,滚动更新和回滚是管理应用程序版本的常用操作。滚动更新允许您逐步替换现有的 Pod 实例,以便在不中断服务的情况下部署新版本。回滚则是在新版本出现问题时恢复到之前的版本。 滚动更新 通过 Deployment 进行滚动更新 1. 创建一个 Deployment: 下面是一个…...
flutter ios打包 xcode报错module ‘xxx‘ not found
flutter ios打包 xcode报错module ‘xxx’ not found 如果已经在androidstudio中成功运行了flutter build ios --release。 那么可能是你使用xcode打开的是ios/Runner.xcodeproj文件。 你关掉xcode,重新打开ios/Runner.xcworkspace/文件。然后重新archiveÿ…...
LLM 构建Data Multi-Agents 赋能数据分析平台的实践之④:数据分析之三(数据展示)
概述 在先前探讨的文章中,我们构建了一个全面的数据测试体系,该体系遵循“数据获取—数据治理—数据分析”的流程。如何高效地构建数据可视化看板,以直观展现分析结果,正逐渐成为利用新兴技术提升效能的关键领域。伴随业务拓展、数…...
Elasticsearch 批量更新
Elasticsearch 批量更新 准备条件查询数据批量更新 准备条件 以下查询操作都基于索引crm_flow_info来操作,索引已经建过了,本文主要讲Elasticsearch批量更新指定字段语句,下面开始写更新语句执行更新啦! 查询数据 查询指定shif…...
【Pytorch笔记】张量
torch.Tensor() 是 PyTorch 库中用于创建张量的一个函数。在 PyTorch 中,张量是多维数组,它们可以存储在 CPU 或 GPU 上,并且支持自动求导,这使得它们非常适合进行深度学习和科学计算。 张量可以在Python list形式下通过 torch.T…...
查找json中指定节点的值,替换为指定的值
有时我们封装好的实体转化成的json字段的值和第三方要求的不一样,比如我们字段的值是字符串,我们需要使用int类型的值,就需要将这个键的值转化成int类型。 比如将以下 convulsionNumber字段中字符串的值“一次”替换为0 {"convulsionT…...
Android 14 开机时间优化措施
Android开机优化系列文档-CSDN博客 Android 14 开机时间优化措施汇总-CSDN博客Android 14 开机时间优化措施-CSDN博客根据systrace报告优化系统时需要关注的指标和优化策略-CSDN博客Android系统上常见的性能优化工具-CSDN博客Android上如何使用perfetto分析systrace-CSDN博客A…...
【QGroundControl二次开发】二.使用QT编译QGC(Windows)
【QGroundControl二次开发】一.开发环境准备(Windows) 二. 使用QT编译QGC(Windows) 2.1 打开QT Creator,选择打开项目,打开之前下载的QGC项目源码。 编译器选择Desktop Qt 6.6.3 MSVC2019 64bit。 点击运…...
[C/C++入门][变量和运算]4、带余除法
给定被除数和除数,求整数商及余数 看到这个题,我们都知道C的除法运算符 /,默认是不带余数的。那现在要求带余数,需要能够想到% %,是C获取余数的方法:比如5/22; 5%21;%得到的是除后的余数。 #inc…...
常用优秀内网穿透工具(实测详细版)
文章目录 1、前言2、安装Nginx3、配置Nginx4、启动Nginx服务4.1、配置登录页面 5、内网穿透5.1、cpolar5.1.1、cpolar软件安装5.1.2、cpolar穿透 5.2、Ngrok5.2.1、Ngrok安装5.2.2、随机域名5.2.3、固定域名5.2.4、前后端服务端口 5.3、NatApp5.4、Frp5.4.1、下载Frp5.4.2、暴露…...
防火墙NAT地址转换和智能选举综合实验
一、实验拓扑 目录 一、实验拓扑 二、实验要求(接上一个实验要求后) 三、实验步骤 3.1办公区设备可以通过电信链路和移动链路上网(多对多的NAT,并且需要保留一个公网IP不能用来转换) 3.2分公司设备可以通过总公司的移动链路和电信链路访…...
Android获取当前屏幕显示的是哪个activity
在 Android 中,要获取当前屏幕显示的 Activity,可以使用以下几种方法: 方法一:使用 ActivityManager 获取当前运行的任务信息 这是一个常见的方法,尽管从 Android 5.0 (API 21) 开始,有些方法变得不太可靠…...
JVM:自动垃圾回收
文章目录 一、C/C的内存管理二、Java的内存管理1、方法去的回收2、堆回收(1)引用计数法和可达性分析法(2)五种对象引用(3)垃圾回收算法 一、C/C的内存管理 在C和C没有自动垃圾回收机制,一个对象…...
【填坑指南】PHP8报:Unable to load dynamic library ‘zip.so’ 错误
1.原因分析 这种情况多数发生在PHP安装时因为各种原因失败后,残余的库与最后安装的PHP版本不兼容导致的。 2.我的路径 一开始我按照以前摸索出来的安装PHP7.3的成功经验来编译方法安装PHP8.3,发现以前的套路已经失效了。反复重装PHP8.3失败后…...
鸿蒙语言基础类库:【@system.notification (通知消息)】
通知消息 说明: 从API Version 7 开始,该接口不再维护,推荐使用新接口[ohos.notification]。本模块首批接口从API version 3开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 导入模块 import notification fro…...
1.JavaWeb开发简介(Tomcat安装使用+Servlet简介)
文章目录 一.web开发简介1.概念:2.特点:3.常用技术:4.服务架构5.web应用开发模式6.HTTP协议1)概念:2)HTTP最基本的过程是:3)IP/域名4)HTTP协议请求方式 7.JavaWeb的相关技术8.Java Web服务器 二、安装配置Tomcat1.简介2.Tomcat目录结构 三.Servlet的入门应用1.使用步骤2.使用注…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
