List中的迭代器实现【C++】

List中的迭代器实现【C++】

  • 一. list的结构
  • 二. 迭代器的区别
  • 三. 迭代器的实现
    • i. 类的设计
    • ii. ++重载
    • iii. !=重载
    • iiii. begin()
    • iiiii. end()
    • iiiii. operator*
  • 四.测试
  • 五. const迭代器的实现
    • i. 实现
    • 5.2 优化实现

一. list的结构

其实按照习惯来说,应该要专门出一篇博客来写

list的模拟实现,但是其实list与vector以及string的主要区别在于迭代器的设计。

所以就偷个懒直接写迭代器的部分了。

这里先声明以下,我这里就是进行一下模拟实现,STL中的list的iterator虽然并不是这样实现的,但是实现逻辑和结构都大差不差

这里就先贴上list类的结构:

namespace list
{template<class T>struct list_node{list_node<T>* _prev;list_node<T>* _next;T _val;//节点的构造函数list_node(const T& val = T()):_prev(nullptr), _next(nullptr), _val(val){}};template<class T>class list{public:list(){//链表的默认构造list_node<T>* head = new list_node<T>;//初始化哨兵位_head = head;_head->_next = _head;_head->_prev = _head;_size = 0;}~list(){}private:list_node<T>* _head;};
}

这个其实和我们之前写的双向带头循环链表一样。

二. 迭代器的区别

迭代器的区别,落到实质问题上
还是容器与容器的区别,也就是vector与list的区别

vector中的iterator是这样去实现的。

首先:

typedef T* iterator;

这里先重命名

iterator begin(){return _start;}iterator end(){return _finish;}

随后直接设计end与begin的函数。

之后就能发现,范围for与迭代器能直接进行使用了。

因为我们实现vector指针的方法是直接将内置类型指针进行改名。

而内置类型指针支持++,所以可以直接运行程序了。
但我们想想list肯定就不支持这样的操作了

vector能这这样,是因为数据存储在内存空间中连续时,正好可以进行使用。

但是list的问题是,内存空间是不连续的
这样的话再用指针内部支持的++算法就不太合适了。

所以我们今天就是为了来模拟实现list的迭代器的实现。

首先的目标就是实现下面这个代码的跑动。

	list::list<int>::iterator it = l1.begin();while (it != l1.end()){std::cout << *it;++it;}

三. 迭代器的实现

我们首先来看,我们最难解决的问题就是it的前置++
因为vector和list最重要的问题就是运算的方式不一样。

那我们想要用我们自己的方式进行++。
这个时候就应该想到了我们模拟实现类的时候最常用的东西:重载运算符

重载运算符在哪里能用:自定义类型
所以我们这个时候应该自然而然的想到自己写一个类,来充当iterator
从而实现我们想要的++方式。

i. 类的设计

    template<class T>struct __list_iterator{list_node<T>* _node;__list_iterator(list_node<T>* node):_node(node){}};

基本上大致结构是这样。

其中list_node就是双链表的节点结构。(上面写过)

这里添加个typedef

