【STL】:反向迭代器

朋友们、伙计们,我们又见面了,本期来给大家解读一下有关反向迭代器的模拟实现,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

目录

前言:

1. 基本构造

2. 接口完善

3. 在list中使用反向迭代器

list反向迭代器版本一:

list反向迭代器版本二: 

4. 在vector中使用反向迭代器 


前言:

前面的模拟实现vector和list中是没有实现反向迭代器的,反向迭代器与正向迭代器相比就是从数据的末端向前面访问遍历,但是两个迭代器的用法都是一样的,++就是下一个,*就可以访问到数据,但是它具体是怎么实现的呢?我们接下来看一看:

1. 基本构造

在list的模拟实现中讲解了如何实现正向迭代器(包含const版本和非const版本)那么在本期实现反向迭代器的时候就有了一定的前车之鉴,比如const版本和非const版本不需要实现两份代码,可以采用模板实现泛型编程。

反向迭代器的构造可以使用正向迭代器来进行复用,因为反向迭代器的++就是正向迭代器里面的--,所以在传递模板参数的时候可以直接传递一个迭代器,直接复用这个迭代器里面的各种结构完成反向迭代器的构造。这种方式叫做迭代器适配器。

#pragma oncenamespace ywh
{//反向迭代器template <class Iterator, class Ref, class Ptr>class ReverseIterator{public:typedef ReverseIterator<Iterator, Ref, Ptr> Self;//构造ReverseIterator(Iterator it):_it(it){}private:Iterator _it;};
}

2. 接口完善

反向迭代器的接口有++、--、*、->、!=、==,这些接口的实现都是可以通过使用模板参数中的迭代器来进行复用即可。

头文件: reverse_iterator.h

#pragma oncenamespace ywh
{//反向迭代器template <class Iterator, class Ref, class Ptr>class ReverseIterator{public:typedef ReverseIterator<Iterator, Ref, Ptr> Self;//构造ReverseIterator(Iterator it):_it(it){}//前置//operator++Self& operator++(){//复用传过来的迭代器里面的operator----_it;return *this;}//operator--Self&operator++(){++_it;return *this;}//operator*Ref operator*(){return *_it;}//operator->Ptr operator->(){return _it.operator->();}//operator==bool operator==(const Self& s){return _it == s._it;}//operator!=bool operator!=(const Self& s){return _it != s._it;}private:Iterator _it;};
}

3. 在list中使用反向迭代器

要使用反向迭代器,首先得在list头文件中包含以下反向迭代器的头文件,然后进行构造:

list反向迭代器版本一:

#pragma once
#include "reverse_iterator.h"
namespace ywh
{//链表结构template<class T>struct list_node{T _data;                 //节点中的数据list_node<T>* _prev;    //指向前一个节点的指针list_node<T>* _next;    //指向后一个节点的指针//构造list_node(const T& x = T()):_data(x), _prev(nullptr), _next(nullptr){}};//正向迭代器//   类型模板参数   传递引用      传递指针template<class T, class Ref, class Ptr>struct __list_iterator{typedef list_node<T> Node;typedef __list_iterator<T, Ref, Ptr> self;Node* _node;//迭代器构造__list_iterator(Node* node):_node(node){}//前置//operator++self& operator++(){_node = _node->_next;return *this;}//operator--self& operator--(){_node = _node->_prev;return *this;}//后置self operator++(int){self* tmp(_node);_node = _node->_next;return tmp;}//operator--self operator--(int){self* tmp(_node);_node = _node->_prev;return tmp;}//operator*Ref operator*(){return _node->_data;}//operator->Ptr operator->(){return &_node->_data;}//operator!=bool operator!=(const self& s){return _node != s._node;}//operator==bool operator==(const self& s){return _node == s._node;}};//list结构template<class T>class list{public:typedef list_node<T> Node;typedef __list_iterator<T, T&, T*> iterator;   //非const迭代器typedef __list_iterator<T, const T&, const T*> const_iterator;  //const迭代器typedef ReverseIterator<iterator, T&, T*> reverse_iterator;   //反向迭代器typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;   //反向迭代器public:基本构造/////...///正向迭代器iterator begin(){return iterator(_head->_next); //使用匿名对象进行构造}iterator end(){return iterator(_head);}const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}//反向迭代器/reverse_iterator rbegin(){return reverse_iterator(--end());}reverse_iterator rend(){return reverse_iterator(end());}const_reverse_iterator rbegin() const{return const_reverse_iterator(--end());}const_reverse_iterator rend() const{return const_reverse_iterator(end());}///修改相关接口//...private:Node* _head;  //链表的头节点size_t _size; //节点个数};
}

