【STL】:反向迭代器

简介: 【STL】:反向迭代器

前言:

前面的模拟实现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; //结束位置
  };
}

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

目录
相关文章
|
5月前
|
算法 编译器 C++
|
11月前
|
算法 C++ 容器
STL迭代器
STL迭代器
37 0
|
12月前
|
C++ 容器
【C++】反向迭代器的实现
【C++】反向迭代器的实现
|
5月前
|
设计模式 编译器 C++
【C++】开始了解反向迭代器
这样我们就实现反向迭代器,大家可以在实际中继续体会。
45 3
|
4月前
|
编译器 容器
反向迭代器的实现
反向迭代器的实现
20 1
|
4月前
|
算法 数据处理 C++
C++一分钟之-迭代器与算法
【6月更文挑战第21天】C++ STL的迭代器统一了容器元素访问,分为多种类型,如输入、输出、前向、双向和随机访问。迭代器使用时需留意失效和类型匹配。STL算法如查找、排序、复制要求特定类型的迭代器,注意容器兼容性和返回值处理。适配器和算法组合增强灵活性,但过度使用可能降低代码可读性。掌握迭代器和算法能提升编程效率和代码质量。
48 3
|
4月前
|
编译器 C++
C++ 反向迭代器的设计与实现
C++ 反向迭代器的设计与实现
|
11月前
|
存储 C++ 容器
|
5月前
|
算法 程序员 C语言
【C++ 迭代器实现细节 】深入探索C++迭代器:从实现到整合
【C++ 迭代器实现细节 】深入探索C++迭代器:从实现到整合
145 0
|
5月前
|
C++ 容器
C++反向迭代器
C++反向迭代器