• 【C++/STL】list(常见接口、模拟实现、反向迭代器)


     🌈个人主页:秦jh_-CSDN博客
    🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12575764.html?spm=1001.2014.3001.5482

    9efbcbc3d25747719da38c01b3fa9b4f.gif

    目录

    前言

     list的常见接口

    对迭代器的封装

     节点

    重载->

    const迭代器

    list与vector的对比

    反向迭代器

     反向迭代器完整代码

    list完整代码


    前言

        💬 hello! 各位铁子们大家好哇。

                 今日更新了list的相关内容
        🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

     list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。

     list的常见接口

    迭代器的封装

    因为list的空间不是连续的,不能用原生指针,必须对其进行封装。 

     节点

    重载->

    当数据是自定义类型时,想通过->访问,就必须重载。 

    const迭代器

    用const迭代器,需要重新弄一个类,而const迭代器跟普通迭代器基本一样,只修改了部分,如果为此就重新弄一个类,代码就太冗余了。

      下面是进行的优化:

    本质相当于写了一个类模板,编译器实例化生成了两个类。

    list与vector的对比

    反向迭代器

    反向迭代器的++就是正向迭代器的--,反向迭代器的--就是正向迭代器的++,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行 包装即可。

     反向迭代器完整代码

    1. #pragma once
    2. //所以容器的反向迭代器
    3. //迭代器适配器
    4. namespace qjh
    5. {
    6. //vector::iterator
    7. template<class Iterator,class Ref,class Ptr> //给谁的正向迭代器,就适配出对应的反向迭代器
    8. struct ReverseIterator
    9. {
    10. typedef ReverseIterator Self;
    11. Iterator _it;
    12. ReverseIterator(Iterator it)
    13. :_it(it)
    14. {}
    15. Ref operator*()
    16. {
    17. Iterator tmp = _it; //不能修改_it,得用临时变量放回
    18. return *(--tmp);
    19. }
    20. Ptr operator->()
    21. {
    22. //return _it->;
    23. //return _it.operator->();
    24. return &(operator*());
    25. }
    26. Self& operator++()
    27. {
    28. --_it;
    29. return *this;
    30. }
    31. Self& operator--()
    32. {
    33. ++_it;
    34. return *this;
    35. }
    36. bool operator!=(const Self& s)
    37. {
    38. return _it != s._it;
    39. }
    40. };
    41. }

    list完整代码

    1. #pragma once
    2. #include
    3. #include"ReverseIterator.h"
    4. namespace qjh
    5. {
    6. template<class T>
    7. struct ListNode //需要全部被公开,用struct
    8. {
    9. ListNode* _next;
    10. ListNode* _prev;
    11. T _data;
    12. ListNode(const T& x=T())
    13. :_next(nullptr)
    14. ,_prev(nullptr)
    15. ,_data(x)
    16. {}
    17. };
    18. template<class T,class Ref,class Ptr>
    19. struct ListIterator //对指针进行封装,因为结点的空间不是连续的
    20. {
    21. typedef ListNode Node;
    22. typedef ListIterator Self;
    23. Node* _node;
    24. ListIterator(Node* node)
    25. :_node(node)
    26. {}
    27. //*it
    28. //T& operator*()
    29. Ref operator*()
    30. {
    31. return _node->_data;
    32. }
    33. //T* operator->()
    34. Ptr operator->()
    35. {
    36. return &_node->_data;
    37. }
    38. //++it
    39. Self& operator++()
    40. {
    41. _node = _node->_next;
    42. return *this;
    43. }
    44. //it++
    45. Self& operator++(int)
    46. {
    47. Self tmp(*this);
    48. _node = _node->_next;
    49. return tmp;
    50. }
    51. //--it
    52. Self& operator--()
    53. {
    54. _node = _node->_prev;
    55. return *this;
    56. }
    57. //it--
    58. Self& operator--(int)
    59. {
    60. Self tmp(*this);
    61. _node = _node->_prev;
    62. return tmp;
    63. }
    64. bool operator!=(const Self& it)
    65. {
    66. return _node != it._node;
    67. }
    68. bool operator==(const Self& it)
    69. {
    70. return _node == it._node;
    71. }
    72. };
    73. //template
    74. //struct ListConstIterator //对指针进行封装,因为结点的空间不是连续的
    75. //{
    76. // typedef ListNode Node;
    77. // typedef ListConstIterator Self;
    78. // Node* _node;
    79. // ListConstIterator(Node* node)
    80. // :_node(node)
    81. // {}
    82. // //*it
    83. // const T& operator*()
    84. // {
    85. // return _node->_data;
    86. // }
    87. // const T* operator->()
    88. // {
    89. // return &_node->_data;
    90. // }
    91. // //++it
    92. // Self& operator++()
    93. // {
    94. // _node = _node->_next;
    95. // return *this;
    96. // }
    97. // //it++
    98. // Self& operator++(int)
    99. // {
    100. // Self tmp(*this);
    101. // _node = _node->_next;
    102. // return tmp;
    103. // }
    104. // //--it
    105. // Self& operator--()
    106. // {
    107. // _node = _node->_prev;
    108. // return *this;
    109. // }
    110. // //it--
    111. // Self& operator--(int)
    112. // {
    113. // Self tmp(*this);
    114. // _node = _node->_prev;
    115. // return tmp;
    116. // }
    117. // bool operator!=(const Self& it)
    118. // {
    119. // return _node != it._node;
    120. // }
    121. // bool operator==(const Self& it)
    122. // {
    123. // return _node == it._node;
    124. // }
    125. //};
    126. template<class T>
    127. class list
    128. {
    129. typedef ListNode Node;
    130. public:
    131. /*typedef ListIterator iterator;
    132. typedef ListConstIterator const_iterator;*/
    133. typedef ListIterator iterator;
    134. typedef ListIteratorconst T&,const T*> const_iterator;
    135. typedef ReverseIterator reverse_iterator;
    136. typedef ReverseIteratorconst T&, const T*> const_reverse_iterator;
    137. reverse_iterator rbegin()
    138. {
    139. return reverse_iterator(end());
    140. }
    141. reverse_iterator rend()
    142. {
    143. return reverse_iterator(begin());
    144. }
    145. iterator begin()
    146. {
    147. return iterator(_head->_next);
    148. }
    149. iterator end()
    150. {
    151. return iterator(_head);
    152. }
    153. //const迭代器需要迭代器指向的内容不能修改!const iterator不是我们需要的const迭代器
    154. //const 迭代器本身可以++等操作
    155. const_iterator begin() const
    156. {
    157. return const_iterator(_head->_next);
    158. }
    159. const_iterator end() const
    160. {
    161. return const_iterator(_head);
    162. }
    163. void empty_init()
    164. {
    165. _head = new Node;
    166. _head->_next = _head;
    167. _head->_prev = _head;
    168. _size = 0;
    169. }
    170. list()
    171. {
    172. empty_init();
    173. }
    174. list(initializer_list<int> il)
    175. {
    176. empty_init();
    177. for (auto& e : il)
    178. {
    179. push_back(e);
    180. }
    181. }
    182. //lt2(lt1)
    183. list(const list& lt)
    184. {
    185. empty_init();
    186. for (auto& e : lt)
    187. {
    188. push_back(e);
    189. }
    190. }
    191. void swap(list& lt)
    192. {
    193. std::swap(_head, lt._head);
    194. std::swap(_size, lt._size);
    195. }
    196. //lt1=lt3
    197. list& operator=(list lt)
    198. {
    199. swap(lt);
    200. return *this;
    201. }
    202. void clear()
    203. {
    204. iterator it = begin();
    205. while (it != end())
    206. {
    207. it = erase(it);
    208. }
    209. }
    210. ~list()
    211. {
    212. clear();
    213. delete _head;
    214. _head = nullptr;
    215. }
    216. //void push_back(const T& x)
    217. //{
    218. // Node* newnode = new Node(x);
    219. // Node* tail = _head->_prev;
    220. // tail->_next = newnode;
    221. // newnode->_prev = tail;
    222. // newnode->_next = _head;
    223. // _head->_prev = newnode;
    224. //}
    225. void push_back(const T& x)
    226. {
    227. insert(end(), x);
    228. }
    229. void push_front(const T& x)
    230. {
    231. insert(begin(), x);
    232. }
    233. void pop_back()
    234. {
    235. erase(--end());//迭代器不能-1,只能用--
    236. }
    237. void pop_front()
    238. {
    239. erase(begin());
    240. }
    241. void insert(iterator pos, const T& val)
    242. {
    243. Node* cur = pos._node;
    244. Node* newnode = new Node(val);
    245. Node* prev = cur->_prev;
    246. prev->_next = newnode;
    247. newnode->_prev = prev;
    248. newnode->_next = cur;
    249. cur->_prev = newnode;
    250. _size++;
    251. }
    252. iterator erase(iterator pos) //节点失效了,需要返回下一个节点
    253. {
    254. Node* cur = pos._node;
    255. Node* prev = cur->_prev;
    256. Node* next = cur->_next;
    257. prev->_next = next;
    258. next->_prev = prev;
    259. delete cur;
    260. _size--;
    261. return iterator(next); //匿名对象
    262. }
    263. size_t size() const
    264. {
    265. return _size;
    266. }
    267. bool empty()
    268. {
    269. return _size == 0;
    270. }
    271. private:
    272. Node* _head;
    273. size_t _size;
    274. };
    275. void test_list1()
    276. {
    277. list<int> lt;
    278. lt.push_back(1);
    279. lt.push_back(2);
    280. lt.push_back(3);
    281. lt.push_back(4);
    282. lt.push_back(5);
    283. list<int>::iterator it = lt.begin();
    284. while (it != lt.end())
    285. {
    286. cout << *it << " ";
    287. ++it;
    288. }
    289. cout << endl;
    290. lt.push_front(10);
    291. lt.push_front(20);
    292. lt.push_front(30);
    293. for (auto e : lt)
    294. {
    295. cout << e << " ";
    296. }
    297. cout << endl;
    298. lt.pop_back();
    299. lt.pop_back();
    300. lt.pop_front();
    301. lt.pop_front();
    302. for (auto e : lt)
    303. {
    304. cout << e << " ";
    305. }
    306. cout << endl;
    307. }
    308. struct A
    309. {
    310. int _a1;
    311. int _a2;
    312. A(int a1 = 0, int a2 = 0)
    313. :_a1(a1)
    314. ,_a2(a2)
    315. {}
    316. };
    317. void test_list2()
    318. {
    319. list lt;

  • 相关阅读:
    rabbitmq 使用SAC队列实现顺序消息
    卷妹带你回顾Java基础(一)每日更新Day4
    LeetCode-146. LRU Cache [C++][Java]
    springboot系列(十五):如何实现静态邮件模板发送?你一定得会|超级详细,建议收藏
    毕业论文中的数据分析无从下手?
    SpringBoot整合Elasticsearch实现分页条件查询及注意事项
    配置Linux文件句柄数
    awoo‘s Favorite Problem(思维)
    notification控件 通知栏
    【C语言 | 符号】C语言中符号易出错的地方
  • 原文地址:https://blog.csdn.net/qinjh_/article/details/137724497