list反向迭代器版本二: 

我们也可以看一下库里面list的反向迭代器如何设计:

可以看到库里面的玩法是一种对称的结构,这种对称的结构在解引用访问时访问的是下一个节点的元素,这样子写是比较好理解的,正向的起始就是反向的结束,正向的结束就是反向的起始,那么我们也可以来按照这种写法来写一下:

头文件:reverse_iterator.h

#pragma once
namespace ywh
{//反向迭代器template <class Iterator, class Ref, class Ptr>class ReverseIterator{public:typedef ReverseIterator<Iterator, Ref, Ptr> Self;//构造ReverseIterator(Iterator it):_it(it){}//前置//operator++Self& operator++(){//复用传过来的迭代器里面的operator----_it;return *this;}//operator--Self&operator++(){++_it;return *this;}//operator*Ref operator*(){Iterator cur = _it;//返回下一个节点的数据return *(--cur);}//operator->Ptr operator->(){return _it.operator->();}//operator==bool operator==(const Self& s){return _it == s._it;}//operator!=bool operator!=(const Self& s){return _it != s._it;}private:Iterator _it;};
}

头文件:List.h

#pragma once
#include "reverse_iterator.h"
namespace ywh
{//链表结构template<class T>struct list_node{T _data;                 //节点中的数据list_node<T>* _prev;    //指向前一个节点的指针list_node<T>* _next;    //指向后一个节点的指针//构造list_node(const T& x = T()):_data(x), _prev(nullptr), _next(nullptr){}};//正向迭代器//   类型模板参数   传递引用      传递指针template<class T, class Ref, class Ptr>struct __list_iterator{typedef list_node<T> Node;typedef __list_iterator<T, Ref, Ptr> self;Node* _node;//迭代器构造__list_iterator(Node* node):_node(node){}//前置//operator++self& operator++(){_node = _node->_next;return *this;}//operator--self& operator--(){_node = _node->_prev;return *this;}//后置self operator++(int){self* tmp(_node);_node = _node->_next;return tmp;}//operator--self operator--(int){self* tmp(_node);_node = _node->_prev;return tmp;}//operator*Ref operator*(){return _node->_data;}//operator->Ptr operator->(){return &_node->_data;}//operator!=bool operator!=(const self& s){return _node != s._node;}//operator==bool operator==(const self& s){return _node == s._node;}};//list结构template<class T>class list{public:typedef list_node<T> Node;typedef __list_iterator<T, T&, T*> iterator;   //非const迭代器typedef __list_iterator<T, const T&, const T*> const_iterator;  //const迭代器typedef ReverseIterator<iterator, T&, T*> reverse_iterator;   //反向迭代器typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;   //反向迭代器public:基本构造/////...///正向迭代器iterator begin(){return iterator(_head->_next); //使用匿名对象进行构造}iterator end(){return iterator(_head);}const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}//反向迭代器/reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}const_reverse_iterator rbegin() const{return const_reverse_iterator(end());}const_reverse_iterator rend() const{return const_reverse_iterator(begin());}///修改相关接口//...private:Node* _head;  //链表的头节点size_t _size; //节点个数};
}

4. 在vector中使用反向迭代器 

vector中的反向迭代器不建议使用上面的版本一,因为begin()和end()是传值返回,是临时对象,而临时对象具有常性,不好进行修改,所以还是比较建议使用这种对称的结构。

头文件:Vector.h

#pragma once
#include <assert.h>
#include "reverse_iterator.h"
namespace ywh
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;typedef ReverseIterator<iterator, T&, T*> reverse_iterator;typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;public:/正向迭代器iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}/反向迭代器/reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}const_reverse_iterator rbegin() const{return const_reverse_iterator(end());}const_reverse_iterator rend() const{return const_reverse_iterator(begin());}/基本构造/////...///容量//...///修改//...private:iterator _start = nullptr;   //起始位置iterator _finish = nullptr;  //有效数据位置iterator _end_of_storage = nullptr; //结束位置};
}

朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!   

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

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

相关文章

rabbitMQ的direct模式的生产者与消费者使用案例

消费者C1的RoutingKey 规则按照info warn 两种RoutingKey匹配 绑定队列console package com.esint.rabbitmq.work03;import com.esint.rabbitmq.RabbitMQUtils; import com.rabbitmq.client.Channel; import com.rabbitmq.client.DeliverCallback;/*** 消费者01的消息接受*/ p…

如何使用MybatisPlus进行数据分页显示

如何使用MybatisPlus进行数据的分页呢&#xff1f; 使用Mybatis Plus提供的分页插件来简化开发&#xff0c;在MybatisPlusInterceptor的拦截器中添加自动分页的PaginationInnerInterceptor拦截器&#xff0c;当前配置需要交给spring的bean管理&#xff0c;类上添加注解Configu…

目标检测 Faster RCNN全面解读复现

Faster RCNN 解读 经过R-CNN和Fast RCNN的积淀&#xff0c;Ross B. Girshick在2016年提出了新的Faster RCNN&#xff0c;在结构上&#xff0c;Faster RCNN已经将特征抽取(feature extraction)&#xff0c;proposal提取&#xff0c;bounding box regression(rect refine)&…

php聊天室通讯系统常用的接口对接函数 curl、file_get_contents()、WebSocket、消息队列

方法有&#xff1a; 1、HTTP请求&#xff0c;可以通过PHP的curl库或者file_get_contents()函数发送HTTP请求来与聊天室接口进行通信&#xff1b; 2、WebSocket协议&#xff0c;可以使用PHP的WebSocket库或者第三方库来与聊天室接口进行对接&#xff1b; 3、使用这些SDK或者包装…

GIT提交代码

1、从远端克隆master分支 git clone -b master ssh://git*** 2、创建开发分支 git checkout -b 209192_dev 3、在对应分支下更新代码 -f为强制更新&#xff0c;会覆盖本地 git pull -f origin 209192_dev:209192_dev git pull -f origin sit:sit git pull -f origin uat:uat 4、…

Nginx快速入门教程,域名转发、负载均衡

1.Nginx简介 Nginx是⽬前最流⾏的Web服务器&#xff0c; 最开始是由⼀个叫做igor的俄罗斯的程序员开发的&#xff0c; 2019年3⽉11⽇被美国的F5公司以6.7亿美元的价格收购&#xff0c; 现在Nginx是F5公司旗下的⼀款产品了。 2.Nginx的版本 Nginx开源版本主要分为两种&#x…

21、嵌套路由实战操作

1、创建内嵌子路由&#xff0c;你需要添加一个vue文件&#xff0c;同时添加一个与该文件同名的目录用来存放子视图组件。 2、在父组件&#xff08;.vue&#xff09;内增加用于显示子视图内容 新建文件 pages\index_id.vue 生成的对应路由 {path: "/",component: _…

电子病历编辑器源码(Springboot+原生HTML)

一、系统简介 本系统主要面向医院医生、护士&#xff0c;提供对住院病人的电子病历书写、保存、修改、打印等功能。本系统基于云端SaaS服务方式&#xff0c;通过浏览器方式访问和使用系统功能&#xff0c;提供电子病历在线制作、管理和使用的一体化电子病历解决方案&#xff0c…

产品经理不得不知道的电商API接口对接流程梳理

接口对接流程梳理 产品经理 知晓自己负责系统做什么&#xff0c;外接三方系统做什么。 系统对接产品经理实操步骤&#xff1a; ①与公司业务人员沟通&#xff0c;与系统对接方产品/技术描述业务场景&#xff0c;沟通发放接口文档材料 ②拿到材料之后电商API接口过多请对方…

武汉站--ChatGPT/GPT4科研技术应用与AI绘图及论文高效写作

2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车…

麒麟KYLINOS2303系统上禁用新功能介绍页面

