• STL——list


    目录

    list的介绍

    list的构造

    list iterator的使用

    list capacity

    list element access

    list modififiers

    list的迭代器失效

    关于迭代器

    list的模拟实现

    main.cpp

    List.h


    C语言总结在这常见八大排序在这

    作者和朋友建立的社区:非科班转码社区-CSDN社区云💖💛💙

    期待hxd的支持哈🎉 🎉 🎉

    最后是打鸡血环节:你只管努力,剩下的交给天意🚀 🚀 🚀  

    list的介绍

    list - C++ Reference (cplusplus.com)

     1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。

    2. list 底层带头双向循环链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
    3. list forward_list 非常相似:最主要的不同在于 forward_list 是单链表,只能朝前迭代,已让其更简单高效。
    4. 与其他的序列式容器相比 (array vector deque) list 通常在任意位置进行插入、移除元素的执行效率更好。
    5. 与其他序列式容器相比, list forward_list 最大的缺陷是不支持任意位置的随机访问,比如:要访问 list的第6 个元素,必须从已知的位置 ( 比如头部或者尾部 ) 迭代到该位置,在这段位置上迭代需要线性的时间
    另外, list 还需要一些额外的空间,以保存每个节点的相关联信息 ( 对于存储类型较小元素的大 list 来说这可能是一个重要的因素)
    早在C语言章节就已经实现过了带头双向循环链表了,但是这次C++不同的是迭代器类的实现,与以往有较大区别,注意理解

    list的构造

    构造函数( (constructor)
    接口说明
    list (size_type n, const value_type& val = value_type())
    构造的 list 中包含 n 个值为 val 的元素
    list()
    构造空的 list
    list (const list& x)
    拷贝构造函数
    list (InputIterator fifirst, InputIterator last)
    [fifirst, last) 区间中的元素构造 list

     其实学到这里了这什么函数是用来干什么的应该是一看就会了,但是考虑到文章的完整性和一些小白,就还是“冗余”得把这些函数及解释写了出来

    list iterator的使用

    函数声明
    接口说明
    begin +
    end
    返回第一个元素的迭代器 + 返回最后一个元素下一个位置的迭代器
                                    end()就是头的位置
    rbegin +
    rend
    返回第一个元素的 reverse_iterator, end 位置 返回最后一个元素下一个位置的 reverse_iterator, begin 位置

    PS:

    1. begin end 为正向迭代器,对迭代器执行 ++ 操作,迭代器向后移动
    2. rbegin(end) rend(begin) 为反向迭代器,对迭代器执行 ++ 操作,迭代器向前移动

    list capacity

    函数声明
    接口说明
    empty
    检测 list 是否为空,是返回 true ,否则返回 false
    size
    返回 list 中有效节点的个数

    list element access

    函数声明
    接口说明
    front
    返回 list 的第一个节点中值的引用
    back
    返回 list 的最后一个节点中值的引用

    list modififiers

    函数声明
    接口说明
    push_front
    list 首元素前插入值为 val 的元素
    pop_front
    删除 list 中第一个元素
    push_back
    list 尾部插入值为 val 的元素
    pop_back
    删除 list 中最后一个元素
    insert
    list position 位置中插入值为 val 的元素
    erase
    删除 list position 位置的元素
    swap
    交换两个 list 中的元素
    clear
    清空 list 中的有效元素

    list的迭代器失效

    迭代器失效即迭代器所指向的节点的无效,即该节 点被删除了 。因为 list 的底层结构为带头结点的双向循环链表 ,因此 list 中进行插入时是不会导致 list 的迭代 器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响

    关于迭代器

    迭代器是对原生态指针 ( 节点指针 ) 进行封装
    插入元素不会导致迭代器失效, 删除元素时,只会导致当前迭代 器失效,其他迭代器不受影响

    list的模拟实现

    main.cpp

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"List.h"
    3. int main()
    4. {
    5. my_list<int> l;
    6. l.insert(l.begin(), 1);
    7. l.insert(l.end(), 2);
    8. l.insert(l.end(), 2);
    9. l.insert(l.end(), 2);
    10. l.insert(l.end(), 7);
    11. l.insert(l.end(), 5);
    12. l.push_back(100);
    13. l.push_back(150);
    14. l.push_back(11);
    15. l.push_front(33);
    16. l.push_front(66);
    17. my_list<int>::iterator it = l.begin();
    18. while (it != l.end())
    19. {
    20. cout << *it << " ";
    21. it++;
    22. }
    23. cout << endl;
    24. cout << endl;
    25. l.pop_back();
    26. l.pop_back();
    27. l.pop_front();
    28. l.pop_front();
    29. it = l.begin();
    30. it = l.begin();
    31. while (it != l.end())
    32. {
    33. cout << *it << " ";
    34. it++;
    35. }
    36. cout << endl;
    37. cout << endl;
    38. it = l.begin();
    39. while (it != l.end())
    40. {
    41. if (*it % 2 == 0)
    42. {
    43. it = l.erase(it);
    44. }
    45. else
    46. {
    47. it++;
    48. }
    49. }
    50. it = l.begin();
    51. while (it != l.end())
    52. {
    53. cout << *it << " ";
    54. it++;
    55. }
    56. cout << endl;
    57. cout << endl;
    58. my_list<int> l2(l);
    59. it = l2.begin();
    60. while (it != l2.end())
    61. {
    62. cout << *it << " ";
    63. it++;
    64. }
    65. cout << endl;
    66. cout << endl;
    67. it = l.begin();
    68. my_list<int>::iterator it2 = --it;
    69. cout << *it << endl;
    70. cout << *it2 << endl;
    71. //cout << l.front() << endl;
    72. //cout << l.back() << endl;
    73. //cout << *(l.begin()--) << endl;
    74. //cout << *(--l.begin()) << endl;
    75. //cout << *(l.begin()++) << endl;
    76. //cout << *(++l.begin()) << endl;
    77. }

    List.h

    1. #include
    2. #include
    3. #include
    4. using std::cout;
    5. using std::endl;
    6. // List的节点类
    7. template<class T>
    8. struct ListNode
    9. {
    10. ListNode(const T& val = T())
    11. :_pPre(nullptr),
    12. _pNext(nullptr),
    13. _val(val)
    14. {}
    15. ListNode* _pPre;
    16. ListNode* _pNext;
    17. T _val;
    18. };
    19. //List的迭代器类
    20. template<class T, class Ref, class Ptr>
    21. struct ListIterator
    22. {
    23. typedef ListNode* PNode;
    24. typedef ListIterator Self;
    25. //给reverse_iterator 用 ,这样反向迭代器类就可以不用传后面两个参数了
    26. typedef T& Ref;
    27. typedef T* Ptr;
    28. ListIterator(PNode pNode = nullptr)
    29. :_pNode(pNode)
    30. {}
    31. //it1(it2)
    32. ListIterator(const Self& l)
    33. {
    34. _pNode = l._pNode;
    35. }
    36. //模板参数 Ref Ptr 的作用 ,返回 const和非const对象(由传参决定)
    37. //(其实就是两个类了,同一个类模板,参数不同,会实例化出不同类型的对象)
    38. Ref operator*()
    39. {
    40. return _pNode->_val;
    41. }
    42. Ptr operator->() //注意返回值
    43. {
    44. //return &(operator*());
    45. return &_pNode->_val;
    46. }
    47. Self& operator++()
    48. {
    49. _pNode = _pNode->_pNext;
    50. return*this;
    51. }
    52. Self operator++(int)
    53. {
    54. Self tmp(*this);
    55. _pNode = _pNode->_pNext;
    56. return tmp;
    57. }
    58. Self& operator--()
    59. {
    60. _pNode = _pNode->_pPre;
    61. return *this;
    62. }
    63. Self& operator--(int)
    64. {
    65. Self tmp = *this;
    66. _pNode = _pNode->_pPre;
    67. return tmp;
    68. }
    69. bool operator!=(const Self& l)
    70. {
    71. return !(operator==(l));
    72. }
    73. bool operator==(const Self& l)
    74. {
    75. return _pNode == l._pNode;
    76. }
    77. PNode _pNode;
    78. };
    79. //List的反向迭代器类
    80. template<class ListIterator>
    81. struct ReverseIterator
    82. {
    83. typedef typename ListIterator::Ref Ref;
    84. typedef typename ListIterator::Ptr Ptr;
    85. typedef ReverseIterator Self;
    86. ReverseIterator(ListIterator it)
    87. :_it(it)
    88. {}
    89. //it1(it2)
    90. ReverseIterator(const Self& l)
    91. {
    92. _it = l._it;
    93. }
    94. Ref operator*()
    95. {
    96. ListIterator temp(_it);
    97. --temp;
    98. return *temp;
    99. }
    100. Ptr operator->() //注意返回值
    101. {
    102. return &(operator*());
    103. }
    104. Self& operator++()
    105. {
    106. --_it;
    107. return *this;
    108. }
    109. Self operator++(int)
    110. {
    111. Self temp(*this);
    112. --_it;
    113. return temp;
    114. }
    115. Self& operator--()
    116. {
    117. ++_it;
    118. return *this;
    119. }
    120. Self& operator--(int)
    121. {
    122. Self temp(*this);
    123. ++_it;
    124. return temp;
    125. }
    126. bool operator!=(const Self& l)
    127. {
    128. return _it != l._it;
    129. }
    130. bool operator==(const Self& l)
    131. {
    132. return _it == l._it;
    133. }
    134. ListIterator _it;
    135. };
    136. //list类
    137. template<class T>
    138. class my_list
    139. {
    140. typedef ListNode Node;
    141. typedef Node* PNode;
    142. public:
    143. typedef ListIterator iterator;
    144. //只有后面两个加上const是因为只有这里是控制const迭代器不能修改的地方
    145. typedef ListIteratorconst T&, const T&> const_iterator;
    146. typedef ReverseIterator reverse_itrator;
    147. typedef ReverseIterator const_reverse_itrator;
    148. public:
    149. ///
    150. // List的构造
    151. my_list()
    152. {
    153. CreateHead();
    154. }
    155. my_list(int n, const T& value = T())
    156. {
    157. CreateHead();
    158. for (int i = 0; i < n; i++)
    159. {
    160. push_back(value);
    161. }
    162. }
    163. template <class Iterator>
    164. my_list(Iterator first, Iterator last)
    165. {
    166. CreateHead();
    167. while (first != last)
    168. {
    169. push_back(*first);
    170. first++;
    171. }
    172. }
    173. //lt1(lt2) lt2
    174. my_list(const my_list& l)
    175. {
    176. CreateHead();
    177. my_list tmp(l.begin(), l.end());
    178. this->swap(tmp);
    179. }
    180. my_list& operator=(my_list l)
    181. {
    182. this->swap(l);
    183. return *this;
    184. }
    185. ~my_list()
    186. {
    187. clear();
    188. delete _pHead;
    189. _pHead = nullptr;
    190. }
    191. ///
    192. // List Iterator
    193. iterator begin()
    194. {
    195. return iterator(_pHead->_pNext);
    196. }
    197. iterator end()
    198. {
    199. return iterator(_pHead);
    200. }
    201. const_iterator begin()const
    202. {
    203. return const_iterator(_pHead->_pNext);
    204. }
    205. const_iterator end()const
    206. {
    207. return const_iterator(_pHead);
    208. }
    209. // List Reversez_Iterator
    210. reverse_itrator rbegin()
    211. {
    212. return reverse_itrator(iterator);
    213. }
    214. reverse_itrator rend()
    215. {
    216. return reverse_itrator(iterator);
    217. }
    218. const_reverse_itrator crbegin()const
    219. {
    220. return const_reverse_itrator(const_iterator);
    221. }
    222. const_reverse_itrator crend()const
    223. {
    224. return const_reverse_itrator(const_iterator);
    225. }
    226. ///
    227. // List Capacity
    228. size_t size()const
    229. {
    230. size_t sz = 0;
    231. iterator it = begin();
    232. while (it != end())
    233. {
    234. sz++;
    235. it++;
    236. }
    237. return sz;
    238. }
    239. bool empty()const
    240. {
    241. return size() == 0;
    242. }
    243. // List Access
    244. T& front()
    245. {
    246. return _pHead->_pNext->_val;
    247. }
    248. const T& front()const
    249. {
    250. return _pHead->_pNext->_val;
    251. }
    252. T& back()
    253. {
    254. return _pHead->_pPre->_val;
    255. }
    256. const T& back()const
    257. {
    258. return _pHead->_pPre->_val;
    259. }
    260. // List Modify
    261. void push_back(const T& val) { insert(end(), val); }
    262. void pop_back() { erase(--end()); }
    263. void push_front(const T& val) { insert(begin(), val); }
    264. void pop_front() { erase(begin()); }
    265. // 在pos位置前插入值为val的节点
    266. iterator insert(iterator pos, const T& val)
    267. {
    268. // prev new cur
    269. Node* newnode = new Node(val);
    270. Node* cur = pos._pNode;
    271. Node* prev = cur->_pPre;
    272. prev->_pNext = newnode;
    273. newnode->_pPre = prev;
    274. newnode->_pNext = cur;
    275. cur->_pPre = newnode;
    276. //返回新插入的位置
    277. return iterator(newnode);
    278. }
    279. // 删除pos位置的节点,返回该节点的下一个位置
    280. iterator erase(iterator pos)
    281. {
    282. assert(pos != end());
    283. Node* cur = pos._pNode;
    284. Node* prev = cur->_pPre;
    285. Node* next = cur->_pNext;
    286. prev->_pNext = next;
    287. next->_pPre = prev;
    288. delete cur;
    289. //匿名对象
    290. return iterator(next);
    291. }
    292. void clear()
    293. {
    294. iterator it = begin();
    295. while (it != end())
    296. {
    297. it = erase(it);
    298. it++;
    299. }
    300. }
    301. void swap(my_list& l)
    302. {
    303. std::swap(_pHead, l._pHead);
    304. }
    305. private:
    306. void CreateHead()
    307. {
    308. _pHead = new Node();
    309. _pHead->_pPre = _pHead;
    310. _pHead->_pNext = _pHead;
    311. }
    312. PNode _pHead;
    313. };

    最后的最后,创作不易,希望读者三连支持💖

    赠人玫瑰,手有余香💖

  • 相关阅读:
    Azure 机器学习 - 如何使用模板创建安全工作区
    全民拼购模式是怎么卖货的?营销模式解析
    我对微服务架构的简单理解
    Jquery中事件
    警告-Ubuntu提示W: Possible missing firmware xxx解决方法
    顶刊TPAMI 2022!基于不同数据模态的行为识别:最新综述
    G120变频器控制方式(宏18)模拟量控制的具体方法示例
    HttpServletRequest详解
    mac M1 pro 安装grpc 报错
    Grafana 安装配置教程,让你的 Prometheus 监控数据变得更美观
  • 原文地址:https://blog.csdn.net/weixin_62700590/article/details/126100454