• C++:stl_List的介绍与模拟实现


    目录

    一.List定义

    二.List的使用

    (1)push_back后的遍历

    ​编辑

    (2)erase,insert那些跟vector一样用法,没什么好说的

    (3)sort(List支持排序,但效率低)

    【1】简介 List::sort

    【2】库里面的sort不支持List的原因(三类迭代器):

    【3】std::sort 与 List::sort 比较,List::sort就是 "飞屋"

    三.List模拟实现

    重点:

    (1)return iterator(_head->_next); 是返回了匿名对象

    (2)begin()迭代器能否直接返回  _head->_next ?——可以

    (3)it->_a1 解释

    (4)为什么list要封装新的iterator,而不能用原生指针?vector却可以

    (5)const迭代器

    (6)erase迭代器失效

    1.第一阶段

    List.h

    Test.cpp

    2.第二阶段 const迭代器

    List.h

    3.第三阶段

    易错点:

    四.list 相关题目


    一.List定义

    Lists are sequence containers that allow constant time insert and erase operations anywhere within the sequence, and iteration in both directions.

    List是一个顺序容器,这个顺序容器允许O(1)的时间复杂度任意插入和删除,还支持双向迭代器。(List底层是双向带头链表)

    二.List的使用

    (1)push_back后的遍历

    List底层是链表,链表空间不连续,就舍弃的[]+下标的遍历方法,通常使用迭代器遍历。

    1. void test_list1()
    2. {
    3. list<int> lt;
    4. lt.push_back(1);
    5. lt.push_back(2);
    6. lt.push_back(3);
    7. lt.push_back(4);
    8. list<int>::iterator it = lt.begin();
    9. while (it != lt.end()) //迭代器遍历
    10. {
    11. cout << *it << " ";
    12. ++it;
    13. }
    14. cout << endl;
    15. for (auto e : lt) //范围for遍历
    16. {
    17. cout << e << " ";
    18. }
    19. cout << endl;
    20. //list::reverse_iterator rit = lt.rbegin();
    21. auto rit = lt.rbegin();
    22. while (rit != lt.rend())
    23. {
    24. cout << *rit << " ";
    25. ++rit;
    26. }
    27. cout << endl;
    28. }

    (2)erase,insert那些跟vector一样用法,没什么好说的

    (3)sort(List支持排序,但效率低)

    【1】简介 List::sort

    库里面的sort不支持List,所以List要有自己的sort(原因在下面),因为结构问题,List::sort效率很低,vector用 std::sort 排序会很快,不建议用List::sort。

    1. void test_list3()
    2. {
    3. list<int> lt;
    4. lt.push_back(1);
    5. lt.push_back(2);
    6. lt.push_back(3);
    7. lt.push_back(4);
    8. lt.push_front(10);
    9. lt.push_front(20);
    10. lt.push_front(30);
    11. lt.push_front(40);
    12. lt.push_back(1);
    13. lt.push_back(1);
    14. lt.push_back(1);
    15. for (auto e : lt)
    16. {
    17. cout << e << " ";
    18. }
    19. cout << endl;
    20. lt.sort();
    21. lt.unique();
    22. for (auto e : lt)
    23. {
    24. cout << e << " ";
    25. }
    26. cout << endl;
    27. }

    【2】库里面的sort不支持List的原因(三类迭代器):

    实现结构的角度,迭代器再实际中分为三类:
    1、单向。
    2、双向。
    3、随机。

    随机迭代器属于单向迭代器也属于双向迭代器,即:单向迭代器包含随机迭代器,双向迭代器也包含随机迭代器。

    库里面的sort是随机迭代器

    List是双向迭代器

    双向包含随机,但随机不包含双向,所以std::sort的使用不能包含双向

    【3】std::sort 与 List::sort 比较,List::sort就是 "飞屋"

    std::sort 底层是快排(要包含头文件

    List::sort 底层是归并排序

     

    总结:短数据情况下(1w个数据以内)List::sort是有价值可以用,大数据就要用vector排序了,连续空间的优势 

    三.List模拟实现

    重点:

    (1)return iterator(_head->_next); 是返回了匿名对象

    iterator()是匿名对象,匿名对象只存在于构造该对象的那行代码,离开构造匿名对象的那行代码后立即调用析构函数。

    ①return iterator(_head->_next); 这一句等价于:②先构造一个iterator类的 it对象,因为不是引用返回,所以需要返回it的临时拷贝,临时拷贝又是it拷贝构造得到的。

    ②iterator it( head-> next);     
        return it;

    对比:②经历了构造对象it,然后拷贝构造一个临时变量;①利用匿名对象优化:把构造匿名对象+拷贝构造临时变量 优化成了 直接构造一个对象并返回。

    1. iterator begin()
    2. {
    3. return iterator(_head->_next); //iterator()是匿名对象,详情看(1)
    4. //return _head->_next;
    5. }
    6. iterator end()
    7. {
    8. return iterator(_head); //iterator()是匿名对象,详情看(1)
    9. }

    (2)begin()迭代器能否直接返回  _head->_next ?——可以

    单参数的构造函数支持隐式类型转换:返回值是iterator,原本是先构造iterator类的对象,再拷贝构造出一个临时变量,通过编译器优化就成了直接构造一个对象并返回。

    1. iterator begin()
    2. {
    3. return iterator(_head->_next); //iterator()是匿名对象,详情看(1)
    4. //return _head->_next; //能否直接返回  _head->_next ?——可以,详情看(2)
    5. }

    (3)it->_a1 解释

    cout << (*it)._a1 << "-"<< (*it)._a2 <<" "; 访问AA中的数据是正常操作,也可以指针指向的写法访问 it->_a1 。因为 *it 返回的是 _node->_data ,所以 it-> 返回的是 &_node->_data,按理来说指针指向方式 访问AA数据元素写法应该是 it->->_a1 编译器为了可读性进行优化处理,优化以后,省略了一个->,成为it->_a1。

    1. struct __list_iterator中:
    2. T& operator*()
    3. {
    4. return _node->_data;
    5. }
    6. T* operator->()
    7. {
    8. //return &(operator*());
    9. return &_node->_data;
    10. }
    11. void test_list2()
    12. {
    13. list lt;
    14. lt.push_back(AA(1, 1));
    15. lt.push_back(AA(2, 2));
    16. lt.push_back(AA(3, 3));
    17. lt.push_back(AA(4, 4));
    18. // 迭代器模拟的是指针行为
    19. // int* it *it
    20. // AA* it *it it->
    21. list::iterator it = lt.begin();
    22. while (it != lt.end())
    23. {
    24. //cout << (*it)._a1 << "-"<< (*it)._a2 <<" ";
    25. cout << it->_a1 << "-" << it->_a2 << " "; //it->_a1解释,详情见(3)
    26. ++it;
    27. }
    28. cout << endl;
    29. }

    (4)为什么list要封装新的iterator,而不能用原生指针?vector却可以

    1. template<class T>
    2. struct __list_iterator //详情见(3),list为什么不能用原生指针?因为物理空间不连续
    3. {……}

     vector相当于家里有矿的孩子,不用努力,家里给(系统支持原生指针做迭代器的++--等)。

    list 相当于普通家庭,需要自己努力(自己写自定义类型支持迭代器__list_iterator,还要重载运算符)

    两者外表(调用)看起来一模一样,实际底层完全不同

    (5)const迭代器

    为了支持像printf这样形参传的是const对象,正常思路是再复制一遍__list_iterator类,然后全部改成const做成__list_const_iterator类,但是这样复用性不好,不便于维护,所以我们采用模板控制const类型参数:反正是对 operator* 和 -> 返回值的改变,不如直接添加两个模板参数T&和T*,分成const和非const两种模板 。lt对象带const时,就用const_iterator模板;对象是非const时就用iterator模板,就用。调用 lt.begin()时,begin()返回的临时对象类型是const_iterator,则__list_iterator 传入的3个模板类型是const_iterator,

    也就是__list_iterator

    1. template<class T, class Ref, class Ptr>
    2. struct __list_iterator
    3. {
    4. // *it
    5. Ref operator*()
    6. {
    7. return _node->_data;
    8. }
    9. Ptr operator->()
    10. {
    11. //return &(operator*());
    12. return &_node->_data;
    13. }
    14. ……
    15. template<class T>
    16. class list
    17. {
    18. typedef list_node Node;
    19. public:
    20. typedef __list_iterator iterator;
    21. typedef __list_iteratorconst T&, const T*> const_iterator;
    22. const_iterator begin() const
    23. {
    24. // list_node*
    25. return const_iterator(_head->_next);
    26. }
    27. const_iterator end() const
    28. {
    29. return const_iterator(_head);
    30. }
    31. ……
    32. void print_list(const list<int>& lt)
    33. {
    34. list<int>::const_iterator it = lt.begin();
    35. while (it != lt.end())
    36. {
    37. //*it = 10; // 不允许修改
    38. cout << *it << " ";
    39. ++it;
    40. }
    41. cout << endl;
    42. }

    (6)erase迭代器失效

    insert不会导致迭代器失效,无论怎么插入,iterator pos都指向原位。只不过返回值是要返回新节点的迭代器。

    erase会导致迭代器失效,只要删除了pos位置的节点,那pos就是野指针了。

    1.第一阶段

    List.h

    1. #pragma once
    2. namespace bit
    3. {
    4. template<class T>
    5. struct list_node
    6. {
    7. list_node* _next;
    8. list_node* _prev;
    9. T _data;
    10. list_node(const T& val = T())
    11. :_next(nullptr)
    12. , _prev(nullptr)
    13. , _data(val)
    14. {}
    15. };
    16. template<class T>
    17. struct __list_iterator //详情见(4),list为什么不能用原生指针?因为物理空间不连续
    18. {
    19. typedef list_node Node;
    20. typedef __list_iterator self;
    21. Node* _node;
    22. __list_iterator(Node* node) //这里写构造函数是为了传参,默认生成的构造函数无法传参
    23. :_node(node)
    24. {}
    25. // 析构函数 -- 节点不属于迭代器,不需要迭代器释放
    26. // 拷贝构造和赋值重载 -- 默认生成的浅拷贝就可以
    27. T& operator*()
    28. {
    29. return _node->_data;
    30. }
    31. T* operator->()
    32. {
    33. //return &(operator*());
    34. return &_node->_data;
    35. }
    36. self& operator++()
    37. {
    38. _node = _node->_next;
    39. return *this;
    40. }
    41. self operator++(int)
    42. {
    43. self tmp(*this);
    44. _node = _node->_next;
    45. return tmp;
    46. }
    47. self& operator--()
    48. {
    49. _node = _node->_prev;
    50. return *this;
    51. }
    52. self operator--(int)
    53. {
    54. self tmp(*this);
    55. _node = _node->_prev;
    56. return tmp;
    57. }
    58. bool operator!=(const self& it)
    59. {
    60. return _node != it._node;
    61. }
    62. bool operator==(const self& it)
    63. {
    64. return _node == it._node;
    65. }
    66. };
    67. template<class T>
    68. class list
    69. {
    70. typedef list_node Node;
    71. public:
    72. typedef __list_iterator iterator;
    73. iterator begin()
    74. {
    75. return iterator(_head->_next); //iterator()是匿名对象,详情看(1)
    76. //return _head->_next; //能否直接返回  _head->_next ?——可以,详情看(2)
    77. }
    78. iterator end()
    79. {
    80. return iterator(_head); //iterator()是匿名对象,详情看(1)
    81. }
    82. list()
    83. {
    84. _head = new Node();
    85. _head->_next = _head;
    86. _head->_prev = _head;
    87. }
    88. void push_back(const T& x)
    89. {
    90. Node* tail = _head->_prev;
    91. Node* newnode = new Node(x);
    92. // _head tail newnode
    93. tail->_next = newnode;
    94. newnode->_prev = tail;
    95. newnode->_next = _head;
    96. _head->_prev = newnode;
    97. }
    98. private:
    99. Node* _head;
    100. };
    101. void test_list1()
    102. {
    103. list<int> lt;
    104. lt.push_back(1);
    105. lt.push_back(2);
    106. lt.push_back(3);
    107. lt.push_back(4);
    108. list<int>::iterator it = lt.begin();
    109. while (it != lt.end())
    110. {
    111. cout << *it << " ";
    112. ++it;
    113. }
    114. cout << endl;
    115. }
    116. struct AA
    117. {
    118. AA(int a1 = 0, int a2 = 0)
    119. :_a1(a1)
    120. , _a2(a2)
    121. {}
    122. int _a1;
    123. int _a2;
    124. };
    125. void test_list2()
    126. {
    127. list lt;
    128. lt.push_back(AA(1, 1));
    129. lt.push_back(AA(2, 2));
    130. lt.push_back(AA(3, 3));
    131. lt.push_back(AA(4, 4));
    132. // 迭代器模拟的是指针行为
    133. // int* it *it
    134. // AA* it *it it->
    135. list::iterator it = lt.begin();
    136. while (it != lt.end())
    137. {
    138. //cout << (*it)._a1 << "-"<< (*it)._a2 <<" ";
    139. cout << it->_a1 << "-" << it->_a2 << " "; //it->_a1解释,详情见(3)
    140. ++it;
    141. }
    142. cout << endl;
    143. }
    144. }

    Test.cpp

    1. int main()
    2. {
    3. bit::test_list2();
    4. return 0;
    5. }

    2.第二阶段 const迭代器

    List.h

    1. #pragma once
    2. #include
    3. namespace bit
    4. {
    5. template<class T>
    6. struct list_node
    7. {
    8. list_node* _next;
    9. list_node* _prev;
    10. T _data;
    11. list_node(const T& val = T())
    12. :_next(nullptr)
    13. , _prev(nullptr)
    14. , _data(val)
    15. {}
    16. };
    17. // typedef __list_iterator iterator;
    18. // typedef __list_iterator const_iterator;
    19. template<class T, class Ref, class Ptr>
    20. struct __list_iterator
    21. {
    22. typedef list_node Node;
    23. typedef __list_iterator self;
    24. Node* _node;
    25. __list_iterator(Node* node)
    26. :_node(node)
    27. {}
    28. // 析构函数 -- 节点不属于迭代器,不需要迭代器释放
    29. // 拷贝构造和赋值重载 -- 默认生成的浅拷贝就可以
    30. // *it
    31. Ref operator*()
    32. {
    33. return _node->_data;
    34. }
    35. Ptr operator->()
    36. {
    37. //return &(operator*());
    38. return &_node->_data;
    39. }
    40. self& operator++()
    41. {
    42. _node = _node->_next;
    43. return *this;
    44. }
    45. self operator++(int)
    46. {
    47. self tmp(*this);
    48. _node = _node->_next;
    49. return tmp;
    50. }
    51. self& operator--()
    52. {
    53. _node = _node->_prev;
    54. return *this;
    55. }
    56. self operator--(int)
    57. {
    58. self tmp(*this);
    59. _node = _node->_prev;
    60. return tmp;
    61. }
    62. bool operator!=(const self& it)
    63. {
    64. return _node != it._node;
    65. }
    66. bool operator==(const self& it)
    67. {
    68. return _node == it._node;
    69. }
    70. };
    71. // 复用性很差
    72. // 单独实现一个类,支持不能修改迭代器指向节点的数据
    73. //template
    74. //struct __list_const_iterator;
    75. template<class T>
    76. class list
    77. {
    78. typedef list_node Node;
    79. public:
    80. typedef __list_iterator iterator;
    81. typedef __list_iteratorconst T&, const T*> const_iterator;
    82. const_iterator begin() const
    83. {
    84. // list_node*
    85. return const_iterator(_head->_next);
    86. }
    87. const_iterator end() const
    88. {
    89. return const_iterator(_head);
    90. }
    91. iterator begin()
    92. {
    93. return iterator(_head->_next);
    94. //return _head->_next;
    95. }
    96. iterator end()
    97. {
    98. return iterator(_head);
    99. }
    100. list()
    101. {
    102. _head = new Node();
    103. _head->_next = _head;
    104. _head->_prev = _head;
    105. }
    106. // lt2(lt1)
    107. /*list(const list& lt)
    108. {
    109. _head = new Node();
    110. _head->_next = _head;
    111. _head->_prev = _head;
    112. for (auto e : lt)
    113. {
    114. push_back(e);
    115. }
    116. }*/
    117. void empty_init()
    118. {
    119. _head = new Node();
    120. _head->_next = _head;
    121. _head->_prev = _head;
    122. }
    123. template <class InputIterator>
    124. list(InputIterator first, InputIterator last)
    125. {
    126. empty_init();
    127. while (first != last)
    128. {
    129. push_back(*first);
    130. ++first;
    131. }
    132. }
    133. // 17:00 继续
    134. void swap(list& lt)
    135. {
    136. std::swap(_head, lt._head);
    137. }
    138. // lt2(lt1) -- 现代写法
    139. list(const list& lt)
    140. {
    141. empty_init();
    142. list tmp(lt.begin(), lt.end());
    143. swap(tmp);
    144. }
    145. // lt2 = lt1
    146. list& operator=(list lt)
    147. {
    148. swap(lt);
    149. return *this;
    150. }
    151. ~list()
    152. {
    153. clear();
    154. delete _head;
    155. _head = nullptr;
    156. }
    157. void clear()
    158. {
    159. iterator it = begin();
    160. while (it != end())
    161. {
    162. it = erase(it);
    163. }
    164. }
    165. void push_back(const T& x)
    166. {
    167. //Node* tail = _head->_prev;
    168. //Node* newnode = new Node(x);
    169. _head tail newnode
    170. //tail->_next = newnode;
    171. //newnode->_prev = tail;
    172. //newnode->_next = _head;
    173. //_head->_prev = newnode;
    174. insert(end(), x);
    175. }
    176. void push_front(const T& x)
    177. {
    178. insert(begin(), x);
    179. }
    180. void pop_back()
    181. {
    182. erase(--end());
    183. }
    184. void pop_front()
    185. {
    186. erase(begin());
    187. }
    188. // 插入在pos位置之前
    189. iterator insert(iterator pos, const T& x)
    190. {
    191. Node* newNode = new Node(x);
    192. Node* cur = pos._node;
    193. Node* prev = cur->_prev;
    194. // prev newnode cur
    195. prev->_next = newNode;
    196. newNode->_prev = prev;
    197. newNode->_next = cur;
    198. cur->_prev = newNode;
    199. return iterator(newNode);
    200. }
    201. iterator erase(iterator pos)
    202. {
    203. assert(pos != end());
    204. Node* cur = pos._node;
    205. Node* prev = cur->_prev;
    206. Node* next = cur->_next;
    207. // prev next
    208. prev->_next = next;
    209. next->_prev = prev;
    210. delete cur;
    211. return iterator(next);
    212. }
    213. private:
    214. Node* _head;
    215. };
    216. void print_list(const list<int>& lt)
    217. {
    218. list<int>::const_iterator it = lt.begin();
    219. while (it != lt.end())
    220. {
    221. //*it = 10; // 不允许修改
    222. cout << *it << " ";
    223. ++it;
    224. }
    225. cout << endl;
    226. }

    3.第三阶段

    易错点:

    erase中的assert漏加,clear要用迭代器实现,list 构造函数重载漏写empty_init()函数,swap应该用库里面swap交换节点,swap函数不能用const(否则无法改变,就是无法交换了),operator=参数不能带引用

    增加内容:insert,erase,头尾插,头尾删,clear,析构,构造函数的重载1个,拷贝构造(远古现代写法,共2个),赋值运算符重载(现代写法1个)

    链表的拷贝构造要深拷贝,如果浅拷贝就会导致两个链表的头结点_head指向同一个链表

    1. #pragma once
    2. #include
    3. namespace bit
    4. {
    5. template<class T>
    6. struct list_node
    7. {
    8. list_node* _next;
    9. list_node* _prev;
    10. T _data;
    11. list_node(const T& val = T())
    12. :_next(nullptr)
    13. , _prev(nullptr)
    14. , _data(val)
    15. {}
    16. };
    17. // typedef __list_iterator iterator;
    18. // typedef __list_iterator const_iterator;
    19. template<class T, class Ref, class Ptr>
    20. struct __list_iterator
    21. {
    22. typedef list_node Node;
    23. typedef __list_iterator self;
    24. Node* _node;
    25. __list_iterator(Node* node)
    26. :_node(node)
    27. {}
    28. // 析构函数 -- 节点不属于迭代器,不需要迭代器释放
    29. // 拷贝构造和赋值重载 -- 默认生成的浅拷贝就可以
    30. // *it
    31. Ref operator*()
    32. {
    33. return _node->_data;
    34. }
    35. Ptr operator->()
    36. {
    37. //return &(operator*());
    38. return &_node->_data;
    39. }
    40. self& operator++()
    41. {
    42. _node = _node->_next;
    43. return *this;
    44. }
    45. self operator++(int)
    46. {
    47. self tmp(*this);
    48. _node = _node->_next;
    49. return tmp;
    50. }
    51. self& operator--()
    52. {
    53. _node = _node->_prev;
    54. return *this;
    55. }
    56. self operator--(int)
    57. {
    58. self tmp(*this);
    59. _node = _node->_prev;
    60. return tmp;
    61. }
    62. bool operator!=(const self& it)
    63. {
    64. return _node != it._node;
    65. }
    66. bool operator==(const self& it)
    67. {
    68. return _node == it._node;
    69. }
    70. };
    71. // 复用性很差
    72. // 单独实现一个类,支持不能修改迭代器指向节点的数据
    73. //template
    74. //struct __list_const_iterator;
    75. template<class T>
    76. class list
    77. {
    78. typedef list_node Node;
    79. public:
    80. typedef __list_iterator iterator;
    81. typedef __list_iteratorconst T&, const T*> const_iterator;
    82. const_iterator begin() const
    83. {
    84. // list_node*
    85. return const_iterator(_head->_next);
    86. }
    87. const_iterator end() const
    88. {
    89. return const_iterator(_head);
    90. }
    91. iterator begin()
    92. {
    93. return iterator(_head->_next);
    94. //return _head->_next;
    95. }
    96. iterator end()
    97. {
    98. return iterator(_head);
    99. }
    100. list()
    101. {
    102. _head = new Node();
    103. _head->_next = _head;
    104. _head->_prev = _head;
    105. }
    106. void empty_init()
    107. {
    108. _head = new Node();
    109. _head->_next = _head;
    110. _head->_prev = _head;
    111. }
    112. //这是构造函数,是使用lt的值来进行构造的
    113. template <class InputIterator>
    114. list(InputIterator first, InputIterator last)
    115. {
    116. empty_init();
    117. while (first != last)
    118. {
    119. push_back(*first);
    120. ++first;
    121. }
    122. }
    123. // lt2(lt1) 拷贝构造远古写法
    124. /*list(const list& lt)
    125. {
    126. _head = new Node();
    127. _head->_next = _head;
    128. _head->_prev = _head;
    129. for (auto e : lt)
    130. {
    131. push_back(e);
    132. }
    133. }*/
    134. // 17:00 继续
    135. void swap(list& lt) //不能加const,要不然修改不了了
    136. {
    137. std::swap(_head, lt._head);
    138. }
    139. // lt2(lt1) -- 拷贝构造现代写法
    140. //链表的拷贝构造要深拷贝,如果浅拷贝就会导致两个链表的头结点_head指向同一个链表
    141. list(const list& lt)
    142. {
    143. empty_init();
    144. list tmp(lt.begin(), lt.end());
    145. swap(tmp);
    146. }
    147. // lt2 = lt1
    148. list& operator=(list lt)
    149. {
    150. swap(lt);
    151. return *this;
    152. }
    153. ~list()
    154. {
    155. clear();
    156. delete _head;
    157. _head = nullptr;
    158. }
    159. void clear()
    160. {
    161. iterator it = begin();
    162. while (it != end())
    163. {
    164. it = erase(it);
    165. }
    166. }
    167. void push_back(const T& x)
    168. {
    169. //Node* tail = _head->_prev;
    170. //Node* newnode = new Node(x);
    171. _head tail newnode
    172. //tail->_next = newnode;
    173. //newnode->_prev = tail;
    174. //newnode->_next = _head;
    175. //_head->_prev = newnode;
    176. insert(end(), x);
    177. }
    178. void push_front(const T& x)
    179. {
    180. insert(begin(), x);
    181. }
    182. void pop_back()
    183. {
    184. erase(--end());
    185. }
    186. void pop_front()
    187. {
    188. erase(begin());
    189. }
    190. // 插入在pos位置之前
    191. iterator insert(iterator pos, const T& x)
    192. {
    193. Node* newNode = new Node(x);
    194. Node* cur = pos._node;
    195. Node* prev = cur->_prev;
    196. // prev newnode cur
    197. prev->_next = newNode;
    198. newNode->_prev = prev;
    199. newNode->_next = cur;
    200. cur->_prev = newNode;
    201. return iterator(newNode);
    202. }
    203. iterator erase(iterator pos)
    204. {
    205. assert(pos != end());
    206. Node* cur = pos._node;
    207. Node* prev = cur->_prev;
    208. Node* next = cur->_next;
    209. // prev next
    210. prev->_next = next;
    211. next->_prev = prev;
    212. delete cur;
    213. return iterator(next);
    214. }
    215. private:
    216. Node* _head;
    217. };
    218. void print_list(const list<int>& lt)
    219. {
    220. list<int>::const_iterator it = lt.begin();
    221. while (it != lt.end())
    222. {
    223. //*it = 10; // 不允许修改
    224. cout << *it << " ";
    225. ++it;
    226. }
    227. cout << endl;
    228. }
    229. void test_list1()
    230. {
    231. list<int> lt;
    232. lt.push_back(1);
    233. lt.push_back(2);
    234. lt.push_back(3);
    235. lt.push_back(4);
    236. list<int>::iterator it = lt.begin();
    237. while (it != lt.end())
    238. {
    239. *it = 20;
    240. cout << *it << " ";
    241. ++it;
    242. }
    243. cout << endl;
    244. print_list(lt);
    245. }
    246. struct AA
    247. {
    248. AA(int a1 = 0, int a2 = 0)
    249. :_a1(a1)
    250. , _a2(a2)
    251. {}
    252. int _a1;
    253. int _a2;
    254. };
    255. void test_list2()
    256. {
    257. list lt;
    258. lt.push_back(AA(1, 1));
    259. lt.push_back(AA(2, 2));
    260. lt.push_back(AA(3, 3));
    261. lt.push_back(AA(4, 4));
    262. // 迭代器模拟的是指针行为
    263. // int* it *it
    264. // AA* it *it it->
    265. list::iterator it = lt.begin();
    266. while (it != lt.end())
    267. {
    268. //cout << (*it)._a1 << "-"<< (*it)._a2 <<" ";
    269. cout << it->_a1 << "-" << it->_a2 << " ";
    270. ++it;
    271. }
    272. cout << endl;
    273. }
    274. void test_list3()
    275. {
    276. list<int> lt;
    277. lt.push_back(1);
    278. lt.push_back(2);
    279. lt.push_back(3);
    280. lt.push_back(4);
    281. lt.push_front(1);
    282. lt.push_front(2);
    283. lt.push_front(3);
    284. lt.push_front(4);
    285. for (auto e : lt)
    286. {
    287. cout << e << " ";
    288. }
    289. cout << endl;
    290. lt.pop_front();
    291. lt.pop_front();
    292. lt.pop_back();
    293. lt.pop_back();
    294. for (auto e : lt)
    295. {
    296. cout << e << " ";
    297. }
    298. cout << endl;
    299. }
    300. void test_list4()
    301. {
    302. list<int> lt;
    303. lt.push_back(1);
    304. lt.push_back(2);
    305. lt.push_back(2);
    306. lt.push_back(3);
    307. lt.push_back(4);
    308. lt.push_back(5);
    309. lt.push_back(6);
    310. // 要求在偶数的前面插入这个偶数*10
    311. auto it1 = lt.begin();
    312. while (it1 != lt.end())
    313. {
    314. if (*it1 % 2 == 0)
    315. {
    316. lt.insert(it1, *it1 * 10);
    317. }
    318. ++it1;
    319. }
    320. for (auto e : lt)
    321. {
    322. cout << e << " ";
    323. }
    324. cout << endl;
    325. }
    326. void test_list5()
    327. {
    328. list<int> lt;
    329. lt.push_back(1);
    330. lt.push_back(2);
    331. lt.push_back(2);
    332. lt.push_back(3);
    333. lt.push_back(4);
    334. lt.push_back(5);
    335. lt.push_back(6);
    336. // 删除所有的偶数
    337. /*auto it1 = lt.begin();
    338. while (it1 != lt.end())
    339. {
    340. if (*it1 % 2 == 0)
    341. {
    342. lt.erase(it1);
    343. }
    344. ++it1;
    345. }*/
    346. auto it1 = lt.begin();
    347. while (it1 != lt.end())
    348. {
    349. if (*it1 % 2 == 0)
    350. {
    351. it1 = lt.erase(it1);
    352. }
    353. else
    354. {
    355. ++it1;
    356. }
    357. }
    358. for (auto e : lt)
    359. {
    360. cout << e << " ";
    361. }
    362. cout << endl;
    363. lt.clear();
    364. for (auto e : lt)
    365. {
    366. cout << e << " ";
    367. }
    368. cout << endl;
    369. lt.push_back(10);
    370. lt.push_back(20);
    371. lt.push_back(30);
    372. for (auto e : lt)
    373. {
    374. cout << e << " ";
    375. }
    376. cout << endl;
    377. }
    378. void test_list6()
    379. {
    380. list<int> lt;
    381. lt.push_back(1);
    382. lt.push_back(2);
    383. lt.push_back(3);
    384. lt.push_back(4);
    385. lt.push_back(5);
    386. lt.push_back(6);
    387. list<int> lt1(lt);
    388. for (auto e : lt1)
    389. {
    390. cout << e << " ";
    391. }
    392. cout << endl;
    393. for (auto e : lt)
    394. {
    395. cout << e << " ";
    396. }
    397. cout << endl;
    398. list<int> lt2;
    399. lt2.push_back(10);
    400. lt2.push_back(20);
    401. lt1 = lt2;
    402. for (auto e : lt2)
    403. {
    404. cout << e << " ";
    405. }
    406. cout << endl;
    407. for (auto e : lt1)
    408. {
    409. cout << e << " ";
    410. }
    411. cout << endl;
    412. }
    413. }

    四.list 相关题目

    1. for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
    2. std::reverse(myvector.begin(),myvector.end()); // 9 8 7 6 5 4 3 2 1

    可知std::reserve 是将包括begin迭代器开始到end前一个位置进行逆置

  • 相关阅读:
    Apple Maps现在可在Firefox和Mac版Edge浏览器中使用
    天啦,从Mongo到ClickHouse我到底经历了什么?
    企业制胜采购管理分别有哪五种策略?
    C#实现顺序表定义、插入、删除、查找操作
    【已解决】pyqt5的打包exe软件图标菜单栏/任务栏/小图标/窗口图标未显示
    基于HTML+CSS+JavaScript制作简单的大学生网页设计——关于我的家乡湖南网页设计主题
    HTTP协议知识点总结-DX的笔记
    4. css资源加载 loader 解析器
    引用
    Codeforces Round #815 (Div. 2)
  • 原文地址:https://blog.csdn.net/zhang_si_hang/article/details/126011527