【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 once

namespace 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 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*()
		{
			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; //结束位置
	};
}


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

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stackY、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值