学习这部分知识,需要你了解vector和list的正向迭代器知识以及容器适配器知识,可以阅读我写的另外三篇vector、list、容器适配器 知识的博客!其中list知识内容尤其重要且难度要求很高!
反向迭代器,顾名思义是与正向迭代器相对,作用是反向遍历容器数据!
目录
一、反向迭代器
1.1 反向迭代器相关函数
1.1.1 rbegin()
1.1.2 rend()
1.2反向迭代器反向遍历vector和list
1.2.1 反向遍历vector
1.2.2 反向遍历list
二、模拟实现vector反向迭代器
2.1 vector正向迭代器
2.2 vector反向迭代器
2.3 模拟测试遍历vector
2.3.1 const反向迭代器效果
2.3.2 反向迭代器遍历
三、模拟实现list反向迭代器
3.1 list 正向迭代器
3.2 模拟实现list反向迭代器
3.3 测试反向迭代器遍历
3.3.1 const迭代器效果展示
3.3.2 反向迭代器遍历list
四、模拟实现vector完整版
五、模拟实现list完整版
一、反向迭代器
1.1 反向迭代器相关函数
C++11中加了独立的返回const迭代器的函数,但这篇博客只模拟实现list的const函数重载来返回const迭代器! 具体这些函数请查看cplusplus.com - The C++ Resources Network!
1.1.1 rbegin()
返回值:返回指向容器中最后一个元素(即其反向开头)的反向迭代器!
const修饰的函数返回值:返回const反向迭代器,其指向成员不能被修改!
1.1.2 rend()
返回值:返回一个反向迭代器,该迭代器指向容器中第一个元素之前的理论元素
const修饰的函数返回值:返回const反向迭代器,其指向成员不能被修改!
1.2反向迭代器反向遍历vector和list
1.2.1 反向遍历vector
1.2.2 反向遍历list
二、模拟实现vector反向迭代器
2.1 vector正向迭代器
namespace wyz//与标准库vector区别,自己定义一个命名空间,在里面写!
{template<class T>class vector{public://...//迭代器typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator cbegin()const{return _start;}const_iterator cend()const{return _finish;}private:iterator _start;iterator _finish;iterator _end_of_storage;};
2.2 vector反向迭代器
反向迭代器是反向遍历容器数据,它也要满足++、--、*、==、!=的功能,只不过它的++是从后往前,--是从前往后。我们很容易可以想到,反向迭代器和正向的功能差不多相同,只不过在++,--的效果相反!vector正向迭代器底层是指针,它的算法迎合基本的逻辑,++向后,--向前!我们无法直接实现让变量++指针减小,--指针增加!所以我们要用到容器适配器,底层我们可以用正向迭代器!反向的效果只要让正向反着来!--让正向++,++让正向--!这样一来我们的遍历就可以实现!也就是说,我们要将反向迭代器封装成类!
下面我们直接上代码:
template<class iterator, class T>struct vector_reverse_iterator{typedef vector_reverse_iterator<iterator, T> Self;public://拷贝构造vector_reverse_iterator(iterator s){_it = _it;}Self& operator++(){--_it;return *this;}Self& operator--(){++_it;return *this;}T operator*(){iterator tmp = _it;return *(--tmp);//注意这个返回!}bool operator!=(Self s){return _it != s._it;}bool operator==(Self s){return _it == s._it;}private:iterator _it;};
在来看看vector中的反向迭代器的申明与相关函数:
typedef T* iterator;
typedef const T* const_iterator;
typedef vector_reverse_iterator<iterator,T> reverse_iterator;
typedef vector_reverse_iterator<const_iterator,const T> const_reverse_iterator;
//正向迭代器
iterator begin()
{return _start;
}
iterator end()
{return _finish;
}
const_iterator cbegin()const
{return _start;
}
const_iterator cend()const
{return _finish;
}
//反向迭代器传参,这里为了与正向对称,直接传_finish和_start
reverse_iterator rbegin()
{return reverse_iterator(_finish);
}
reverse_iterator rend()
{return reverse_iterator(_start);
}
//const反向迭代器,不能修改迭代器指向数据!
const_reverse_iterator crbegin()const
{return const_reverse_iterator(_finish);
}
const_reverse_iterator crend()const
{return const_reverse_iterator(_start);
}
💡💡现在这里主要的一个细节问题就是反向迭代器*解引用返回值!为什么要用临时变量先--后解引用返回?画一张图带你来看看!
这里因为我的rbegin()传参为了与正向对称,没有修改迭代器初始指向!如果我让rbegin()返回的是, return reverse_iterator(_finish-1); 同样rend()返回 reverse_iterator(_start-1),就不用像上面那样先--再*了!直接*返回就可以!
2.3 模拟测试遍历vector
2.3.1 const反向迭代器效果
满足const修饰不能修改数据!
2.3.2 反向迭代器遍历
void vector_test_4()
{wyz::vector<int>v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);wyz::vector<int>::reverse_iterator rit = v.rbegin();while (rit != v.rend()){cout << *rit << ' ';++rit;}cout << endl;
}
void vector_test_5()
{wyz::vector<int>v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);wyz::vector<int>::const_reverse_iterator crit = v.crbegin();while (crit != v.crend()){cout << *crit << ' ';++crit;}cout << endl;
}
int main()
{cout << "vector_test_4()测试结果:";vector_test_4();cout << "vector_test_5()测试结果:";vector_test_5();return 0;
}
三、模拟实现list反向迭代器
3.1 list 正向迭代器
template<class T, class ref, class ptr>
struct list_iterator
{typedef list_node<T> node;typedef list_iterator<T, ref, ptr> Self;node* pnode;list_iterator(node* p):pnode(p){}ref operator*(){return pnode->data;}ptr operator->(){return &pnode->data;}//前置Self& operator++(){pnode = pnode->next;return *this;}//后置Self operator++(int){Self tmp(pnode);pnode = pnode->next;return tmp;}//前置Self& operator--(){pnode = pnode->prev;return *this;}//后置Self operator--(int){Self tmp(pnode);pnode = pnode->prev;return tmp;}bool operator!=(const Self& it){return pnode != it.pnode;}bool operator==(const Self& it){return pnode == it.pnode;}
};
3.2 模拟实现list反向迭代器
经过前面的vecotr反向迭代器模拟,我们知道其实反向迭代器可以用正向作容器,实现容器适配器!下面我们来实现list反向迭代器。
下面我们上代码:
template<class iterator, class ref, class ptr>
class list_reverse_iterator
{typedef list_reverse_iterator<iterator, ref, ptr> self;
public:list_reverse_iterator(iterator it):_it(it){}self& operator++(){--_it;return *this;}self& operator--(){++_it;return *this;}ref operator*(){iterator tmp = _it;return *(--tmp);//注意这里的先--后*}ptr operator->(){return &(operator*());//ref=T& &ref=&(T&) 即相当于T*=ptr}bool operator!=(const self& s){return _it != s._it;}bool operator==(const self& s){return _it == s._it;}
private:iterator _it;
};
我们再来看看list的反向迭代器申明与相关函数:
typedef list_iterator<T, T&, T*> iterator;
typedef list_iterator<T, const T&, const T*> const_iterator;
typedef list_reverse_iterator<iterator, T&, T*> reverse_iterator;
typedef list_reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;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函数重载返回const反向迭代器
const_reverse_iterator rbegin()const
{return const_reverse_iterator(end());
}
const_reverse_iterator rend()const
{return const_reverse_iterator(begin());
}
思路几乎和上面的vector一样,这里我们还要再说明一下为什么这里还是先--后*! 我们可以看到反向迭代器相关函数依然与正向相对称!我们还是画图来理解!
3.3 测试反向迭代器遍历
3.3.1 const迭代器效果展示
3.3.2 反向迭代器遍历list
void list_test_4()
{const wyz::list<int> clt;clt.push_back(1);clt.push_back(2);clt.push_back(3);clt.push_back(4);clt.push_back(5);wyz::list<int>::const_reverse_iterator const_rit = clt.rbegin();while (const_rit != clt.rend()){//cout << (*const_rit)++ << ' ';cout << *const_rit << ' ';++const_rit;}cout << endl;
}
void list_test_5()
{wyz::list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);wyz::list<int>::reverse_iterator rit = lt.rbegin();while (rit != lt.rend()){cout << *rit << ' ';++rit;}cout << endl;
}
int main()
{cout << "list_test_4()测试结果:";list_test_4();cout << "list_test_5()测试结果:";list_test_5();return 0;
}
四、模拟实现vector完整版
namespcae wyz
{
template<class T>
class vector
{
public://构造函数vector():_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){}vector(const vector<T>& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(v.size());for (auto& e : v){push_back(e);}}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}vector<T>& operator=(vector<T> tmp){swap(tmp);return *this;}//这里为了更加直观化,不用T* 而是重新定义一个模板Inputiteratortemplate<class InputIterator>vector(InputIterator first, InputIterator last):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(last - first);while (first != last){push_back(*first);first++;}}vector(int n, const T& val = T()):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(n);while (n){push_back(val);n--;}}//析构函数~vector(){delete[]_start;_start = nullptr;_finish = nullptr;_end_of_storage = nullptr;}//返回空间数据个数size_t size()const{return _finish - _start;}//返回空间大小size_t capacity()const{return _end_of_storage - _start;}//预开辟空间void reserve(size_t n){if (n > capacity()){//记录数组有效个数size_t sz = size();T* tmp = new T[n];if (_start){for (int i = 0;i < sz;i++){tmp[i] = _start[i];}delete[]_start;}//更新_start = tmp;_finish = _start + sz;_end_of_storage = _start + n;}}//预指定数据个数void resize(size_t n, T val = T()){if (n > capacity()){//预开辟空间reserve(n);//尾插while (_finish < _start + n){*_finish = val;_finish++;}}//n<capacity() 直接修改_finish位置,不需要挪动数据else{_finish = _start + n;}}template<class iterator, class T>struct vector_reverse_iterator{typedef vector_reverse_iterator<iterator, T> Self;public:vector_reverse_iterator(iterator it){_it = it;}Self& operator++(){--_it;return *this;}Self& operator--(){++_it;return *this;}T operator*(){iterator tmp = _it;return *(--tmp);}bool operator!=(Self s){return _it != s._it;}bool operator==(Self s){return _it == s._it;}private:iterator _it;};//迭代器typedef T* iterator;typedef const T* const_iterator;typedef vector_reverse_iterator<iterator, T> reverse_iterator;typedef vector_reverse_iterator<const_iterator, const T> const_reverse_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator cbegin()const{return _start;}const_iterator cend()const{return _finish;}reverse_iterator rbegin(){return reverse_iterator(_finish);}reverse_iterator rend(){return reverse_iterator(_start);}const_reverse_iterator crbegin()const{return const_reverse_iterator(_finish);}const_reverse_iterator crend()const{return const_reverse_iterator(_start);}//返回数组指定位置内容T& operator[](size_t pos){return _start[pos];}const T& operator[](size_t pos)const{return _start[pos];}bool empty(){return _start == _finish;}void clear(){_start = _finish;}//尾插void push_back(const T& x){//判断是否需要扩容if (_finish == _end_of_storage){size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);}*(_finish) = x;_finish++;}//尾删void pop_back(){assert(!empty());_finish--;}//指定位置插入void insert(iterator pos, T x){size_t n = pos - _start;//判断是否需要扩容if (_finish == _end_of_storage){size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);pos = _start + n;}iterator end = _finish;while (end >= pos){*(end + 1) = *end;end--;}*(end + 1) = x;_finish++;}//指定位置删除iterator erase(iterator pos){assert(!empty());iterator begin = pos;while (begin != _finish - 1){*begin = *(begin + 1);begin++;}_finish--;return pos;}
private:iterator _start;iterator _finish;iterator _end_of_storage;
};
}
五、模拟实现list完整版
namespace wyz
{template<class T>struct list_node{list_node(const T& val=T()):prev(nullptr),next(nullptr),data(val){}public:list_node* prev;list_node* next;T data;};template<class T,class ref,class ptr>struct list_iterator{typedef list_node<T> node;typedef list_iterator<T, ref, ptr> Self;node* pnode;list_iterator(node* p):pnode(p){}ref operator*(){return pnode->data;}ptr operator->(){return &pnode->data;}//前置Self& operator++(){pnode = pnode->next;return *this;}//后置Self operator++(int){Self tmp(pnode);pnode = pnode->next;return tmp;}//前置Self& operator--(){pnode = pnode->prev;return *this;}//后置Self operator--(int){Self tmp(pnode);pnode = pnode->prev;return tmp;}bool operator!=(const Self& it){return pnode != it.pnode;}bool operator==(const Self& it){return pnode == it.pnode;}};template<class iterator,class ref,class ptr>class list_reverse_iterator{typedef list_reverse_iterator<iterator, ref, ptr> self;public:list_reverse_iterator(iterator it):_it(it){}self& operator++(){--_it;return *this;}self& operator--(){++_it;return *this;}ref operator*(){iterator tmp = _it;return *(--tmp);}ptr operator->(){return &(operator*());}bool operator!=(const self& s){return _it != s._it;}bool operator==(const self& s){return _it == s._it;}private:iterator _it;};template<class T>class list{public:typedef list_node<T> node;typedef list_iterator<T,T&,T*> iterator;typedef list_iterator<T, const T&,const T*> const_iterator;typedef list_reverse_iterator<iterator, T&,T*> reverse_iterator;typedef list_reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;iterator begin(){//匿名对象返回!return iterator(head->next);}const_iterator begin()const{return const_iterator(head->next);}const_iterator end()const{return const_iterator(head);}iterator end(){return 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());}void clear(){iterator first = begin();while (first != end()){first=erase(first);//!!!}}~list(){clear();delete head;head = nullptr;}void empty_initialize(){head = new node;head->next = head;head->prev = head;}list(){empty_initialize();}template <class InputIterator>list(InputIterator first, InputIterator end){empty_initialize();while (first != end){push_back(*first);++first;}}void swap(list<T>& lt){std::swap(head, lt.head);}list(const list<T>& lt){empty_initialize();list<T> tmp(lt.begin(), lt.end());swap(tmp);}list<T>& operator=(list<T> tmp){swap(tmp);return *this;}void push_back(const T& x)const{insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_front(){erase(begin());}void pop_back(){erase(--end());}void insert(iterator pos,const T& x){node* newnode = new node(x);node* cur = pos.pnode;node* prev = cur->prev;prev->next = newnode;newnode->prev = prev;cur->prev = newnode;newnode->next = cur;}void insert(const_iterator pos, const T& x)const{node* newnode = new node(x);node* cur = pos.pnode;node* prev = cur->prev;prev->next = newnode;newnode->prev = prev;cur->prev = newnode;newnode->next = cur;}iterator erase(iterator pos){node* cur = pos.pnode;node* prev = cur->prev;node* next = cur->next;prev->next = next;next->prev = prev;delete cur;return iterator(next);}const_iterator erase(const_iterator pos)const{node* cur = pos.pnode;node* prev = cur->prev;node* next = cur->next;prev->next = next;next->prev = prev;delete cur;return iterator(next);}private:node* head;//底层是一个哨兵结点};
}