• 【STL】:反向迭代器


    朋友们、伙计们,我们又见面了,本期来给大家解读一下有关反向迭代器的模拟实现,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

    C 语 言 专 栏:C语言:从入门到精通

    数据结构专栏:数据结构

    个  人  主  页 :stackY、

    C + + 专 栏   :C++

    Linux 专 栏  :Linux

    目录

    前言:

    1. 基本构造

    2. 接口完善

    3. 在list中使用反向迭代器

    list反向迭代器版本一:

    list反向迭代器版本二: 

    4. 在vector中使用反向迭代器 


    前言:

    前面的模拟实现vector和list中是没有实现反向迭代器的,反向迭代器与正向迭代器相比就是从数据的末端向前面访问遍历,但是两个迭代器的用法都是一样的,++就是下一个,*就可以访问到数据,但是它具体是怎么实现的呢?我们接下来看一看:

    1. 基本构造

    list的模拟实现中讲解了如何实现正向迭代器(包含const版本和非const版本)那么在本期实现反向迭代器的时候就有了一定的前车之鉴,比如const版本和非const版本不需要实现两份代码,可以采用模板实现泛型编程。

    反向迭代器的构造可以使用正向迭代器来进行复用,因为反向迭代器的++就是正向迭代器里面的--,所以在传递模板参数的时候可以直接传递一个迭代器,直接复用这个迭代器里面的各种结构完成反向迭代器的构造。这种方式叫做迭代器适配器。

    1. #pragma once
    2. namespace ywh
    3. {
    4. //反向迭代器
    5. template <class Iterator, class Ref, class Ptr>
    6. class ReverseIterator
    7. {
    8. public:
    9. typedef ReverseIterator Self;
    10. //构造
    11. ReverseIterator(Iterator it)
    12. :_it(it)
    13. {}
    14. private:
    15. Iterator _it;
    16. };
    17. }

    2. 接口完善

    反向迭代器的接口有++、--、*、->、!=、==,这些接口的实现都是可以通过使用模板参数中的迭代器来进行复用即可。

    头文件: reverse_iterator.h

    1. #pragma once
    2. namespace ywh
    3. {
    4. //反向迭代器
    5. template <class Iterator, class Ref, class Ptr>
    6. class ReverseIterator
    7. {
    8. public:
    9. typedef ReverseIterator Self;
    10. //构造
    11. ReverseIterator(Iterator it)
    12. :_it(it)
    13. {}
    14. //前置
    15. //operator++
    16. Self& operator++()
    17. {
    18. //复用传过来的迭代器里面的operator--
    19. --_it;
    20. return *this;
    21. }
    22. //operator--
    23. Self&operator++()
    24. {
    25. ++_it;
    26. return *this;
    27. }
    28. //operator*
    29. Ref operator*()
    30. {
    31. return *_it;
    32. }
    33. //operator->
    34. Ptr operator->()
    35. {
    36. return _it.operator->();
    37. }
    38. //operator==
    39. bool operator==(const Self& s)
    40. {
    41. return _it == s._it;
    42. }
    43. //operator!=
    44. bool operator!=(const Self& s)
    45. {
    46. return _it != s._it;
    47. }
    48. private:
    49. Iterator _it;
    50. };
    51. }

    3. 在list中使用反向迭代器

    要使用反向迭代器,首先得在list头文件中包含以下反向迭代器的头文件,然后进行构造:

    list反向迭代器版本一:

    1. #pragma once
    2. #include "reverse_iterator.h"
    3. namespace ywh
    4. {
    5. //链表结构
    6. template<class T>
    7. struct list_node
    8. {
    9. T _data; //节点中的数据
    10. list_node* _prev; //指向前一个节点的指针
    11. list_node* _next; //指向后一个节点的指针
    12. //构造
    13. list_node(const T& x = T())
    14. :_data(x)
    15. , _prev(nullptr)
    16. , _next(nullptr)
    17. {}
    18. };
    19. //正向迭代器
    20. // 类型模板参数 传递引用 传递指针
    21. template<class T, class Ref, class Ptr>
    22. struct __list_iterator
    23. {
    24. typedef list_node Node;
    25. typedef __list_iterator self;
    26. Node* _node;
    27. //迭代器构造
    28. __list_iterator(Node* node)
    29. :_node(node)
    30. {}
    31. //前置
    32. //operator++
    33. self& operator++()
    34. {
    35. _node = _node->_next;
    36. return *this;
    37. }
    38. //operator--
    39. self& operator--()
    40. {
    41. _node = _node->_prev;
    42. return *this;
    43. }
    44. //后置
    45. self operator++(int)
    46. {
    47. self* tmp(_node);
    48. _node = _node->_next;
    49. return tmp;
    50. }
    51. //operator--
    52. self operator--(int)
    53. {
    54. self* tmp(_node);
    55. _node = _node->_prev;
    56. return tmp;
    57. }
    58. //operator*
    59. Ref operator*()
    60. {
    61. return _node->_data;
    62. }
    63. //operator->
    64. Ptr operator->()
    65. {
    66. return &_node->_data;
    67. }
    68. //operator!=
    69. bool operator!=(const self& s)
    70. {
    71. return _node != s._node;
    72. }
    73. //operator==
    74. bool operator==(const self& s)
    75. {
    76. return _node == s._node;
    77. }
    78. };
    79. //list结构
    80. template<class T>
    81. class list
    82. {
    83. public:
    84. typedef list_node Node;
    85. typedef __list_iterator iterator; //非const迭代器
    86. typedef __list_iteratorconst T&, const T*> const_iterator; //const迭代器
    87. typedef ReverseIterator reverse_iterator; //反向迭代器
    88. typedef ReverseIteratorconst T&, const T*> const_reverse_iterator; //反向迭代器
    89. public:
    90. 基本构造///
    91. //...
    92. ///正向迭代器
    93. iterator begin()
    94. {
    95. return iterator(_head->_next); //使用匿名对象进行构造
    96. }
    97. iterator end()
    98. {
    99. return iterator(_head);
    100. }
    101. const_iterator begin() const
    102. {
    103. return const_iterator(_head->_next);
    104. }
    105. const_iterator end() const
    106. {
    107. return const_iterator(_head);
    108. }
    109. //反向迭代器/
    110. reverse_iterator rbegin()
    111. {
    112. return reverse_iterator(--end());
    113. }
    114. reverse_iterator rend()
    115. {
    116. return reverse_iterator(end());
    117. }
    118. const_reverse_iterator rbegin() const
    119. {
    120. return const_reverse_iterator(--end());
    121. }
    122. const_reverse_iterator rend() const
    123. {
    124. return const_reverse_iterator(end());
    125. }
    126. ///修改相关接口
    127. //...
    128. private:
    129. Node* _head; //链表的头节点
    130. size_t _size; //节点个数
    131. };
    132. }

    list反向迭代器版本二: 

    我们也可以看一下库里面list的反向迭代器如何设计:

    可以看到库里面的玩法是一种对称的结构,这种对称的结构在解引用访问时访问的是下一个节点的元素,这样子写是比较好理解的,正向的起始就是反向的结束,正向的结束就是反向的起始,那么我们也可以来按照这种写法来写一下:

    头文件:reverse_iterator.h

    1. #pragma once
    2. namespace ywh
    3. {
    4. //反向迭代器
    5. template <class Iterator, class Ref, class Ptr>
    6. class ReverseIterator
    7. {
    8. public:
    9. typedef ReverseIterator Self;
    10. //构造
    11. ReverseIterator(Iterator it)
    12. :_it(it)
    13. {}
    14. //前置
    15. //operator++
    16. Self& operator++()
    17. {
    18. //复用传过来的迭代器里面的operator--
    19. --_it;
    20. return *this;
    21. }
    22. //operator--
    23. Self&operator++()
    24. {
    25. ++_it;
    26. return *this;
    27. }
    28. //operator*
    29. Ref operator*()
    30. {
    31. Iterator cur = _it;
    32. //返回下一个节点的数据
    33. return *(--cur);
    34. }
    35. //operator->
    36. Ptr operator->()
    37. {
    38. return _it.operator->();
    39. }
    40. //operator==
    41. bool operator==(const Self& s)
    42. {
    43. return _it == s._it;
    44. }
    45. //operator!=
    46. bool operator!=(const Self& s)
    47. {
    48. return _it != s._it;
    49. }
    50. private:
    51. Iterator _it;
    52. };
    53. }

    头文件:List.h

    1. #pragma once
    2. #include "reverse_iterator.h"
    3. namespace ywh
    4. {
    5. //链表结构
    6. template<class T>
    7. struct list_node
    8. {
    9. T _data; //节点中的数据
    10. list_node* _prev; //指向前一个节点的指针
    11. list_node* _next; //指向后一个节点的指针
    12. //构造
    13. list_node(const T& x = T())
    14. :_data(x)
    15. , _prev(nullptr)
    16. , _next(nullptr)
    17. {}
    18. };
    19. //正向迭代器
    20. // 类型模板参数 传递引用 传递指针
    21. template<class T, class Ref, class Ptr>
    22. struct __list_iterator
    23. {
    24. typedef list_node Node;
    25. typedef __list_iterator self;
    26. Node* _node;
    27. //迭代器构造
    28. __list_iterator(Node* node)
    29. :_node(node)
    30. {}
    31. //前置
    32. //operator++
    33. self& operator++()
    34. {
    35. _node = _node->_next;
    36. return *this;
    37. }
    38. //operator--
    39. self& operator--()
    40. {
    41. _node = _node->_prev;
    42. return *this;
    43. }
    44. //后置
    45. self operator++(int)
    46. {
    47. self* tmp(_node);
    48. _node = _node->_next;
    49. return tmp;
    50. }
    51. //operator--
    52. self operator--(int)
    53. {
    54. self* tmp(_node);
    55. _node = _node->_prev;
    56. return tmp;
    57. }
    58. //operator*
    59. Ref operator*()
    60. {
    61. return _node->_data;
    62. }
    63. //operator->
    64. Ptr operator->()
    65. {
    66. return &_node->_data;
    67. }
    68. //operator!=
    69. bool operator!=(const self& s)
    70. {
    71. return _node != s._node;
    72. }
    73. //operator==
    74. bool operator==(const self& s)
    75. {
    76. return _node == s._node;
    77. }
    78. };
    79. //list结构
    80. template<class T>
    81. class list
    82. {
    83. public:
    84. typedef list_node Node;
    85. typedef __list_iterator iterator; //非const迭代器
    86. typedef __list_iteratorconst T&, const T*> const_iterator; //const迭代器
    87. typedef ReverseIterator reverse_iterator; //反向迭代器
    88. typedef ReverseIteratorconst T&, const T*> const_reverse_iterator; //反向迭代器
    89. public:
    90. 基本构造///
    91. //...
    92. ///正向迭代器
    93. iterator begin()
    94. {
    95. return iterator(_head->_next); //使用匿名对象进行构造
    96. }
    97. iterator end()
    98. {
    99. return iterator(_head);
    100. }
    101. const_iterator begin() const
    102. {
    103. return const_iterator(_head->_next);
    104. }
    105. const_iterator end() const
    106. {
    107. return const_iterator(_head);
    108. }
    109. //反向迭代器/
    110. reverse_iterator rbegin()
    111. {
    112. return reverse_iterator(end());
    113. }
    114. reverse_iterator rend()
    115. {
    116. return reverse_iterator(begin());
    117. }
    118. const_reverse_iterator rbegin() const
    119. {
    120. return const_reverse_iterator(end());
    121. }
    122. const_reverse_iterator rend() const
    123. {
    124. return const_reverse_iterator(begin());
    125. }
    126. ///修改相关接口
    127. //...
    128. private:
    129. Node* _head; //链表的头节点
    130. size_t _size; //节点个数
    131. };
    132. }

    4. 在vector中使用反向迭代器 

    vector中的反向迭代器不建议使用上面的版本一,因为begin()和end()是传值返回,是临时对象,而临时对象具有常性,不好进行修改,所以还是比较建议使用这种对称的结构。

    头文件:Vector.h

    1. #pragma once
    2. #include
    3. #include "reverse_iterator.h"
    4. namespace ywh
    5. {
    6. template<class T>
    7. class vector
    8. {
    9. public:
    10. typedef T* iterator;
    11. typedef const T* const_iterator;
    12. typedef ReverseIterator reverse_iterator;
    13. typedef ReverseIteratorconst T&, const T*> const_reverse_iterator;
    14. public:
    15. /正向迭代器
    16. iterator begin()
    17. {
    18. return _start;
    19. }
    20. iterator end()
    21. {
    22. return _finish;
    23. }
    24. const_iterator begin() const
    25. {
    26. return _start;
    27. }
    28. const_iterator end() const
    29. {
    30. return _finish;
    31. }
    32. /反向迭代器/
    33. reverse_iterator rbegin()
    34. {
    35. return reverse_iterator(end());
    36. }
    37. reverse_iterator rend()
    38. {
    39. return reverse_iterator(begin());
    40. }
    41. const_reverse_iterator rbegin() const
    42. {
    43. return const_reverse_iterator(end());
    44. }
    45. const_reverse_iterator rend() const
    46. {
    47. return const_reverse_iterator(begin());
    48. }
    49. /基本构造///
    50. //...
    51. ///容量
    52. //...
    53. ///修改
    54. //...
    55. private:
    56. iterator _start = nullptr; //起始位置
    57. iterator _finish = nullptr; //有效数据位置
    58. iterator _end_of_storage = nullptr; //结束位置
    59. };
    60. }

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

  • 相关阅读:
    Android UI freeze分析
    Postman —— 配置环境变量
    贝塞尔函数
    建议收藏!混迹职场多年总结出的8大技巧!
    17.3.2.5 灰度(内存处理)
    数字化转型“黑话”知多少?一文让你不仅听得懂、还会落地执行
    【BOOST C++ 14 消息编程】(3) 集体数据交换
    3.1python基础01
    伴随第四次电气革命实现半导体行业的可持续智能增长
    智慧灯杆网关管理平台:城市建设的智慧化之道
  • 原文地址:https://blog.csdn.net/Yikefore/article/details/134217776