C++的stack和queue类(三):适配所有容器的反向迭代器

目录

前言

list的反向迭代器 

list.h文件

ReverseIterator.h文件

test.cpp文件


前言

迭代器按性质分类:

  • 单向:forward_list
  • 双向:list
  • 随机:vector / deque

迭代器按功能分类:

  • 正向
  • 反向
  • const

list的反向迭代器 

问题:反向迭代器和正向迭代器的不同点在哪?

答:二者功能类似,只是++和--的方向不一样

基本概念:本来每个容器都要写一个反向迭代器的类,但是这样太费劲了,我们只需要写一个反向迭代器的类模板给编译器,传不同的容器的正向迭代器实例化,编译器帮助我们实例化出各种容器的对应反向迭代器

list.h文件

#pragma once
#include<assert.h>
#include"ReverseIterator.h"namespace bit
{template<class T>struct ListNode{ListNode<T>* _next;ListNode<T>* _prev;T _data;ListNode(const T& x = T()):_next(nullptr), _prev(nullptr), _data(x){}};//正向迭代器的类模板
///template<class T, class Ref, class Ptr>struct ListIterator{typedef ListNode<T> Node;// typedef ListIterator<T, T&, T*>// typedef ListIterator<T, const T&, const T*>typedef ListIterator<T, Ref, Ptr> iterator;Node* _node;ListIterator(Node* node):_node(node){}// *it//T& operator*()Ref operator*(){return _node->_data;}// it->//T* operator->()Ptr operator->(){return &_node->_data;}// ++ititerator& operator++(){_node = _node->_next;return *this;}iterator operator++(int){iterator tmp(*this);_node = _node->_next;return tmp;}iterator& operator--(){_node = _node->_prev;return *this;}iterator operator--(int){iterator tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const iterator& it){return _node != it._node;}bool operator==(const iterator& it){return _node == it._node;}};//list类模板
///template<class T>class list{typedef ListNode<T> Node;public://<容器类>typedef ListIterator<T, T&, T*> iterator;//正向迭代器的类模板typedef ListIterator<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;//const反向迭代器的类模板//普通反向迭代器(const没写)reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}iterator begin(){return _head->_next;}iterator end(){return _head;}// const迭代器,需要是迭代器不能修改,还是迭代器指向的内容?// 迭代器指向的内容不能修改!const iterator不是我们需要const迭代器// T* const p1// const T* p2const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}//C++11的initializer_listlist(initializer_list<T> il){empty_init();for (auto& e : il){push_back(e);}}// lt2(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}// 需要析构,一般就需要自己写深拷贝// 不需要析构,一般就不需要自己写深拷贝,默认浅拷贝就可以void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}// lt1 = lt3list<T>& operator=(list<T> lt){swap(lt);return *this;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}~list(){clear();delete _head;_head = nullptr;}/*void push_back(const T& x){Node* newnode = new Node(x);Node* tail = _head->_prev;tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;}*/void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void insert(iterator pos, const T& val){Node* cur = pos._node;Node* newnode = new Node(val);Node* prev = cur->_prev;// prev newnode cur;prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;_size++;}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;_size--;return iterator(next);}size_t size() const{return _size;}bool empty(){return _size == 0;}private:Node* _head;size_t _size;};
}

ReverseIterator.h文件

#pragma once// 所有容器的反向迭代器
// 迭代器适配器
namespace bit
{// vector<T>::iterator// list<T>::iteratortemplate<class Iterator, class Ref, class Ptr>struct ReverseIterator{// typedef ReverseIterator<T, T&, T*>// typedef ReverseIterator<T, const T&, const T*>typedef ReverseIterator<Iterator, Ref, Ptr> rever_iterator;//将反向迭代器的类型重命名为rever_iteratorIterator _it;//定义一个正向迭代器类型的对象,并对其进行初始化和封装ReverseIterator(Iterator it)//反向迭代器的对象由正向迭代器的对象初始化:_it(it){}Ref operator*(){Iterator tmp = _it;//不改变原迭代器本身的指向,只想获取迭代器指向的下一个位置的数据的值return *(--tmp);}Ptr operator->(){return &(operator*());//返回该对象地址,返回值的类型是Ptr*,匿名指针}//++和--逻辑与正向迭代器相反//前置++rever_iterator& operator++()//返回类型是一个反向迭代器类类型的引用{--_it;return *this;}//前置--rever_iterator& operator--(){++_it;return *this;}bool operator!=(const rever_iterator& s){return _it != s._it;}};
}

test.cpp文件