        template<class T>class list{public:typedef __list_iterator<T> iterator;

这个typedef和vefctor的使用没有什么大区别了。

现在来专注实现上面代码的所有的重载即可

ii. ++重载

  __list_iterator<T>& operator++(){_node = _node->_next;return *this;}

这个就是我们以前写的双链表和单链表的部分了。

iii. !=重载

 bool operator!=(const __list_iterator<T>& node){return _node != node._node;}

iiii. begin()

注意:这里的end和begin都是在list中的

因为迭代器执行时,会在list中寻找begin和end

 iterator begin(){return iterator(_head->_next);}

这里我们需要返回的是迭代器的类型

所以需要调用一下迭代器的构造函数

iiiii. end()

 iterator end(){return _head;}

我们发现begin需要调用构造函数

但是这边end却没有调用

因为单参数的构造函数返回时
如果返回的类型和需要返回的类型不同
就会主动调用需要返回类型的构造函数进行转换

iiiii. operator*

 T& operator*(){return _node->_val;}

四.测试

这里就直接写一个push_back的方法

  void push_back(const T& val){insert(end(), val);}void insert(iterator pos, const T& val){list_node<T>* new_node = new list_node<T>(val);_size++;pos._node->_prev->_next = new_node;new_node->_prev = pos._node->_prev;new_node->_next = pos._node;pos._node->_prev = new_node;}

接下来进行测试即可

	list::list<int> l1;l1.push_back(1);l1.push_back(1);l1.push_back(1);l1.push_back(1);l1.push_back(1);list::list<int>::iterator it = l1.begin();while (it != l1.end()){std::cout << *it;++it;}

在这里插入图片描述
这里能发现程序完美执行了。

五. const迭代器的实现

我们在使用STL中自带的迭代器时

应该经常能用到const迭代器。

const_iterator

这里我们首先要清楚const_iterator实现的是什么:

我们清楚效果是:指向的内容不能修改,但是迭代器本身可以修改。

所以实现的类型就是const T* ptr

而不是T* const ptr

那我们要达成这种效果。
可以从函数的返回值上入手

平常使用函数时,基本上都是通过重载符*
来进行对应值的修改

 const T& operator*(){return _node->_val;}

那我们这样不就可以了吗。。

i. 实现

typedef __list_iterator<T>const_iterator;

这里在list中重命名一下。

    template<class T>struct __list_const_iterator{list_node<T>* _node;__list_const_iterator(list_node<T>* node):_node(node){}const T& operator*(){return _node->_val;}__list_const_iterator<T>& operator++(){_node = _node->_next;return *this;}bool operator!=(const  __list_const_iterator<T>& node){return _node != node._node;}};

之后再把这个类丢进去。

但是这样会发现,实现的太过繁杂了。

这里就来个优化版本。

5.2 优化实现

这里先直接上结果

list中的重命名:

 typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*>const_iterator;

具体实现:

    template<class T, class ref>struct __list_iterator{list_node<T>* _node;__list_iterator(list_node<T>* node):_node(node){}ref& operator*(){return _node->_val;}__list_iterator<T, ref, ptr>& operator++(){_node = _node->_next;return *this;}bool operator!=(const  __list_iterator<T, ref, ptr>& node){return _node != node._node;}};

这里是给模板新添加了一个参数。

从而实现const与普通的两种类型迭代器的实现。

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

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

相关文章

C语言精华题目锦集1

第一题 test.c文件中包括如下语句&#xff0c;文件中定义的四个变量中&#xff0c;是指针类型的是&#xff08;&#xff09;【多选】 #define INT_PTR int* typedef int* intptr; INT_PRT a,b; int_ptr c,d;A:a  B:b  C:c  D:d #define是宏定义&#xff0c;此时在程序中IN…

微信小程序:仅前端实现对象数组的模糊查询

效果 核心代码 //对数组进行过滤&#xff0c;返回数组中每一想满足name值包括变量query的 let result array.filter(item > { return item.name.includes(query); }); 完整代码 wxml <input type"text" placeholder"请输入名称" placeholder-styl…

ADFS 高可用配置 + NLB配置(Windows网络负载均衡)

ADFS 高可用配置 NLB配置&#xff08;Windows网络负载均衡&#xff09; ADFS安装配置NLB配置节点 TEST-ADFS-01 网络负载平衡配置节点 TEST-ADFS-02 网络负载平衡修改CRM配置 ADFS实现高可用负载均衡有两种&#xff0c;主要是在数据库的选择方式&#xff1a; windows自带的内…

如何安装Node.js? 创建Vue脚手架

1.进入Node.js官网&#xff0c;点击LTS版本进行下载 Node.js (nodejs.org)https://nodejs.org/en 2.然后一直【Next】即可 3.打开【cmd】,输入【node -v】注意node和-v中间的空格 查看已安装的Node.js的版本号&#xff0c;如果可以看到版本号&#xff0c;则安装成功 创建Vue脚手…

世微 升压恒压IC dc-dc转换器 充电器手持设备便携式产品 AP8660

AP8660是一款升压dc-dc转换器&#xff0c;内置MOS调节器&#xff0c;内部补偿&#xff0c;还可以最小6个外部组件&#xff0c;内部的软识启动功能可以降压涌入电流 AP8660 SOT23-6封装&#xff0c;可以为PCB提供节省空间 特点 可调输出&#xff0c;最高达到24W 内部固定PWM频…

leetcode-链表经典题

1.反转单链表 206. 反转链表https://leetcode.cn/problems/reverse-linked-list/这里我们使用创建一个变量cur来遍历原链表&#xff0c;再创建一个新节点newnode&#xff0c;首先使用一个循环来遍历原链表&#xff0c;cur为NULL是循环结束&#xff0c;每次进入循环将cur的下一…

2023数据结构期中测验-2023秋-计算机+未来网络专业

数据结构期中测验 选择题函数题6-1 求链式表的表长6-2 逆序数据建立链表6-3 删除单链表偶数节点6-4 求二叉树高度6-5 先序输出叶结点 为了防止不自觉的朝答案看去&#xff0c;特意用了明黄色字体&#xff0c;如下查看答案&#xff1a; 选择题 2-1 下述程序段的时间复杂度为&am…

Linux 部署Sentinel控制台

Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 1.版本选择 SpringCloudAlibaba SpringClo…

若依侧边栏添加计数标记效果

2023.11.13今天我学习了如何对若依的侧边栏添加技术标记的效果&#xff0c;如图&#xff1a; 我们需要用到两个页面&#xff1a; 先说子组件实现计数标记效果 1.item.vue <script> export default {name: MenuItem,functional: true,props: {icon: {type: String,defau…

深度学习 python opencv 实现人脸年龄性别识别 计算机竞赛

文章目录 0 前言1 项目课题介绍2 关键技术2.1 卷积神经网络2.2 卷积层2.3 池化层2.4 激活函数&#xff1a;2.5 全连接层 3 使用tensorflow中keras模块实现卷积神经网络4 Keras介绍4.1 Keras深度学习模型4.2 Keras中重要的预定义对象4.3 Keras的网络层构造 5 数据集处理训练5.1 …

【源码复现】图神经网络之PPNP/APPNH

目录 1、论文简介2、论文核心介绍2.1、现有方法局限2.2、PageRank&Personalized PageRank2.3、PPNP&APPNP 3、源码复现3.1、模型总体框架3.2、PPNP3.3、APPNP3.4、MLP(两层) 1、论文简介 论文题目——《PREDICT THEN PROPAGATE: GRAPH NEURAL NETWORKS MEET PERSONALI…

Spring Task定时任务框架

二十四、Spring Task 24.1 介绍 Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 定位&#xff1a;定时任务框架 作用&#xff1a;定时自动执行某段Java代码 为什么要在Java程序中使用Spring Task&#xff1f; 应用场景…

ACM练习——第一天

因为最近要去农大参加他们的算法邀请赛&#xff0c;然后赛制是ACM赛制的&#xff0c;所以我就直接很迷茫。 然后我就找到了牛客的ACM练习题&#xff0c;好好的练习一下ACM写法&#xff0c;而且我还要被迫写C&#xff0c;哭了。 开始钻研 1.从Java过度到C 题目源于牛客网&…

[工业自动化-14]:西门子S7-15xxx编程 - 软件编程 - STEP7 TIA博途是全集成自动化软件TIA portal快速入门

目录 一、TIA博途是全集成自动化软件TIA portal快速入门 1.1 简介 1.2 软件常用界面 1.3 软件安装的电脑硬件要求 1.4 入口 1.5 主界面 二、PLC软件编程包含哪些内容 2.1 概述 2.2 电机运动控制 一、TIA博途是全集成自动化软件TIA portal快速入门 1.1 简介 Siemens …

Java中的7大设计原则

在面向对象的设计过程中&#xff0c;首先需要考虑的是如何同时提高一个软件系统的可维护性和可复用性。这时&#xff0c;遵从面向对象的设计原则&#xff0c;可以在进行设计方案时减少错误设计的产生&#xff0c;从不同的角度提升一个软件结构的设计水平。 1、单一职责 一个类…

用于强化学习的置换不变神经网络

一、介绍 如果强化学习代理提供的输入在训练中未明确定义&#xff0c;则通常表现不佳。一种新方法使 RL 代理能够正常运行&#xff0c;即使受到损坏、不完整或混乱的输入的影响也是如此。 “大脑能够使用来自皮肤的信息&#xff0c;就好像它来自眼睛一样。我们不是用眼睛看&…

重磅发布 OpenAI 推出用户自定义版 ChatGPT

文章目录 重磅发布 OpenAI 推出用户自定义版 ChatGPT个人简介 重磅发布 OpenAI 推出用户自定义版 ChatGPT OpenAI 首届开发者大会 (OpenAI DevDay) 于北京时间 11 月 7 日凌晨 02:00 开始&#xff0c;大会上宣布了一系列平台更新。其中一个重要更新是用户可以创建他们自己的自定…

Spring Cloud学习(七)【Docker 容器】

文章目录 初识 DockerDocker 介绍Docker与虚拟机Docker架构安装 Docker Docker 基本操作镜像相关命令容器相关命令数据卷 Dockerfile 自定义镜像镜像结构Dockerfile DockerComposeDockerCompose介绍安装DockerCompose Docker镜像仓库常见镜像仓库服务私有镜像仓库 初识 Docker …

里氏代换原则

package com.jmj.principles.dmeo2.after;/*** 四边形接口*/ public interface Quadrilateral {double getLength();double getWidth();}package com.jmj.principles.dmeo2.after;/*** 长方形类*/ public class Rectangle implements Quadrilateral{private double length;priv…

WPF ToggleButton 主题切换动画按钮

WPF ToggleButton 主题切换动画按钮 仿造最近看到的html中的一个效果&#xff0c;大致思路是文章这样&#xff0c;感觉还可以再雕琢一下。 代码如下 XAML: <UserControl x:Class"WPFSwitch.AnimationSwitch"xmlns"http://schemas.microsoft.com/winfx/200…