原文链接&#xff1a;麒麟KYLINOS2303系统上禁用新功能介绍页面 hello&#xff0c;大家好啊&#xff0c;今天给大家带来一篇在麒麟KYLINOS2303系统上禁用新功能介绍页面的文章&#xff0c;在我们安装完系统登录后&#xff0c;会发现有新功能介绍这个界面&#xff0c;我们可以通…

《微信小程序开发从入门到实战》学习十六

第三章 开发第一个小程序 3.3 开发创建投票页面 3.3.2 修改模拟器中的启动页面 通过页面跳转的方式预览第二个页面内容不方便。 微信开发工具的工具栏有一个编译模式的设置&#xff1a; 选择“添加编译模式”&#xff0c; 加一个便于区分的名称&#xff0c;点击确定。 模拟…

PPT基础:编辑顶点

目录 编辑顶点对顶点的编辑对线段的编辑编辑顶点用法 编辑顶点 所在位置&#xff1a; 实质&#xff1a;是一种改变图像性质的操作 如何把一个圆形变成三角形&#xff1a;选中其中一个顶点&#xff0c;右键删除一个顶点&#xff1b;靠近某一条边&#xff0c;右键“拉伸弓形”即…

css实现原生form表单label必填选项红色*样式,以及js控制必填校验

文章目录 一、css实现原生form表单label必填选项红色*样式&#xff0c;以及js控制必填校验&#xff1f;二、实现方案参考原文 一、css实现原生form表单label必填选项红色*样式&#xff0c;以及js控制必填校验&#xff1f; 二、实现方案 1.css实现原生form表单label必填选项红色…

Centos(Linux)服务器安装Dotnet8 及 常见问题解决

1. 下载dotnet8 sdk 下载 .NET 8.0 SDK (v8.0.100) - Linux x64 Binaries 拿到 dotnet-sdk-8.0.100-linux-x64.tar.gz 文件 2. 把文件上传到 /usr/local/software 目录 mkdir -p /usr/local/software/dotnet8 把文件拷贝过去 mv dotnet-sdk-8.0.100-linux-x64.tar.gz /usr/loc…

【 OpenGauss源码学习 —— 列存储(update)】

列存储&#xff08;Insert&#xff09; 概述相关函数CStoreUpdate::ExecUpdate 函数JunkFilter 结构体CStoreInsert::BatchInsert 函数bulkload_rows::append_one_vector 函数bulkload_rows::append_in_column_orientation我函数 ExecVecUpdate 函数CStoreUpdate::EndUpdate 函…

Python3.7+PyQt5 pyuic5将.ui文件转换为.py文件、Python读取配置文件、生成日志

1.实际开发项目时&#xff0c;是使用Qt Designer来设计UI界面&#xff0c;得到一个.ui的文件&#xff0c;然后利用PyQt5安装时自带的工具pyuic5将.ui文件转换为.py文件&#xff1a; pyuic5 -o mywindow.py mywindow.ui #先是py文件名&#xff0c;再是ui文件名样式图 QT5 UI&am…

单链表相关面试题--1.删除链表中等于给定值 val 的所有节点

/* 解题思路&#xff1a;从头节点开始进行元素删除&#xff0c;每删除一个元素&#xff0c;需要重新链接节点 */ struct ListNode* removeElements(struct ListNode* head, int val) {if(head NULL)return NULL;struct ListNode* cur head;struct ListNode* prev NULL;while…

vulnhub靶机Presidential

靶机地址&#xff1a;https://download.vulnhub.com/presidential/Presidential.ova 主机发现 arp-scan -l 端口扫描 nmap --min-rate 10000 192.168.21.150 端口服务扫描 nmap -sV -sT -O -p80 192.168.21.150 漏洞扫描 nmap --scriptvuln -p80 192.168.21.150 只有一个端…

海康Visionmaster-环境配置:MFC 二次开发环境配置方法

1 新建 MFC 工程&#xff0c;拷贝 DLL:VM\VisionMaster4.0.0\Development\V4.0.0 \ComControl\bin\x64 下的所有拷贝到项目工程输出目录下&#xff0c;如下图所示&#xff0c;项目的输出路径是 Dll 文件夹。 2 通过配置 C目录和链接器的方式配置 VM 环境 2.1 C目录下添加附加…