• C++学习第九天(list及其模拟实现)


    1、list介绍

    • list是可以在常熟范围内任意位置进行 插入和删除的序列式容器,并且该容器可以前后双向迭代
    • list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素
    • list和forward_list非常相似,最主要不同的是forward_list是单链表,只能朝前迭代,以让其更简单高效。
    • list可以在任何位置进行插入,移除元素的效率更高
    • 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问。

     2、list的使用

    list中的接口比较多,一下是常见的重要接口

    list的构造

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

    list iterator的使用

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

    【ATT】

    • begin和end为正向迭代器,对迭代器执行++操作,迭代器向后移动
    • rbegin和rend为反向迭代器,对迭代器执行++操作,迭代器向前移动

    list capacity的使用

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

    list element access的使用

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

    list modifiers的使用

    函数声明接口说明
    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的迭代器失效的,只有在删除的时候才会失效,而且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响

    1. void test3()
    2. {
    3. int array[] = { 1,2,3,4,5,6,7,8,9,0 };
    4. list<int> l(array, array + sizeof(array) / sizeof(array[0]));
    5. list<int>::iterator it = l.begin();
    6. while (it != l.end())
    7. {
    8. //erase()函数被执行后,it所指向的节点已经被删除,因此it无效,在下一次使用it时,必须先给其赋值
    9. l.erase(it);
    10. ++it;
    11. }
    12. }
    13. //修正
    14. void test2()
    15. {
    16. int array[] = { 1,2,3,4,5,6,7,8,9,0 };
    17. list<int> l(array, array + sizeof(array) / sizeof(array[0]));
    18. list<int>::iterator it = l.begin();
    19. while (it != l.end())
    20. {
    21. it = l.erase(it);
    22. }
    23. for (auto e : l)
    24. {
    25. cout << e << " ";
    26. }
    27. }
    28. int main()
    29. {
    30. test2();
    31. return 0;
    32. }

    3、list的模拟实现

    1. #pragma once
    2. #include
    3. #include
    4. using namespace std;
    5. namespace bit
    6. {
    7. //List节点类
    8. template<class T>
    9. struct ListNode
    10. {
    11. ListNode(const T& val = T())
    12. :_prev(nullptr)
    13. ,_next(nullptr)
    14. ,_val(val)
    15. {}
    16. ListNode* _prev;
    17. ListNode* _next;
    18. T _val;
    19. };
    20. template<class T, class Ref, class Ptr>
    21. class ListIterator
    22. {
    23. typedef ListNode Node;
    24. typedef ListIterator Self;
    25. public:
    26. typedef Ref Ref;
    27. typedef Ptr Ptr;
    28. public:
    29. ListIterator(Node* node = nullptr)
    30. :_node(node)
    31. {}
    32. //具有指针行为
    33. Ref operator*()
    34. {
    35. return _node->_val;
    36. }
    37. Ptr operator->()
    38. {
    39. return &(operator*());
    40. }
    41. //迭代器支持移动
    42. Self& operator++()
    43. {
    44. _node = _node->_next;
    45. return *this;
    46. }
    47. Self operator++(int)
    48. {
    49. Self tmp(*this);
    50. _node = _node->_next;
    51. return tmp;
    52. }
    53. Self& operator--()
    54. {
    55. _node = _node->_prev;
    56. return *this;
    57. }
    58. Self& operator--(int)
    59. {
    60. Self tmp(*this);
    61. _node = _node->_prev;
    62. return tmp;
    63. }
    64. //迭代器支持比较
    65. bool operator!=(const Self& l)const
    66. {
    67. return _node != l._node;
    68. }
    69. bool operator==(const Self& l)const
    70. {
    71. return _node != l._node;
    72. }
    73. Node* _node;
    74. };
    75. template<class Iterator>
    76. class ReverseListIterator
    77. {
    78. //typename的作用是明确告诉编译器,Ref是Iterator中的一个类型,而不是静态成员变量
    79. //否则编译器就不知道Ref是Iterator中的类型还是静态成员变量
    80. //因为静态成员变量也是按照 类名::静态成员变量名 的方式访问的
    81. public:
    82. typedef typename Iterator::Ref Ref;
    83. typedef typename Iterator::Ptr Ptr;
    84. typedef ReverseListIterator Self;
    85. public:
    86. ReverseListIterator(Iterator it)
    87. :_it(it)
    88. {}
    89. Ref operator*()
    90. {
    91. Iterator tmp(_it);
    92. --tmp;
    93. return *tmp;
    94. }
    95. Ptr operator->()
    96. {
    97. return &(operator*());
    98. }
    99. Self& operator++()
    100. {
    101. --_it;
    102. return *this;
    103. }
    104. Self operator++(int)
    105. {
    106. Self temp(*this);
    107. --_it;
    108. return temp;
    109. }
    110. Self& operator--()
    111. {
    112. ++_it;
    113. return *this;
    114. }
    115. Self operator--(int)
    116. {
    117. Self temp(*this);
    118. ++_it;
    119. return temp;
    120. }
    121. //
    122. // 迭代器支持比较
    123. bool operator!=(const Self& l)const
    124. {
    125. return _it != l._it;
    126. }
    127. bool operator==(const Self& l)const
    128. {
    129. return _it != l._it;
    130. }
    131. Iterator _it;
    132. };
    133. template<class T>
    134. class list
    135. {
    136. typedef ListNode Node;
    137. public:
    138. // 正向迭代器
    139. typedef ListIterator iterator;
    140. typedef ListIteratorconst T&, const T&> const_iterator;
    141. // 反向迭代器
    142. typedef ReverseListIterator reverse_iterator;
    143. typedef ReverseListIterator const_reverse_iterator;
    144. public:
    145. ///
    146. // List的构造
    147. list()
    148. {
    149. CreateHead();
    150. }
    151. list(int n, const T& value = T())
    152. {
    153. CreateHead();
    154. for (int i = 0; i < n; ++i)
    155. push_back(value);
    156. }
    157. template <class Iterator>
    158. list(Iterator first, Iterator last)
    159. {
    160. CreateHead();
    161. while (first != last)
    162. {
    163. push_back(*first);
    164. ++first;
    165. }
    166. }
    167. list(const list& l)
    168. {
    169. CreateHead();
    170. // 用l中的元素构造临时的temp,然后与当前对象交换
    171. list temp(l.begin(), l.end());
    172. this->swap(temp);
    173. }
    174. list& operator=(list l)
    175. {
    176. this->swap(l);
    177. return *this;
    178. }
    179. ~list()
    180. {
    181. clear();
    182. delete _head;
    183. _head = nullptr;
    184. }
    185. ///
    186. // List的迭代器
    187. iterator begin()
    188. {
    189. return iterator(_head->_next);
    190. }
    191. iterator end()
    192. {
    193. return iterator(_head);
    194. }
    195. const_iterator begin()const
    196. {
    197. return const_iterator(_head->_next);
    198. }
    199. const_iterator end()const
    200. {
    201. return const_iterator(_head);
    202. }
    203. reverse_iterator rbegin()
    204. {
    205. return reverse_iterator(end());
    206. }
    207. reverse_iterator rend()
    208. {
    209. return reverse_iterator(begin());
    210. }
    211. const_reverse_iterator rbegin()const
    212. {
    213. return const_reverse_iterator(end());
    214. }
    215. const_reverse_iterator rend()const
    216. {
    217. return const_reverse_iterator(begin());
    218. }
    219. ///
    220. // List的容量相关
    221. size_t size()const
    222. {
    223. Node* cur = _head->_next;
    224. size_t count = 0;
    225. while (cur != _head)
    226. {
    227. count++;
    228. cur = cur->_next;
    229. }
    230. return count;
    231. }
    232. bool empty()const
    233. {
    234. return _head->_next == _head;
    235. }
    236. void resize(size_t newsize, const T& data = T())
    237. {
    238. size_t oldsize = size();
    239. if (newsize <= oldsize)
    240. {
    241. // 有效元素个数减少到newsize
    242. while (newsize < oldsize)
    243. {
    244. pop_back();
    245. oldsize--;
    246. }
    247. }
    248. else
    249. {
    250. while (oldsize < newsize)
    251. {
    252. push_back(data);
    253. oldsize++;
    254. }
    255. }
    256. }
    257. // List的元素访问操作
    258. // 注意:List不支持operator[]
    259. T& front()
    260. {
    261. return _head->_next->_val;
    262. }
    263. const T& front()const
    264. {
    265. return _head->_next->_val;
    266. }
    267. T& back()
    268. {
    269. return _head->_prev->_val;
    270. }
    271. const T& back()const
    272. {
    273. return _head->_prev->_val;
    274. }
    275. // List的插入和删除
    276. void push_back(const T& val)
    277. {
    278. insert(end(), val);
    279. }
    280. void pop_back()
    281. {
    282. erase(--end());
    283. }
    284. void push_front(const T& val)
    285. {
    286. insert(begin(), val);
    287. }
    288. void pop_front()
    289. {
    290. erase(begin());
    291. }
    292. // 在pos位置前插入值为val的节点
    293. iterator insert(iterator pos, const T& val)
    294. {
    295. Node* pNewNode = new Node(val);
    296. Node* pCur = pos._node;
    297. // 先将新节点插入
    298. pNewNode->_prev = pCur->_prev;
    299. pNewNode->_next = pCur;
    300. pNewNode->_prev->_next = pNewNode;
    301. pCur->_prev = pNewNode;
    302. return iterator(pNewNode);
    303. }
    304. // 删除pos位置的节点,返回该节点的下一个位置
    305. iterator erase(iterator pos)
    306. {
    307. // 找到待删除的节点
    308. Node* pDel = pos._node;
    309. Node* pRet = pDel->_next;
    310. // 将该节点从链表中拆下来并删除
    311. pDel->_prev->_next = pDel->_next;
    312. pDel->_next->_prev = pDel->_prev;
    313. delete pDel;
    314. return iterator(pRet);
    315. }
    316. void clear()
    317. {
    318. Node* cur = _head->_next;
    319. // 采用头删除删除
    320. while (cur != _head)
    321. {
    322. _head->_next = cur->_next;
    323. delete cur;
    324. cur = _head->_next;
    325. }
    326. _head->_next = _head->_prev = _head;
    327. }
    328. void swap(bite::list& l)
    329. {
    330. std::swap(_head, l._head);
    331. }
    332. private:
    333. void CreateHead()
    334. {
    335. _head = new Node;
    336. _head->_prev = _head;
    337. _head->_next = _head;
    338. }
    339. private:
    340. Node* _head;
    341. };
    342. }
    343. ///
    344. // 对模拟实现的list进行测试
    345. // 正向打印链表
    346. template<class T>
    347. void PrintList(const bite::list& l)
    348. {
    349. auto it = l.begin();
    350. while (it != l.end())
    351. {
    352. cout << *it << " ";
    353. ++it;
    354. }
    355. cout << endl;
    356. }
    357. // 测试List的构造
    358. void TestBiteList1()
    359. {
    360. bite::list<int> l1;
    361. bite::list<int> l2(10, 5);
    362. PrintList(l2);
    363. int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    364. bite::list<int> l3(array, array + sizeof(array) / sizeof(array[0]));
    365. PrintList(l3);
    366. bite::list<int> l4(l3);
    367. PrintList(l4);
    368. l1 = l4;
    369. PrintList(l1);
    370. }
    371. // PushBack()/PopBack()/PushFront()/PopFront()
    372. void TestBiteList2()
    373. {
    374. // 测试PushBack与PopBack
    375. bite::list<int> l;
    376. l.push_back(1);
    377. l.push_back(2);
    378. l.push_back(3);
    379. PrintList(l);
    380. l.pop_back();
    381. l.pop_back();
    382. PrintList(l);
    383. l.pop_back();
    384. cout << l.size() << endl;
    385. // 测试PushFront与PopFront
    386. l.push_front(1);
    387. l.push_front(2);
    388. l.push_front(3);
    389. PrintList(l);
    390. l.pop_front();
    391. l.pop_front();
    392. PrintList(l);
    393. l.pop_front();
    394. cout << l.size() << endl;
    395. }
    396. // 测试insert和erase
    397. void TestBiteList3()
    398. {
    399. int array[] = { 1, 2, 3, 4, 5 };
    400. bite::list<int> l(array, array + sizeof(array) / sizeof(array[0]));
    401. auto pos = l.begin();
    402. l.insert(l.begin(), 0);
    403. PrintList(l);
    404. ++pos;
    405. l.insert(pos, 2);
    406. PrintList(l);
    407. l.erase(l.begin());
    408. l.erase(pos);
    409. PrintList(l);
    410. // pos指向的节点已经被删除,pos迭代器失效
    411. cout << *pos << endl;
    412. auto it = l.begin();
    413. while (it != l.end())
    414. {
    415. it = l.erase(it);
    416. }
    417. cout << l.size() << endl;
    418. }
    419. // 测试反向迭代器
    420. void TestBiteList4()
    421. {
    422. int array[] = { 1, 2, 3, 4, 5 };
    423. bite::list<int> l(array, array + sizeof(array) / sizeof(array[0]));
    424. auto rit = l.rbegin();
    425. while (rit != l.rend())
    426. {
    427. cout << *rit << " ";
    428. ++rit;
    429. }
    430. cout << endl;
    431. const bite::list<int> cl(l);
    432. auto crit = l.rbegin();
    433. while (crit != l.rend())
    434. {
    435. cout << *crit << " ";
    436. ++crit;
    437. }
    438. cout << endl;
    439. }
    440. };
    441. }

  • 相关阅读:
    UG NX二次开发(C++)-CAM-根据刀具对程序组进行重新分组
    详细讲解库函数的使用及模拟实现(提升对库函数的理解和运用)
    待试验:AR与DMX同步,实现AR效果与现实灯光互相影响,增强体验的真实感
    计算机网络——网络层(多协议标签交换MPLS、软件定义网络SDN)
    【Linux】权限理解
    EPSS 解读:与 CVSS 相比,孰美?
    第64章 Jquery JSON Table Nop后台重构定义Jquery DataTables
    分析和比较深度学习框架 PyTorch 和 Tensorflow
    PHP 或者linux 直播中hls m3u8 rtmp 截图封面识别色情
    Speedoffice(excel)如何使用COUNTIF函数进行条件计数
  • 原文地址:https://blog.csdn.net/zjx_web_c/article/details/137599760