#include<iostream>
#include<vector>
#include<list>
#include<algorithm>
using namespace std;
#include"list.h"//list必须放在这,list.h中有需要以上头文件的地方,不改变其它代码的前提下放在上面几行会报错int main()
{bit::list<int> lt = { 1,2,3,4 };bit::list<int>::reverse_iterator rit = lt.rbegin();while (rit != lt.rend()){cout << *rit << " ";++rit;}cout << endl;return 0;
}
  • lt是一个被多参数实例化的一个list类类型的对象
  • rit是一个反向迭代器类型的对象,先调用lt中的rbegin函数,该函数又会调用end函数返回一个实例化好的普通正向迭代器类类型的匿名对象,然后该匿名对象会作为参数传递给ReverseIterator类模板,从而实例化出一个反向迭代器类类型的对象,最后返回给rit

  • 调用lt的rend函数,经过一系列操作后返回一个反向迭代器类类型的匿名对象,rit和该匿名对象一起传入rit的!=重载函数中进行比较,该函数又会调用二者正向迭代器中的!=重载函数,最后将比较结果返回
  • *rit会调用rit中的*重载函数,生成一个临时的正向迭代器类型的对象tmp(_it是由正向迭代初始化的)--tmp调用正向迭代器的--重载函数令tmp指向的前一个对象,调用tmp的*重载函数返回获取的数据(运用临时对象原迭代器指向的对象不变)
  • ++rit调用rit的++重载函数,先调用_it的--重载函数将_it指向前一个对象并返回更新后的_it,最后++重载函数返回更新后的_it

~over~

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

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

相关文章

深入理解Apache ZooKeeper与Kafka的协同工作原理

目录 引言 一、ZooKeeper基础概念 &#xff08;一&#xff09;ZooKeeper简介 &#xff08;二&#xff09;ZooKeeper数据结构 &#xff08;三&#xff09;ZooKeeper特点 &#xff08;四&#xff09;应用场景 二、ZooKeeper工作模式 &#xff08;一&#xff09;工作机制 …

请求分发场景下的鉴权问题

说明&#xff1a;记录一次对请求分发&#xff0c;无法登录系统的问题。 场景 如下&#xff0c;在此结构下&#xff0c;如何判断该用户是已登录的用户&#xff1b; 常规操作&#xff0c;用户登录后给用户发Token&#xff0c;同时将发放的Token存入到Redis中。要求用户后续请求…

在 Vue 3 中使用 Axios 发送 POST 请求

在 Vue 3 中使用 Axios 发送 POST 请求需要首先安装 Axios&#xff0c;然后在 Vue 组件或 Vuex 中使用它。以下是一个简单的安装和使用案例&#xff1a; 安装 Axios 你可以使用 npm 或 yarn 来安装 Axios&#xff1a; npm install axios # 或者 yarn add axios 使用 Axios…

架构设计-订单系统之订单系统的架构进化

1、单数据库架构 产品初期&#xff0c;技术团队的核心目标是&#xff1a;“快速实现产品需求&#xff0c;尽早对外提供服务”。 彼时的专车服务都连同一个 SQLServer 数据库&#xff0c;服务层已经按照业务领域做了一定程度的拆分。 这种架构非常简单&#xff0c;团队可以分开…

单片机方案 发声毛绒小黄鸭

随着科技的不断进步&#xff0c;智能早教已经成为了新时代儿童教育的趋势。智能早教玩具&#xff0c;一款集互动陪伴、启蒙教育、情感培养于一身的高科技产品。它不仅能陪伴孩子成长&#xff0c;还能在游戏中启迪智慧&#xff0c;是家长和孩子的理想选择。 酷得电子方案开发特…

股票价格预测 | Python使用GRU预测股票价格

文章目录 效果一览文章概述代码设计效果一览 文章概述 Python使用GRU预测股票价格 代码设计 import pandas as pd import matplotlib.pyplot as plt import numpy as np import tensorflow as tf from numpy

Python 正则表达式模块使用

目录 1、匹配单个字符 2、匹配多个字符 3、匹配开头结尾 4、匹配分组 说明&#xff1a;在Python中需要通过正则表达式对字符串进行匹配的时候&#xff0c;可以使用re模块 表达式&#xff1a;re.match(正则表达式&#xff0c; 要匹配的字符串) 有返回值说明匹配成功&#x…

13-pyspark的共享变量用法总结

目录 前言广播变量广播变量的作用 广播变量的使用方式 累加器累加器的作用累加器的优缺点累加器的使用方式 PySpark实战笔记系列第四篇 10-用PySpark建立第一个Spark RDD(PySpark实战笔记系列第一篇)11-pyspark的RDD的变换与动作算子总结(PySpark实战笔记系列第二篇))12-pysp…

