• 【C++】【STL】【list类的使用】【list类的模拟实现】


    目录

    一、list的介绍

    迭代器失效问题

    list中的sort问题

    二、list类的模拟实现

    1.定义节点类,list类,迭代器类

    ①定义节点类

    ②定义list类

    ③定义迭代器类

    2.迭代器类中具体功能的定义

    ①迭代器所指向数据的比较

    ②迭代器的++,--

    ③迭代器->符号的重载

    3.list中具体功能的定义

     ①常量迭代器和迭代器的初始和结束位置的返回

    ②列表的构造函数

    ③列表的insert插入

    ④列表的头插和尾插

    ⑤列表的擦除函数erase

    ⑥列表的头插和头删

    4.深浅拷贝的问题

    析构函数

    clear函数

    初始化函数

    定义深拷贝的拷贝函数

    定义赋值拷贝

    测试代码

    5.细节问题

    三、头文件代码汇总

    四、测试代码汇总


    一、list的介绍

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

    构造函数( (constructor)

    接口说明

    list (size_type n, const value_type& val = value_type())

    构造的list中包含n个值为val的元素

    list()

    构造空的list

    list (const list& x)

    拷贝构造函数

    list (InputIterator first, InputIterator last)

    [first, last)区间中的元素构造list

    函数声明

    接口说明

    begin +end

    返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器

    rbegin +rend

    返回第一个元素的reverse_iterator,end位置返回最后一个元素下一个位置的

    reverse_iterator,begin位置

    注意:

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

    函数声明

    接口说明

    empty

    检测list是否为空,是返回true,否则返回false

    size

    返回list中有效节点的个数

    函数声明

    接口说明

    front

    返回list的第一个节点中值的引用

    back

    返回list的最后一个节点中值的引用

    函数声明

    接口说明

    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中的有效元素

    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. lt.push_back(5);
    9. list<int>::iterator it=lt.begin();
    10. while(it!=lt.end())
    11. {
    12. cout<<*it<<" ";
    13. ++it;
    14. }
    15. cout<
    16. it=lt.begin();
    17. while(it!=lt.end())
    18. {
    19. (*it) *=2;
    20. ++it;
    21. }
    22. it=lt.begin();
    23. while(it!=lt.end())
    24. {
    25. cout<<*it<<" ";
    26. ++it;
    27. }
    28. cout<
    29. for(auto e: lt)
    30. {
    31. cout<" ";
    32. }
    33. cout<
    34. lt.push_front(10);
    35. lt.push_front(20);
    36. lt.pop_back();
    37. for(auto e: lt)
    38. {
    39. cout<" ";
    40. }
    41. cout<
    42. };

     

    迭代器失效问题

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

    1. void TestListIterator1()
    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. auto it = l.begin();
    6. while (it != l.end())
    7. {
    8. // erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给其赋值
    9. l.erase(it);
    10. ++it;
    11. }
    12. }
    13. int main() {
    14. TestListIterator1();
    15. return 0;
    16. }

    1. // 改正
    2. void TestListIterator()
    3. {
    4. int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    5. list<int> l(array, array+sizeof(array)/sizeof(array[0]));
    6. auto it = l.begin();
    7. while (it != l.end())
    8. {
    9. l.erase(it++); // it = l.erase(it);
    10. }
    11. }
    12. int main() {
    13. TestListIterator();
    14. return 0;
    15. }

    1. void test_list2() {
    2. list<int> lt;
    3. lt.push_back(1);
    4. lt.push_back(2);
    5. lt.push_back(3);
    6. lt.push_back(4);
    7. lt.push_back(5);
    8. auto pos=find(lt.begin(),lt.end(),3);
    9. //找到了就插入
    10. if(pos !=lt.end())
    11. {
    12. //pos是否会失效?不会
    13. //相对位置关系是不会发生变化的,同时也不会产生野指针
    14. //因为这是一个链表
    15. lt.insert(pos,30);
    16. }
    17. for(auto e: lt)
    18. {
    19. cout<" ";
    20. }
    21. cout<
    22. auto pos1=find(lt.begin(),lt.end(),3);
    23. if(pos1!=lt.end())
    24. {
    25. //pos是否会失效?
    26. lt.erase(pos1);
    27. cout<<*pos1<
    28. }
    29. for(auto e: lt)
    30. {
    31. cout<" ";
    32. }
    33. cout<
    34. }

    remove的简单测试

    remove会将list中所有指定的要删除的元素全部都删掉

    1. void test_list3() {
    2. list<int> lt;
    3. lt.push_back(1);
    4. lt.push_back(2);
    5. lt.push_back(3);
    6. lt.push_back(4);
    7. lt.push_back(3);
    8. lt.push_back(5);
    9. for(auto e: lt)
    10. {
    11. cout<" ";
    12. }
    13. cout<
    14. //remove会将list中全部的3都去除掉
    15. lt.remove(3);
    16. for(auto e: lt)
    17. {
    18. cout<" ";
    19. }
    20. cout<
    21. }

    list中的sort问题

    1. void test_list4() {
    2. list<int> lt;
    3. lt.push_back(1);
    4. lt.push_back(2);
    5. lt.push_back(3);
    6. lt.push_back(4);
    7. lt.push_back(3);
    8. lt.push_back(5);
    9. //这个算法库中的sort是没办法用的
    10. //sort(lt.begin(),lt.end());
    11. //sort算法的迭代器用的是随机访问迭代器,链表的不是,因此不能用该算法
    12. //使用list专门的sort是可以的,其采用归并的思路
    13. lt.sort();
    14. for(auto e: lt)
    15. {
    16. cout<" ";
    17. }
    18. cout<
    19. }

    1. //N个数据需要排序,vector+算法sort 还是list+sort?
    2. //虽然快排和归并的效率是差不多的,但是vector支持随机访问,在大量的数据的情况下会比list+sort有很大的提升
    3. //使用vector排完再拷贝回去都比list+sort快

    1. // N个数据需要排序,vector+ 算法sort list+ sort
    2. void test_op()
    3. {
    4. srand(time(0));
    5. const int N = 100000;
    6. vector<int> v;
    7. v.reserve(N);
    8. list<int> lt1;
    9. list<int> lt2;
    10. for (int i = 0; i < N; ++i)
    11. {
    12. auto e = rand();
    13. //v.push_back(e);
    14. lt1.push_back(e);
    15. lt2.push_back(e);
    16. }
    17. // 拷贝到vector排序,排完以后再拷贝回来
    18. int begin1 = clock();
    19. for (auto e : lt1)
    20. {
    21. v.push_back(e);
    22. }
    23. sort(v.begin(), v.end());
    24. size_t i = 0;
    25. for (auto& e : lt1)
    26. {
    27. e = v[i++];
    28. }
    29. int end1 = clock();
    30. int begin2 = clock();
    31. // sort(lt.begin(), lt.end());
    32. lt2.sort();
    33. int end2 = clock();
    34. printf("copy vector sort:%d\n", end1 - begin1);
    35. printf("list sort:%d\n", end2 - begin2);
    36. }
    37. int main()
    38. {
    39. test_op();
    40. return 0;
    41. }

    容器+sort比list+sort快出了不只一点点 

    二、list类的模拟实现

    1.定义节点类,list类,迭代器类

    ①定义节点类

    1. template<class T>
    2. struct list_node
    3. {
    4. T _data;
    5. list_node* _next;
    6. list_node* _prev;
    7. //构造函数
    8. list_node(const T& x = T())
    9. :_data(x)
    10. , _next(nullptr)
    11. , _prev(nullptr)
    12. {}
    13. };

    ②定义list类

    1. template<class T>
    2. class list
    3. {
    4. typedef list_node Node;
    5. public:
    6. //采用复用的方式构建我们的普通迭代器和const迭代器
    7. //第一个参数就是我们的list对象,后面两个参数用来区分是普通迭代器还是const迭代器
    8. typedef __list_iterator iterator;
    9. //迭代器返回的是&T
    10. typedef __list_iteratorconst T&, const T*> const_iterator;
    11. private:
    12. Node* _head;
    13. };

    ③定义迭代器类

    1. // 像指针一样的对象
    2. template<class T, class Ref, class Ptr>
    3. struct __list_iterator
    4. {
    5. typedef list_node Node;
    6. //采用复用的方式构建我们的普通迭代器和const迭代器
    7. //第一个参数就是我们的list对象,后面两个参数用来区分是普通迭代器还是const迭代器
    8. typedef __list_iterator iterator;
    9. typedef bidirectional_iterator_tag iterator_category;
    10. typedef T value_type;
    11. typedef Ptr pointer;
    12. typedef Ref reference;
    13. typedef ptrdiff_t difference_type;
    14. Node* _node;
    15. __list_iterator(Node* node)
    16. :_node(node)
    17. {}
    18. //不需用写迭代器的析构函数
    19. //因为我们迭代器仅仅是用来遍历链表的,如果在遍历完成将这个结点给释放了
    20. //那么我们的链表就断掉了!!!
    21. //不需用写迭代器的拷贝构造
    22. //因为默认的就是浅拷贝,也就是两个迭代器指向统一个结点,这也正是我们期望的
    23. };

    2.迭代器类中具体功能的定义

    ①迭代器所指向数据的比较

    1. bool operator!=(const iterator& it) const
    2. {
    3. return _node != it._node;
    4. }
    5. bool operator==(const iterator& it) const
    6. {
    7. return _node == it._node;
    8. }

    ②迭代器的++,--

    用于迭代器的遍历

    注意:链表结点的依次遍历和之前的数组是不同的!

    1. // ++it
    2. iterator& operator++()
    3. {
    4. _node = _node->_next;
    5. return *this;
    6. }
    7. // it++
    8. iterator operator++(int)
    9. {
    10. iterator tmp(*this);
    11. _node = _node->_next;
    12. return tmp;
    13. }
    14. // --it
    15. iterator& operator--()
    16. {
    17. _node = _node->_prev;
    18. return *this;
    19. }
    20. // it--
    21. iterator operator--(int)
    22. {
    23. iterator tmp(*this);
    24. _node = _node->_prev;
    25. return tmp;
    26. }

    ③迭代器->符号的重载

    箭头是用来访问结构成员的。

    1. Ref operator*()
    2. {
    3. return _node->_data;
    4. }
    5. //T* operator->()
    6. Ptr operator->()
    7. {
    8. //&(_node->_data)
    9. return &(operator*());
    10. }

    按照上面的代码,我们其实是需要输入it->->_a1来访问it迭代器中的_a1参数的,其中it->是调用了

     it->会被转化成it.operator->(),也就是返回一个T*对象

    而T*在会调用上面的函数

    返回T*->_data

    但是写两个箭头太难看了,编译器为了方便,就变成只输入一个->就可以了。 

     并且由于我们上面迭代器的定义方式,我们这里也并没有把是不是const属性给写死,这样下面函数中的Ref和Ptr会随着我们上面模板中的定义而随之改变,也就不用区分是不是const了。

    3.list中具体功能的定义

     ①常量迭代器和迭代器的初始和结束位置的返回

    1. const_iterator begin() const
    2. {
    3. return const_iterator(_head->_next);
    4. }
    5. const_iterator end() const
    6. {
    7. return const_iterator(_head);
    8. }
    9. iterator begin()
    10. {
    11. return iterator(_head->_next);
    12. }
    13. iterator end()
    14. {
    15. return iterator(_head);
    16. }

    ②列表的构造函数

    1. list()
    2. {
    3. _head = new Node;
    4. _head->_next = _head;
    5. _head->_prev = _head;
    6. }

    ③列表的insert插入

    1. iterator insert(iterator pos, const T& x)
    2. {
    3. Node* cur = pos._node;
    4. Node* prev = cur->_prev;
    5. Node* newnode = new Node(x);
    6. // prev newnode cur
    7. prev->_next = newnode;
    8. newnode->_prev = prev;
    9. newnode->_next = cur;
    10. cur->_prev = newnode;
    11. return iterator(newnode);
    12. }

    ④列表的头插和尾插

    1. void push_back(const T& x)
    2. {
    3. //可以手动重新写一个
    4. //Node* tail = _head->_prev;
    5. //Node* newnode = new Node(x);
    6. _head tail newnode
    7. //tail->_next = newnode;
    8. //newnode->_prev = tail;
    9. //newnode->_next = _head;
    10. //_head->_prev = newnode;
    11. //也可以复用insert
    12. insert(end(), x);
    13. }
    14. void push_front(const T& x)
    15. {
    16. insert(begin(), x);
    17. }

    ⑤列表的擦除函数erase

    1. iterator erase(iterator pos)
    2. {
    3. assert(pos != end());
    4. Node* cur = pos._node;
    5. Node* prev = cur->_prev;
    6. Node* next = cur->_next;
    7. prev->_next = next;
    8. next->_prev = prev;
    9. delete cur;
    10. return iterator(next);
    11. }

    ⑥列表的头插和头删

    1. void pop_back()
    2. {
    3. erase(--end());
    4. }
    5. void pop_front()
    6. {
    7. erase(begin());
    8. }

    4.深浅拷贝的问题

    如果我们给我们上面的代码添上析构函数,就会发生报错。因为我们两个list在发生拷贝的时候是浅拷贝,对于同一个结点会释放两次,所以就会发生报错。这里我们就需要将我们的浅拷贝调整为深拷贝

    析构函数

    1. ~list()
    2. {
    3. clear();
    4. delete _head;
    5. _head= nullptr;
    6. }

    在析构之前我们最好提供一个clear函数

    clear仅仅是清除数据,但是头结点是不清除的的

    clear函数

    1. void clear()
    2. {
    3. iterator it=begin();
    4. while(it!=end())
    5. {
    6. //返回下一个位置的迭代器,防止迭代器失效
    7. it=erase(it);
    8. }
    9. }

    初始化函数

    这里我们单独将初始化函数定义出来,然后其他的代码复用初始化函数 

    1. //创建并初始化哨兵位头结点
    2. void empty_init()
    3. {
    4. _head = new Node;
    5. _head->_next = _head;
    6. _head->_prev = _head;
    7. }
    8. //lt2(lt1)
    9. list(const list& lt)
    10. {
    11. //现代写法,最好先初始化一下
    12. empty_init();
    13. list tmp(lt.begin(),lt.end());
    14. swap(tmp);
    15. }
    16. void swap(list lt)
    17. {
    18. std::swap(_head,lt._head);
    19. }
    20. list()
    21. {
    22. empty_init();
    23. }

    定义深拷贝的拷贝函数

    1. template<class InputIterator>
    2. list(InputIterator first,InputIterator last)
    3. {
    4. empty_init();
    5. while(first!=last)
    6. {
    7. //将节点中的内容一个一个拷贝
    8. push_back(*first);
    9. ++first;
    10. }
    11. }

    定义赋值拷贝

    1. //lt1=lt3
    2. list& operator=(list lt)
    3. {
    4. swap(lt);
    5. return *this;
    6. }

    测试代码

    1. void test_list4()
    2. {
    3. list<int> lt;
    4. lt.push_back(1);
    5. lt.push_back(3);
    6. lt.push_back(2);
    7. lt.push_back(3);
    8. lt.push_back(4);
    9. lt.push_back(3);
    10. lt.push_back(3);
    11. lt.push_back(5);
    12. // listcopy(lt);
    13. list<int> copy=lt;
    14. for (auto e : lt)
    15. {
    16. cout << e << " ";
    17. }
    18. cout << endl;
    19. list<int>::iterator it =copy.begin();
    20. while(it!=copy.end())
    21. {
    22. (*it)*=2;
    23. it++;
    24. }
    25. cout<
    26. // cout<<(*copy.begin()*=2)<
    27. for (auto e : copy)
    28. {
    29. cout << e << " ";
    30. }
    31. cout << endl;
    32. for (auto e : lt)
    33. {
    34. cout << e << " ";
    35. }
    36. cout << endl;
    37. }

    我们观察到修改拷贝的list,我们原来的list并不会发生变化

    5.细节问题

    在类外面必须带上模板参数,比方说下面这里

     在类里面编译器会做优化,比方说这里的其实不写也可以,但是写上最好

    可以看到编译器并没有报错。

     

    三、头文件代码汇总

    1. #ifndef LIST_TEST2_LIST_H
    2. #define LIST_TEST2_LIST_H
    3. #pragma once
    4. #include
    5. namespace zhuyuan
    6. {
    7. template<class T>
    8. struct list_node
    9. {
    10. T _data;
    11. list_node* _next;
    12. list_node* _prev;
    13. list_node(const T& x = T())
    14. :_data(x)
    15. , _next(nullptr)
    16. , _prev(nullptr)
    17. {}
    18. };
    19. // typedef __list_iterator iterator;
    20. // typedef __list_iterator const_iterator;
    21. // 像指针一样的对象
    22. template<class T, class Ref, class Ptr>
    23. struct __list_iterator
    24. {
    25. typedef list_node Node;
    26. typedef __list_iterator iterator;
    27. typedef bidirectional_iterator_tag iterator_category;
    28. typedef T value_type;
    29. typedef Ptr pointer;
    30. typedef Ref reference;
    31. typedef ptrdiff_t difference_type;
    32. Node* _node;
    33. __list_iterator(Node* node)
    34. :_node(node)
    35. {}
    36. bool operator!=(const iterator& it) const
    37. {
    38. return _node != it._node;
    39. }
    40. bool operator==(const iterator& it) const
    41. {
    42. return _node == it._node;
    43. }
    44. // *it it.operator*()
    45. // const T& operator*()
    46. // T& operator*()
    47. Ref operator*()
    48. {
    49. return _node->_data;
    50. }
    51. //T* operator->()
    52. Ptr operator->()
    53. {
    54. return &(operator*());
    55. }
    56. // ++it
    57. iterator& operator++()
    58. {
    59. _node = _node->_next;
    60. return *this;
    61. }
    62. // it++
    63. iterator operator++(int)
    64. {
    65. iterator tmp(*this);
    66. _node = _node->_next;
    67. return tmp;
    68. }
    69. // --it
    70. iterator& operator--()
    71. {
    72. _node = _node->_prev;
    73. return *this;
    74. }
    75. // it--
    76. iterator operator--(int)
    77. {
    78. iterator tmp(*this);
    79. _node = _node->_prev;
    80. return tmp;
    81. }
    82. };
    83. template<class T>
    84. class list
    85. {
    86. typedef list_node Node;
    87. public:
    88. typedef __list_iterator iterator;
    89. typedef __list_iteratorconst T&, const T*> const_iterator;
    90. const_iterator begin() const
    91. {
    92. return const_iterator(_head->_next);
    93. }
    94. const_iterator end() const
    95. {
    96. return const_iterator(_head);
    97. }
    98. iterator begin()
    99. {
    100. return iterator(_head->_next);
    101. }
    102. iterator end()
    103. {
    104. return iterator(_head);
    105. }
    106. list()
    107. {
    108. empty_init();
    109. }
    110. template<class InputIterator>
    111. list(InputIterator first,InputIterator last)
    112. {
    113. empty_init();
    114. while(first!=last)
    115. {
    116. //将节点中的内容一个一个拷贝
    117. push_back(*first);
    118. ++first;
    119. }
    120. }
    121. //创建并初始化哨兵位头结点
    122. void empty_init()
    123. {
    124. _head = new Node;
    125. _head->_next = _head;
    126. _head->_prev = _head;
    127. }
    128. //lt2(lt1)
    129. list(const list& lt)
    130. {
    131. //现代写法,最好先初始化一下
    132. empty_init();
    133. list tmp(lt.begin(),lt.end());
    134. swap(tmp);
    135. }
    136. void swap(list lt)
    137. {
    138. std::swap(_head,lt._head);
    139. }
    140. ~list()
    141. {
    142. clear();
    143. delete _head;
    144. _head= nullptr;
    145. }
    146. void clear()
    147. {
    148. iterator it=begin();
    149. while(it!=end())
    150. {
    151. //返回下一个位置的迭代器,防止迭代器失效
    152. it=erase(it);
    153. }
    154. }
    155. //lt1=lt3
    156. list& operator=(list lt)
    157. {
    158. swap(lt);
    159. return *this;
    160. }
    161. void push_back(const T& x)
    162. {
    163. //Node* tail = _head->_prev;
    164. //Node* newnode = new Node(x);
    165. _head tail newnode
    166. //tail->_next = newnode;
    167. //newnode->_prev = tail;
    168. //newnode->_next = _head;
    169. //_head->_prev = newnode;
    170. insert(end(), x);
    171. }
    172. void push_front(const T& x)
    173. {
    174. insert(begin(), x);
    175. }
    176. iterator insert(iterator pos, const T& x)
    177. {
    178. Node* cur = pos._node;
    179. Node* prev = cur->_prev;
    180. Node* newnode = new Node(x);
    181. // prev newnode cur
    182. prev->_next = newnode;
    183. newnode->_prev = prev;
    184. newnode->_next = cur;
    185. cur->_prev = newnode;
    186. return iterator(newnode);
    187. }
    188. void pop_back()
    189. {
    190. erase(--end());
    191. }
    192. void pop_front()
    193. {
    194. erase(begin());
    195. }
    196. iterator erase(iterator pos)
    197. {
    198. assert(pos != end());
    199. Node* cur = pos._node;
    200. Node* prev = cur->_prev;
    201. Node* next = cur->_next;
    202. prev->_next = next;
    203. next->_prev = prev;
    204. delete cur;
    205. return iterator(next);
    206. }
    207. private:
    208. Node* _head;
    209. };
    210. void test_list1()
    211. {
    212. list<int> lt;
    213. lt.push_back(1);
    214. lt.push_back(2);
    215. lt.push_back(3);
    216. lt.push_back(4);
    217. lt.push_back(5);
    218. list<int>::iterator it = lt.begin();
    219. while (it != lt.end())
    220. {
    221. cout << *it << " ";
    222. ++it;
    223. }
    224. cout << endl;
    225. it = lt.begin();
    226. while (it != lt.end())
    227. {
    228. *it *= 2;
    229. ++it;
    230. }
    231. cout << endl;
    232. for (auto e : lt)
    233. {
    234. cout << e << " ";
    235. }
    236. cout << endl;
    237. }
    238. struct Pos
    239. {
    240. int _a1;
    241. int _a2;
    242. Pos(int a1 = 0, int a2 = 0)
    243. :_a1(a1)
    244. ,_a2(a2)
    245. {}
    246. };
    247. void test_list2()
    248. {
    249. int x = 10;
    250. int* p1 = &x;
    251. cout << *p1 << endl;
    252. Pos aa;
    253. Pos* p2 = &aa;
    254. p2->_a1;
    255. p2->_a2;
    256. list lt;
    257. lt.push_back(Pos(10, 20));
    258. lt.push_back(Pos(10, 21));
    259. list::iterator it = lt.begin();
    260. while (it != lt.end())
    261. {
    262. //cout << (*it)._a1 << ":" << (*it)._a2 << endl;
    263. cout << it->_a1 << ":" << it->_a2 << endl;
    264. ++it;
    265. }
    266. cout << endl;
    267. }
    268. void Func(const list<int>& l)
    269. {
    270. list<int>::const_iterator it = l.begin();
    271. while (it != l.end())
    272. {
    273. //*it = 10;
    274. cout << *it << " ";
    275. ++it;
    276. }
    277. cout << endl;
    278. }
    279. void test_list3()
    280. {
    281. list<int> lt;
    282. lt.push_back(1);
    283. lt.push_back(2);
    284. lt.push_back(3);
    285. lt.push_back(4);
    286. lt.push_back(5);
    287. Func(lt);
    288. }
    289. void test_list4()
    290. {
    291. list<int> lt;
    292. lt.push_back(1);
    293. lt.push_back(2);
    294. lt.push_back(3);
    295. lt.push_back(4);
    296. lt.push_back(5);
    297. list<int>::iterator it = lt.begin();
    298. while (it != lt.end())
    299. {
    300. cout << *it << " ";
    301. ++it;
    302. }
    303. cout << endl;
    304. it = lt.begin();
    305. while (it != lt.end())
    306. {
    307. *it *= 2;
    308. ++it;
    309. }
    310. cout << endl;
    311. for (auto e : lt)
    312. {
    313. cout << e << " ";
    314. }
    315. cout << endl;
    316. lt.push_front(10);
    317. lt.push_front(20);
    318. lt.push_front(30);
    319. lt.push_front(40);
    320. lt.pop_back();
    321. lt.pop_back();
    322. for (auto e : lt)
    323. {
    324. cout << e << " ";
    325. }
    326. cout << endl;
    327. auto pos = find(lt.begin(), lt.end(), 4);
    328. if (pos != lt.end())
    329. {
    330. // pos是否会失效?不会
    331. lt.insert(pos, 40);
    332. //lt.insert(pos, 30);
    333. *pos *= 100;
    334. }
    335. for (auto e : lt)
    336. {
    337. cout << e << " ";
    338. }
    339. cout << endl;
    340. lt.clear();
    341. }
    342. }
    343. #endif //LIST_TEST2_LIST_H

    四、测试代码汇总

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. using namespace std;
    7. #include "list.h"
    8. void test_list1()
    9. {
    10. list<int> lt;
    11. lt.push_back(1);
    12. lt.push_back(2);
    13. lt.push_back(3);
    14. lt.push_back(4);
    15. lt.push_back(5);
    16. list<int>::iterator it = lt.begin();
    17. while (it != lt.end())
    18. {
    19. cout << *it << " ";
    20. ++it;
    21. }
    22. cout << endl;
    23. it = lt.begin();
    24. while (it != lt.end())
    25. {
    26. *it *= 2;
    27. ++it;
    28. }
    29. cout << endl;
    30. for (auto e : lt)
    31. {
    32. cout << e << " ";
    33. }
    34. cout << endl;
    35. lt.push_front(10);
    36. lt.push_front(20);
    37. lt.push_front(30);
    38. lt.push_front(40);
    39. lt.pop_back();
    40. lt.pop_back();
    41. for (auto e : lt)
    42. {
    43. cout << e << " ";
    44. }
    45. cout << endl;
    46. }
    47. void test_list2()
    48. {
    49. list<int> lt;
    50. lt.push_back(1);
    51. lt.push_back(2);
    52. lt.push_back(3);
    53. lt.push_back(4);
    54. lt.push_back(5);
    55. auto pos = find(lt.begin(), lt.end(), 3);
    56. if (pos != lt.end())
    57. {
    58. // pos是否会失效?不会
    59. lt.insert(pos, 30);
    60. //lt.insert(pos, 30);
    61. *pos *= 100;
    62. }
    63. for (auto e : lt)
    64. {
    65. cout << e << " ";
    66. }
    67. cout << endl;
    68. pos = find(lt.begin(), lt.end(), 4);
    69. if (pos != lt.end())
    70. {
    71. // pos是否会失效?会
    72. lt.erase(pos);
    73. // cout << *pos << endl;
    74. }
    75. for (auto e : lt)
    76. {
    77. cout << e << " ";
    78. }
    79. cout << endl;
    80. }
    81. void test_list3()
    82. {
    83. list<int> lt;
    84. lt.push_back(1);
    85. lt.push_back(3);
    86. lt.push_back(2);
    87. lt.push_back(3);
    88. lt.push_back(4);
    89. lt.push_back(3);
    90. lt.push_back(3);
    91. lt.push_back(5);
    92. /*for (auto e : lt)
    93. {
    94. cout << e << " ";
    95. }
    96. cout << endl;
    97. lt.remove(3);
    98. for (auto e : lt)
    99. {
    100. cout << e << " ";
    101. }
    102. cout << endl;*/
    103. // sort(lt.begin(), lt.end());
    104. lt.sort();
    105. for (auto e : lt)
    106. {
    107. cout << e << " ";
    108. }
    109. cout << endl;
    110. }
    111. // N个数据需要排序,vector+ 算法sort list+ sort
    112. void test_op()
    113. {
    114. srand(time(0));
    115. const int N = 100000;
    116. vector<int> v;
    117. v.reserve(N);
    118. list<int> lt1;
    119. list<int> lt2;
    120. for (int i = 0; i < N; ++i)
    121. {
    122. auto e = rand();
    123. //v.push_back(e);
    124. lt1.push_back(e);
    125. lt2.push_back(e);
    126. }
    127. // 拷贝到vector排序,排完以后再拷贝回来
    128. int begin1 = clock();
    129. for (auto e : lt1)
    130. {
    131. v.push_back(e);
    132. }
    133. sort(v.begin(), v.end());
    134. size_t i = 0;
    135. for (auto& e : lt1)
    136. {
    137. e = v[i++];
    138. }
    139. int end1 = clock();
    140. int begin2 = clock();
    141. // sort(lt.begin(), lt.end());
    142. lt2.sort();
    143. int end2 = clock();
    144. printf("copy vector sort:%d\n", end1 - begin1);
    145. printf("list sort:%d\n", end2 - begin2);
    146. }
    147. void test_list4()
    148. {
    149. list<int> lt;
    150. lt.push_back(1);
    151. lt.push_back(3);
    152. lt.push_back(2);
    153. lt.push_back(3);
    154. lt.push_back(4);
    155. lt.push_back(3);
    156. lt.push_back(3);
    157. lt.push_back(5);
    158. // listcopy(lt);
    159. list<int> copy=lt;
    160. for (auto e : lt)
    161. {
    162. cout << e << " ";
    163. }
    164. cout << endl;
    165. list<int>::iterator it =copy.begin();
    166. while(it!=copy.end())
    167. {
    168. (*it)*=2;
    169. it++;
    170. }
    171. cout<
    172. // cout<<(*copy.begin()*=2)<
    173. for (auto e : copy)
    174. {
    175. cout << e << " ";
    176. }
    177. cout << endl;
    178. for (auto e : lt)
    179. {
    180. cout << e << " ";
    181. }
    182. cout << endl;
    183. }
    184. int main()
    185. {
    186. test_list4();
    187. // test_op();
    188. // bit::test_list4();
    189. //
    190. return 0;
    191. }

  • 相关阅读:
    【昇腾开发全流程】MindSpore华为云模型训练
    浙江DAMA-CDGA/CDGP数据治理认证招生简章
    C++opencv 色彩空间转换和保存
    Nested loop(PostgreSQL 14 Internals翻译版)
    如何查看SSL证书是OV还是DV?
    【前端】JavaScript数据类型
    leetcode(力扣) 647. 回文子串 (动态规划)
    罗丹明聚乙二醇氨基,Rhodamine-PEG-NH2,NH2-PEG-Rhodamine荧光标记
    最短无序连续子数组
    《论文笔记》Multi-UAV Collaborative Monocular SLAM
  • 原文地址:https://blog.csdn.net/weixin_62684026/article/details/126910925