模拟实现list和vector反向迭代器

news/2024/12/28 20:06:04/

学习这部分知识,需要你了解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;//底层是一个哨兵结点};
}


http://www.ppmy.cn/news/10653.html

相关文章

【Python】基于高德地图API的坐标转换函数

【Python】基于高德地图API的坐标转换函数 API申请&#xff1a; lbs.amap.com/api/webservice/guide/api/convert/产品介绍 坐标转换是一类简单的HTTP接口&#xff0c;能够将用户输入的非高德坐标&#xff08;GPS坐标、mapbar坐标、baidu坐标&#xff09;转换成高德坐标。 …

[Linux]Linux调试器-gdb

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【LINUX】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文…

智引未来,深兰科技机器人家族首次亮相TechG

12月31日&#xff0c;首届上海国际消费电子技术展(简称TechG)在南京国际博览中心圆满落下帷幕。作为全球消费电子技术领域的顶级行业盛会&#xff0c;本届展会共吸引了来自全球的300余家企业出席&#xff0c;共计逾2万名专业人士到场参观。阿里巴巴、蚂蚁科技、海尔、科大讯飞、…

基于Android的课堂评分系统

需求信息&#xff1a; 管理员 1&#xff1a;登录 2&#xff1a;学生教师课程管理&#xff0c;可以增加 教师 1&#xff1a;登录 2&#xff1a;选择要上课的学生&#xff0c;设置该课程成绩比例 3&#xff1a;出勤管理 请假-2&#xff0c;旷课-3&#xff0c;迟到早退-1 4&#x…

KMP算法--子串查找问题

目录 一.前言 二.KMP算法简介 三.关键概念1&#xff1a;字符串的前后缀 四. 关键概念2&#xff1a;字符串相等前后缀与最长相等前后缀长度 五.关键概念3&#xff1a;Next数组 六.Next数组在算法中的应用&#xff1a; 七.模式串Next数组的构建 先膜拜一下三位神仙&#x…

【dp】排列问题

文章目录零钱兑换组合总和IV零钱兑换 很明显&#xff0c;本题使用完全背包算法&#xff0c;求解的是组合数&#xff0c;直接使用完全背包算法即可&#xff0c;为什么是组合数呢&#xff1f; 如果题目说 amount5&#xff0c;coins[1,2,5] 有9种方法&#xff0c;那就是排列数&am…

天然气井远程监控解决方案

天然气井&#xff08;也称天然气计量井&#xff09;&#xff0c;是一种主要以气体计量为主的一种能源设备&#xff0c;也可以称为储气装置。 由于天然气在开采、运输、生产、使用过程中都会产生大量的热能&#xff0c;同时也会消耗大量的能量&#xff0c;因此在开采天然气过程中…

[JavaEE]synchronized 与 死锁

专栏简介: JavaEE从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 1.synchronized 的特性 2. synchronized 使用示例:…