反向迭代器
- 反向迭代器
- 构造函数
- ++运算符重载
- - -运算符重载
- 其他运算符重载
- rbegin()与rend()
- list与vector比较
反向迭代器
通过前面学习我们就可以知道,反向迭代器的++就是正向迭代器的–,反向迭代器的–就是正向迭代器的++,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。
我们以list的反向迭代器为例:
对于list来说,他的正向迭代器的begin()就是头结点后面的那个结点位置,end()就是头结点位置,而他的反向迭代器通过了解STL源码可以发现,begin()是头结点位置,end()是头结点后面的那个结点位置,与正向迭代器时对称的:
为了与list相对应,我们的反向迭代器模板参数也需要设置为三个:
template<class Iterator, class Ref, class Ptr>
//typedef __reverse_iterator<iterator, T&, T*> reverse_iterator;
//typedef __reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
构造函数
我们使用正向迭代器来实现反向迭代器,反向迭代器的构造函数参数就需要我们设置为正向迭代器:
//构造函数
__reverse_iterator(Iterator it)
:_cur(it)
{}
++运算符重载
反向迭代器的++其实就是正向迭代器的- -:
//前置++
RIterator& operator++()
{
_cur--;//正向迭代器--
return *this;
}
//后置++
RIterator operator++(int)
{
RIterator tmp(*this);//创建一个变量tmp
_cur--;//正向迭代器--
return tmp;
}
- -运算符重载
反向迭代器的- -其实就是正向迭代器的++:
//前置--
RIterator& operator--()
{
_cur++;//正向迭代器++
return *this;
}
//后置--
RIterator operator--(int)
{
RIterator tmp(*this);
_cur++;//正向迭代器++
return tmp;
}
其他运算符重载
其他运算符重载就与正向迭代器相同:
//解引用
Ref operator*()
{
auto tmp = _cur;//创建一个tmp赋值为cur
--tmp;//指向头结点的前一个结点
return *tmp;
}
//->
Ptr operator->()
{
return &(operator*());
}
//等于==
bool operator==(const RIterator& rit)
{
return _cur == rit._cur;
}
//不等于!=
bool operator!=(const RIterator& rit)
{
return _cur != rit._cur;
}
rbegin()与rend()
//rbegin
//普通类型
reverse_iterator rbegin()
{
return reverse_iterator (end());//对应尾结点
}
//const类型
const_reverse_iterator rbegin()const
{
return reverse_iterator (end());
}
//rend()
//普通类型
reverse_iterator rend()
{
return reverse_iterator (begin());//对应头结点下一个节点
}
//const类型
const_reverse_iterator rend()const
{
return reverse_iterator (begin());
}
list与vector比较
vector | list | |
---|---|---|
底层结构 | 动态顺序表 | 一段连续空间 |
随机访问 | 支持随机访问,访问某个元素效率为O(1) | 不支持随机访问,访问某个元素效率O(N) |
插入和删除 | 任意位置插入和删除效率低,需要搬移元素,时间复杂度为O(N),插入时有可能需要增容,增容:开辟新空间,拷贝元素,释放旧空间,导致效率更低 | 任意位置插入和删除效率高,不需要搬移元素,时间复杂度为O(1) |
空间利用率 | 底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高 | 底层节点动态开辟,小节点容易造成内存碎片,空间利用率低,缓存利用率低 |
迭代器 | 原生态指针 | 对原生态指针(节点指针)进行封装 |
迭代器失效 | 在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效 | 插入元素不会导致迭代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响 |
使用场景 | 需要高效存储,支持随机访问,不关心插入删除效率 | 大量插入和删除操作,不关心随机访问 |