Springboot+Vue项目-基于Java+MySQL的课程作业管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

秀米、135、蚂蚁编辑器如何为推文添加附件

秀米、135、蚂蚁编辑器作为第三方的公众号图文排版工具&#xff0c;给从事运营和编辑工作的同学提供了更多的排版选择。不同于公众号自家的编辑器&#xff0c;这些第三方编辑器脱离了微信的直接支持&#xff0c;在很多排版操作上&#xff0c;还是有很多操作不一样的地方。 公众…

通过 Vue 3 组合式 API 优化 Uni-app 基础页面功能

Uni-app 是一个跨平台的应用开发框架&#xff0c;支持同时开发小程序、App 和 H5 等多个平台。而 Vue 3 的组合式 API 则是 Vue 3 新增的特性之一&#xff0c;它可以让我们更好地组织和复用组件逻辑。本文将结合 Vue 3 的组合式 API&#xff0c;来优化 Uni-app 中基础页面的功能…

自动化运维(二十三)Ansible 实战动态库存插件和回调插件

Ansible 支持多种类型的插件&#xff0c;这些插件可以帮助你扩展和定制 Ansible 的功能。每种插件类型都有其特定的用途和应用场景。今天我们一起学习动态库存插件和回调插件。 一、动态库存插件 Ansible 动态库存插件允许从各种外部数据源动态获取库存信息&#xff0c;包括主…

AndroidAutomotive模块介绍(一)整体介绍

前言 Android Automotive 是一个基本 Android 平台&#xff0c;可运行 IVI 系统中预安装的 Android 应用以及可选的第二方和第三方 Android 应用。 本系列文档将会系统的介绍 Android Automotive 的功能、架构、逻辑等。模块逻辑将从 应用api接口、系统服务、底层服务&#x…

软件设计师:11-结构化开发与UML

结构化开发&#xff08;3-4分&#xff09; 一、模块化 二、耦合&#xff08;背&#xff09; 三、内聚&#xff08;背&#xff09; 四、设计原则&#xff08;背&#xff09; 五、系统文档 六、数据流图 数据流的起点或终点必须有一个是加工 判断依据&#xff1a; 1、…

Vivado Design Suite中route_design命令脚本示例

本文详细介绍了四个route_design命令的示例脚本&#xff0c;这些脚本需要添加到工程的约束文件.xdc中&#xff0c;结果保存在工程文件中的runs\impl_1中的runme.log文件。 一、示例脚本1 route_design write_checkpoint -force $outputDir/post_route report_timing_summary …

img使用 :src 动态绑定图片地址,图片不成功

使用vue cli 创建的vue2项目&#xff0c;项目中想实现轮播效果。 出现的问题&#xff1a; 使用 :src 动态绑定图片地址&#xff0c;图片没有出现 <el-carousel :interval"3000" arrow"always"><el-carousel-item v-for"(item,index) in sw…

【MATLAB源码-第46期】基于matlab的OFDM系统多径数目对比,有无CP(循环前缀)对比,有无信道均衡对比。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 OFDM&#xff08;正交频分复用&#xff09;是一种频域上的多载波调制技术&#xff0c;经常用于高速数据通信中。以下是关于多径数目、有无CP&#xff08;循环前缀&#xff09;以及有无信道均衡在OFDM系统中对误码率的影响&am…

6-125 二叉树的后序遍历(Python语言描述)

本题要求输出二叉树的后序遍历,输出格式见样例。 函数接口定义: #后序遍历 def postOrder(T)其中二叉树类的定义如下: #二叉树的存储-二叉链表 class BinaryTree:#1.构造方法def __init__(self,newValue):self.key = newValue #树根self.left = None #左子树初…

小程序如何通过把动态数据值传入到css文件中控制样式

场景&#xff1a;动态改变一个模块的高度 一、常用解决方法&#xff1a;行内样式绑值&#xff0c;或者动态class来传递 <viewclass"box":style"height: ${boxHeight}px">我是一个动态高度的box,我的高度是{{boxHeight}}px </view>二、高度传…

第07-1章 计算机网络相关概念

7.1 本章目标 了解网络协议的概念了解网络体系结构熟悉ISO/OSI参考模型以及每一层的功能掌握TCP/IP模型各层的主要协议及其功能熟练掌握IP地址、子网规划等相关内容 7.2 网络协议的概念 7.2.1 概念介绍 &#xff08;1&#xff09;网络协议&#xff1a;计算机网络和分布系统中…