反向迭代器的概念:
反向迭代器是一种特殊的迭代器,它与正向迭代器正好相反,正向迭代器从头向尾遍历,而反向迭代器是从尾到头遍历;至于正向迭代器的具体实现方法,我之前已经写过,在此不做赘述,如有需要请阅读这一篇博客:http://t.csdn.cn/7BRwC
由反向迭代器与正向迭代器的性质可知:
正向迭代器的++ =反向迭代器的-- ;
正向迭代器的-- =反向迭代器的++ ;
,但是,不是所有的容器都支持正向迭代器与反向迭代器,有的容器支持双向迭代,有的不支持,所以迭代器有大致分为五种(输出迭代器/输入迭代器/向前迭代器/双向迭代器/随机访问迭代器),这里,我们以支持双向迭代的list类为例,来实现反向迭代器;
这里我们可以先看一下list正向迭代器的实现方式,具体代码如下所示:
//增加模板参数ref,解决const迭代器的问题;
//增加模板参数ptr,解决自定义类型结构体的->问题;
template <class T,class ref,class ptr>
struct list_iterator
{
typedef list_node<T> node;//生成结点,
typedef list_iterator<T,ref,ptr> self;//typedef 重定义名称,增强其可读性;
node* _node;//迭代器内需要一个节点,来实现移动以及取值;
list_iterator(node* node)//迭代器需要结点来实现迭代;
:_node(node)
{
}
ref operator*()
{
return _node->data;
}
ptr operator->()
{
return &_node->data;
}
self& operator++()
{
_node = _node->_next;//++是指向下一个结点
return *this;
}
self operator++(int)
{
self temp(*this);
_node = _node->_next;
return temp;
}
self& operator--()
{
_node = _node->_prev;
return *this;
}
self operator--(int) //--是指向上一个结点
{
self temp(*this);
_node = _node->_prev;
return temp;
}
bool operator!=(const self& LL)
{
return _node != LL._node;
}
bool operator==(const self& LL)
{
return _node == LL._node;
}
};
template <class T>
class List
{
typedef list_node<T> node;
public:
typedef list_iterator<T, T&, T*> iterator;//普通迭代器;
typedef list_iterator<T, const T&, const T*> const_iterator;//const迭代器,可以修改迭代器,但是不能修改迭代器所指向的内容;
//正向迭代器
iterator begin()
{
return iterator(_phead->_next);
}
iterator end()
{
return iterator(_phead);
}
//const正向迭代器:
const_iterator begin()const
{
return const_iterator(_phead->_next);
}
const_iterator end()const
{
return const_iterator(_phead);
}
private:
node* _phead;
};
我们知道,正向迭代器与反向迭代器的++/--是倒过来的,那么什么只需要在list类上的正向迭代器上做稍微的改动就基本上就能实现出反向迭代器,只需要把正向迭代器中的指向下一个结点改为指向上一个结点就实现出反向迭代器,具体代码如下所示:
//增加模板参数ref,解决const迭代器的问题;
//增加模板参数ptr,解决自定义类型结构体的->问题;
template <class T,class ref,class ptr>
struct list_iterator//正向迭代器:
{
typedef list_node<T> node;//生成结点,
typedef list_iterator<T,ref,ptr> self;//typedef 重定义名称,增强其可读性;
node* _node;//迭代器内需要一个节点,来实现移动以及取值;
list_iterator(node* node)//迭代器需要结点来实现迭代;
:_node(node)
{
}
ref operator*()
{
return _node->data;
}
ptr operator->()
{
return &_node->data;
}
self& operator++()
{
_node = _node->_next;
return *this;
}
self operator++(int)
{
self temp(*this);
_node = _node->_next;
return temp;
}
self& operator--()
{
_node = _node->_prev;
return *this;
}
self operator--(int)
{
self temp(*this);
_node = _node->_prev;
return temp;
}
bool operator!=(const self& LL)
{
return _node != LL._node;
}
bool operator==(const self& LL)
{
return _node == LL._node;
}
};
//改造正向迭代器变成反向迭代器:
//不适用于其他容器,list可以通过改写正向迭代器逆推反向迭代器。但是如vector则无法逆推!
template <class T, class ref, class ptr>
struct reverse_iterator
{
typedef list_node<T> node;
typedef reverse_iterator<T, ref, ptr> self;
node* _node;//迭代器内需要一个节点,来实现移动以及取值;
reverse_iterator(node* node)
:_node(node)
{
}
ref operator*()
{
return _node->data;
}
ptr operator->()
{
return &_node->data;
}
self& operator++()
{
_node = _node->_prev;//++是指向上一个结点
return *this;
}
self operator++(int)
{
self temp(*this);
_node = _node->_prev;
return temp;
}
self& operator--()//-- 是指向下一个结点
{
_node = _node->_next;
return *this;
}
self operator--(int)
{
self temp(*this);
_node = _node->_next;
return temp;
}
bool operator!=(const self& LL)
{
return _node != LL._node;
}
bool operator==(const self& LL)
{
return _node == LL._node;
}
};
template <class T>
class List
{
typedef list_node<T> node;
public:
typedef list_iterator<T, T&, T*> iterator;//普通迭代器;
typedef list_iterator<T, const T&, const T*> const_iterator;//const迭代器,可以修改迭代器,但是不能修改迭代器所指向的内容;
//typedef reverse_Iterator<T, T&, T*> reverse_iterator;//通过正向迭代器逆推反向迭代器;
//typedef reverse_Iterator<T, T&, T*> const_reverse_iterator;//const反向迭代器;
//正向迭代器
iterator begin()
{
return iterator(_phead->_next);
}
iterator end()
{
return iterator(_phead);
}
//const正向迭代器:
const_iterator begin()const
{
return const_iterator(_phead->_next);
}
const_iterator end()const
{
return const_iterator(_phead);
}
通过正向迭代器逆推反向迭代器:
reverse_iterator rbegin()
{
return reverse_iterator(_phead->_prev);
}
reverse_iterator rend()
{
return reverse_iterator(_phead);
}
通过正向迭代器逆推反向迭代器(const反向迭代器):
const_reverse_iterator rbegin()const
{
return const_reverse_iterator(_phead->_prev);
}
const_reverse_iterator rend()const
{
return const_reverse_iterator(_phead);
}
private:
node* _phead;
};
通过上述代码我们可知,虽然可以通过正向迭代器逆推出反向迭代器,但是只是改变了迭代器++,--所指向的结点,同时因为这是list类,是双向循环链式结构,不具有普适性,为了应对代码冗余与不具有普适性两大缺点,我们必须舍弃这种修改正向迭代器的做法
//////
通过对STL库反向迭代器源码的学习,我们可以将正向迭代器封装来实现反向迭代器,就像通过适配器模式用 顺序表,链表来实现 数组栈 / 链式栈 / 队列一样,我们通过正向迭代器来实现反向迭代器,同时,我们发现源码中operator*的实现有一丝丝的奇怪,operator*不再解引用当前迭代器
所指向的元素;
为了解决operator*的问题,我们需要明白begin(),end(),rbegin(),rend()的位置;通过源码的描述,画出大致位置图(以list类为例):
我们可以发现STL库中将正向迭代器的begin(),end(),与反向迭代器的rbegin(),rend()设计成正好相反的样子,可能是为了追求“对称美”,那么,为了解决在 rbegin() 处解引用的问题,
所以将operator*改为解引用上一个结点;
总结出:
正向迭代器的operator*:解引用当前迭代器所指向的元素;
反向迭代器的operator*:解引用当前迭代器所指向的前一个元素;
具体代码如下所示:
//增加模板参数ref,解决const迭代器的问题;
//增加模板参数ptr,解决自定义类型结构体的->问题;
template <class T,class ref,class ptr>
struct list_iterator//正向迭代器:
{
typedef list_node<T> node;//生成结点,
typedef list_iterator<T,ref,ptr> self;//typedef 重定义名称,增强其可读性;
node* _node;//迭代器内需要一个节点,来实现移动以及取值;
list_iterator(node* node)//迭代器需要结点来实现迭代;
:_node(node)
{
}
ref operator*()
{
return _node->data;
}
ptr operator->()
{
return &_node->data;
}
self& operator++()
{
_node = _node->_next;
return *this;
}
self operator++(int)
{
self temp(*this);
_node = _node->_next;
return temp;
}
self& operator--()
{
_node = _node->_prev;
return *this;
}
self operator--(int)
{
self temp(*this);
_node = _node->_prev;
return temp;
}
bool operator!=(const self& LL)
{
return _node != LL._node;
}
bool operator==(const self& LL)
{
return _node == LL._node;
}
};
//封装正向迭代器,来实现反向迭代器,
//适用于所有的容器。泛型模板,只要这个容器是可双向迭代的,都可以使用封装正向迭代器来实现反向迭代器;
template<class Iterator,class Ref,class ptr>//封装正向迭代器
struct reverse_Iterator
{
typedef reverse_Iterator<Iterator,Ref,ptr> self;
Iterator _cur;
reverse_Iterator(Iterator it)
:_cur(it)
{
}
Ref operator*()//解引用当前迭代器所指向的前一个元素;
{
Iterator temp = _cur;
--temp;
return *temp;
}
ptr operator->()
{
Iterator temp =_cur;
--temp;
return &(*temp);
}
self& operator++()//++就是指向前一个元素;
{
--_cur;
return *this;
}
self operator++(int)
{
Iterator temp = _cur;
--_cur;
return temp;
}
self& operator--()//--就是指向后一个元素;
{
++_cur;
return *this;
}
self operator--(int)
{
iterator temp = _cur;
++_cur;
return temp;
}
bool operator!=(const self& LL)
{
return _cur != LL._cur;
}
bool operator==(const self& LL)
{
return _cur == LL._cur;
}
};
template <class T>
class List
{
typedef list_node<T> node;
public:
typedef list_iterator<T, T&, T*> iterator;//普通迭代器;
typedef list_iterator<T, const T&, const T*> const_iterator;//const迭代器,可以修改迭代器,但是不能修改迭代器所指向的内容;
typedef reverse_Iterator<iterator, T&, T*> reverse_iterator;//通过封装正向迭代器来实现反向迭代器;
typedef reverse_Iterator <iterator, const T&, const T*> const_reverse_iterator;//const反向迭代器;
//正向迭代器:
iterator begin()
{
return iterator(_phead->_next);
}
iterator end()
{
return iterator(_phead);
}
//const正向迭代器
const_iterator begin()const
{
return const_iterator(_phead->_next);
}
const_iterator end()const
{
return const_iterator(_phead);
}
//反向迭代器:
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
//const反向迭代器:
const_reverse_iterator rbegin()const
{
return const_reverse_iterator(end());
}
const_reverse_iterator rend()const
{
return const_reverse_iterator(begin());
}
private:
node* _phead;
};
写到这里,反向迭代器基本上已经实现,但是给人感觉和我们改动正向迭代器逆推反向迭代器差不多,代码也有冗余,那么封装正向迭代器的意义在什么地方呢?
封装正向迭代器实现反向迭代器的巨大优点是:只要这个容器支持双向迭代遍历,那么都可以通过封装正向迭代器实现反向迭代器,而改动正向迭代器逆推反向迭代器不一定能实现出来,比如vector等;