C++根本知识7 list

[复制链接]
发表于 2026-1-22 02:53:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1. list的先容及使用

1.1 list的先容


1.2 list的使用

1.2.1 list的构造


1.2.2 list iterator的使用

此处,各人可临时将迭代器明确成一个指针,该指针指向list中的某个节点。


   【注意】
  

  • begin与end为正向迭代器,对迭代器实行++使用,迭代器向后移动
  • rbegin(end)与rend(begin)为反向迭代器,对迭代器实行++使用,迭代器向前移动
  1.2.3 list capacity


1.2.4 list element access


1.2.5 list modifiers


1.2.6 list的迭代器失效

前面说过,此处各人可将迭代器临时明确成类似于指针,迭代器失效即迭代器所指向的节点的无
效,即该节点被删除了。由于list的底层结构为带头结点的双向循环链表,因此在list中举行插入
时是不会导致list的迭代器失效的,只有在删除时才会失效,而且失效的只是指向被删除节点的迭
代器,其他迭代器不会受到影响。

使用接口
  1. #include<iostream>
  2. #include<algorithm>
  3. #include<list>
  4. #include<vector>
  5. using namespace std;
复制代码

  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)
  16.         {
  17.                 cout << e << " ";
  18.         }
  19.         cout << endl;
  20. }
复制代码
  支持迭代器就支持范围for
  
  1. struct A
  2. {
  3. public:
  4.         A(int a1 = 1, int a2 = 1)
  5.                 :_a1(a1)
  6.                 , _a2(a2)
  7.         {
  8.                 cout << "A(int a1 = 1, int a2 = 1)" << endl;
  9.         }
  10.         A(const A& aa)
  11.                 :_a1(aa._a1)
  12.                 , _a2(aa._a2)
  13.         {
  14.                 cout << "A(const A& aa)" << endl;
  15.         }
  16.         int _a1;
  17.         int _a2;
  18. };
复制代码

  1. void test_list2()
  2. {
  3.         list<A> lt;
  4.         A aa1(1, 1);
  5.         lt.push_back(aa1);
  6.         lt.push_back(A(2, 2));//匿名对象
  7. }
复制代码
  传参走隐式范例转换
  
  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_back(5);
  9.         lt.push_back(6);
  10.         for (auto e : lt)
  11.         {
  12.                 cout << e << " ";
  13.         }
  14.         cout << endl;
  15.         auto it = lt.begin();
  16.         int k = 3;
  17.         while (k--)
  18.         {
  19.                 ++it;
  20.         }
  21.         lt.insert(it, 30);
  22.         for (auto e : lt)
  23.         {
  24.                 cout << e << " ";
  25.         }
  26.         cout << endl;
  27.         int x = 0;
  28.         cin >> x;
  29.         it = find(lt.begin(), lt.end(), x);
  30.         if (it != lt.end())
  31.         {
  32.                 lt.erase(it);
  33.         }
  34.         for (auto e : lt)
  35.         {
  36.                 cout << e << " ";
  37.         }
  38.         cout << endl;
  39. }
复制代码
  list迭代器只支持了+±-运算符的重载,因此实现+=智能通过++实现
  
  1. void test_list4()
  2. {
  3.         list<int> lt;
  4.         lt.push_back(1);
  5.         lt.push_back(20);
  6.         lt.push_back(3);
  7.         lt.push_back(5);
  8.         lt.push_back(4);
  9.         lt.push_back(5);
  10.         lt.push_back(6);
  11.         for (auto e : lt)
  12.         {
  13.                 cout << e << " ";
  14.         }
  15.         cout << endl;
  16.         // 升序
  17.         // lt.sort();
  18.         // 降序 - 仿函数
  19.         // less<int> ls;
  20.         // greater<int> gt;
  21.         // lt.sort(gt);
  22.         lt.sort(greater<int>());
  23.         lt.reverse();//类方法
  24.         reverse(lt.begin(), lt.end());//算法库实现的
  25.         for (auto e : lt)
  26.         {
  27.                 cout << e << " ";
  28.         }
  29.         cout << endl;
  30.         std::list<double> first, second;
  31.         first.push_back(3.1);
  32.         first.push_back(2.2);
  33.         first.push_back(2.9);
  34.         second.push_back(3.7);
  35.         second.push_back(7.1);
  36.         second.push_back(1.4);
  37.         first.sort();
  38.         second.sort();
  39.         first.merge(second);
  40. }
复制代码
  排序时我们使用了一个仿函数,仿函数是一个类可以实现排序时升序照旧降序。
merge支持将将两个排序好的链表归并插入到*this中
  
  1. void test_list5()
  2. {
  3.         list<int> lt;
  4.         lt.push_back(1);
  5.         lt.push_back(20);
  6.         lt.push_back(3);
  7.         lt.push_back(5);
  8.         lt.push_back(5);
  9.         lt.push_back(4);
  10.         lt.push_back(5);
  11.         lt.push_back(6);
  12.         lt.sort();
  13.         for (auto e : lt)
  14.         {
  15.                 cout << e << " ";
  16.         }
  17.         cout << endl;
  18.         lt.unique();
  19.         for (auto e : lt)
  20.         {
  21.                 cout << e << " ";
  22.         }
  23.         cout << endl;
  24. }
复制代码
  unique实现删除重复元素(在链表排序好的情况下)
  
  1. void test_list6()
  2. {
  3.         // 一个链表节点转移给另一个链表
  4.         std::list<int> mylist1, mylist2;
  5.         std::list<int>::iterator it;
  6.         // set some initial values:
  7.         for (int i = 1; i <= 4; ++i)
  8.                 mylist1.push_back(i);      // mylist1: 1 2 3 4
  9.         for (int i = 1; i <= 3; ++i)
  10.                 mylist2.push_back(i * 10);   // mylist2: 10 20 30
  11.         it = mylist1.begin();
  12.         ++it;                         // points to 2
  13.         mylist1.splice(it, mylist2); // mylist1: 1 10 20 30 2 3 4
  14.         // mylist2 (empty)
  15.         // "it" still points to 2 (the 5th element
  16. // 调整当前链表节点的顺序
  17.         list<int> lt;
  18.         lt.push_back(1);
  19.         lt.push_back(2);
  20.         lt.push_back(3);
  21.         lt.push_back(4);
  22.         lt.push_back(5);
  23.         lt.push_back(6);
  24.         for (auto e : lt)
  25.         {
  26.                 cout << e << " ";
  27.         }
  28.         cout << endl;
  29.         int x = 0;
  30.         cin >> x;
  31.         it = find(lt.begin(), lt.end(), x);
  32.         if (it != lt.end())
  33.         {
  34.                 //lt.splice(lt.begin(), lt, it);
  35.                 lt.splice(lt.begin(), lt, it, lt.end());
  36.         }
  37.         for (auto e : lt)
  38.         {
  39.                 cout << e << " ";
  40.         }
  41.         cout << endl;
  42. }
复制代码
  splice实现粘连可以是一个链表内部的粘连也可以是两个链表去粘连

  

  • 将链表x的全部结点粘连在position之前
  • 将链表x中的i结点粘连在position之前
  • 将链表x的迭代去区间粘连在position之前
  
  1. void test_op()
  2. {
  3.         srand(time(0));
  4.         const int N = 1000000;
  5.         list<int> lt1;
  6.         list<int> lt2;
  7.         for (int i = 0; i < N; ++i)
  8.         {
  9.                 auto e = rand() + i;
  10.                 lt1.push_back(e);
  11.                 lt2.push_back(e);
  12.         }
  13.         int begin1 = clock();
  14.         // 拷贝vector
  15.         vector<int> v(lt2.begin(), lt2.end());
  16.         // 排序
  17.         sort(v.begin(), v.end());
  18.         // 拷贝回lt2
  19.         lt2.assign(v.begin(), v.end());
  20.         int end1 = clock();
  21.         int begin2 = clock();
  22.         lt1.sort();
  23.         int end2 = clock();
  24.         printf("list copy vector sort copy list sort:%d\n", end1 - begin1);
  25.         printf("list sort:%d\n", end2 - begin2);
  26. }
复制代码
  链表排序在算法库中实现,不是类方法的一部门。但是对于链表排序最好把list放到vector中排序在调用assign返回给list,在如许的代价下排序的服从也是远高于对list排序
  
2.1 模拟实现list

要模拟实现list,必须要熟悉list的底层结构以及其接口的寄义,通过上面的学习,这些内容已根本
把握,现在我们来模拟实现list。
  1. #pragma once
  2. #include<assert.h>
  3. #include<iostream>
  4. using namespace std;
  5. namespace Yusei
  6. {
  7.         template<class T>
  8.         struct list_node
  9.         {
  10.                 T _date;
  11.                 list_node<T>* _next;
  12.                 list_node<T>* _prev;
  13.                 list_node(const T& date=T())
  14.                         :_next(nullptr)
  15.                         ,_prev(nullptr)
  16.                         ,_date(date)
  17.                 {}
  18.         };
  19.         template<class T, class Ref, class Ptr>
  20.         struct list_iterator
  21.         {
  22.                 typedef list_node<T> Node;
  23.                 typedef list_iterator<T, Ref, Ptr> Self;
  24.                 Node* _node;
  25.                 list_iterator(Node* node)
  26.                         :_node(node)
  27.                 {}
  28.                 Ref operator*()
  29.                 {
  30.                         return _node->_date;
  31.                 }
  32.                 Ptr operator ->()
  33.                 {
  34.                         return &_node->_date;
  35.                 }
  36.                 Self& operator++()
  37.                 {
  38.                          _node=_node->_next;
  39.                          return *this;
  40.                 }
  41.                 Self& operator--()
  42.                 {
  43.                         _node = _node->_prev;
  44.                         return *this;
  45.                 }
  46.                 Self& operator++(int)
  47.                 {
  48.                         Self tmp(*this);
  49.                         _node = _node->_next;
  50.                         return tmp;
  51.                 }
  52.                 Self& operator--(int)
  53.                 {
  54.                         Self tmp(*this);
  55.                         _node = _node->_prev;
  56.                         return tmp;
  57.                 }
  58.                 bool operator!=(const Self& s)const
  59.                 {
  60.                         return _node != s._node;
  61.                 }
  62.                 bool operator==(const Self& s)const
  63.                 {
  64.                         return _node == s._node;
  65.                 }
  66.         };
  67.         template<class T>
  68.         class list
  69.         {
  70.                 typedef list_node<T> Node;
  71.         public:
  72.                 typedef list_iterator<T, T&, T*> iterator;
  73.                 typedef list_iterator<T, const T&, const T*> const_iterator;
  74.                 iterator begin()
  75.                 {
  76.                         return _head->_next;
  77.                 }
  78.                 iterator end()
  79.                 {
  80.                         return _head;
  81.                 }
  82.                 const_iterator begin() const
  83.                 {
  84.                         return _head->_next;
  85.                 }
  86.                 const_iterator end() const
  87.                 {
  88.                         return _head;
  89.                 }
  90.                 void empty_init()
  91.                 {
  92.                         _head = new Node;
  93.                         _head->_next = _head;
  94.                         _head->_prev = _head;
  95.                         _size = 0;
  96.                 }
  97.                 list()
  98.                 {
  99.                         empty_init();
  100.                 }
  101.                 list(initializer_list<T> il)
  102.                 {
  103.                         empty_init();
  104.                         for (auto& e : il)
  105.                         {
  106.                                 push_back(e);
  107.                         }
  108.                 }
  109.                 list(const list<T>& lt)
  110.                 {
  111.                         empty_init();
  112.                         for (auto& e : lt)
  113.                         {
  114.                                 push_back(e);
  115.                         }
  116.                 }
  117.                 void swap(list<T>& lt)
  118.                 {
  119.                         std::swap(_head, lt._head);
  120.                         std::swap(_size, lt._size);
  121.                 }
  122.                 list<T>& operator=(list<T> lt)
  123.                 {
  124.                         swap(lt);
  125.                         return *this;
  126.                 }
  127.                 ~list()
  128.                 {
  129.                         clear();
  130.                         delete _head;
  131.                         _head = nullptr;
  132.                 }
  133.                 void clear()
  134.                 {
  135.                         auto it = begin();
  136.                         while (it != end())
  137.                         {
  138.                                 it = erase(it);
  139.                         }
  140.                 }
  141.                 iterator insert(iterator pos, const T& x)
  142.                 {
  143.                         Node* cur = pos._node;
  144.                         Node* prev = cur->_prev;
  145.                         Node* newnode = new Node(x);
  146.                         // prev newnode cur
  147.                         newnode->_next = cur;
  148.                         cur->_prev = newnode;
  149.                         newnode->_prev = prev;
  150.                         prev->_next = newnode;
  151.                         ++_size;
  152.                         return newnode;
  153.                 }
  154.                 void push_back(const T& x)
  155.                 {
  156.                         insert(end(), x);
  157.                 }
  158.                 void push_front(const T& x)
  159.                 {
  160.                         insert(begin(), x);
  161.                 }
  162.                 iterator erase(iterator pos)
  163.                 {
  164.                         assert(pos != end());
  165.                         Node* prev = pos._node->_prev;
  166.                         Node* next = pos._node->_next;
  167.                         prev->_next = next;
  168.                         next->_prev = prev;
  169.                         delete pos._node;
  170.                         --_size;
  171.                         return next;
  172.                 }
  173.                 void pop_back()
  174.                 {
  175.                         erase(--end());
  176.                 }
  177.                 void pop_front()
  178.                 {
  179.                         erase(begin());
  180.                 }
  181.                 size_t size() const
  182.                 {
  183.                         return _size;
  184.                 }
  185.                 bool empty() const
  186.                 {
  187.                         return _size == 0;
  188.                 }
  189.         private:
  190.                 Node* _head;
  191.                 size_t _size;
  192.         };
  193.         struct AA
  194.         {
  195.                 int _a1 = 1;
  196.                 int _a2 = 1;
  197.         };
  198.         template<class Container>
  199.         void print_container(const Container& con)
  200.         {
  201.                 typename Container::const_iterator it = con.begin();
  202.                 //auto it = con.begin();
  203.                 while (it != con.end())
  204.                 {
  205.                         //*it += 10;
  206.                         cout << *it << " ";
  207.                         ++it;
  208.                 }
  209.                 cout << endl;
  210.                 for (auto e : con)
  211.                 {
  212.                         cout << e << " ";
  213.                 }
  214.                 cout << endl;
  215.         }
  216.         void test_list1()
  217.         {
  218.                 list<int> lt;
  219.                 lt.push_back(1);
  220.                 lt.push_back(2);
  221.                 lt.push_back(3);
  222.                 lt.push_back(4);
  223.                 list<int>::iterator it = lt.begin();
  224.                 while (it != lt.end())
  225.                 {
  226.                         *it += 10;
  227.                         cout << *it << " ";
  228.                         ++it;
  229.                 }
  230.                 cout << endl;
  231.                 for (auto e : lt)
  232.                 {
  233.                         cout << e << " ";
  234.                 }
  235.                 cout << endl;
  236.                 print_container(lt);
  237.                 list<AA> lta;
  238.                 lta.push_back(AA());
  239.                 lta.push_back(AA());
  240.                 lta.push_back(AA());
  241.                 lta.push_back(AA());
  242.                 list<AA>::iterator ita = lta.begin();
  243.                 while (ita != lta.end())
  244.                 {
  245.                         cout << ita->_a1 << ":" << ita->_a2 << endl;
  246.                         cout << ita.operator->()->_a1 << ":" << ita.operator->()->_a2 << endl;
  247.                         ++ita;
  248.                 }
  249.                 cout << endl;
  250.         }
  251.         void test_list2()
  252.         {
  253.                 list<int> lt;
  254.                 lt.push_back(1);
  255.                 lt.push_back(2);
  256.                 lt.push_back(3);
  257.                 lt.push_back(4);
  258.                 // insert以后迭代器不失效
  259.                 list<int>::iterator it = lt.begin();
  260.                 lt.insert(it, 10);
  261.                 *it += 100;
  262.                 print_container(lt);
  263.                 // erase以后迭代器失效
  264.                 // 删除所有的偶数
  265.                 it = lt.begin();
  266.                 while (it != lt.end())
  267.                 {
  268.                         if (*it % 2 == 0)
  269.                         {
  270.                                 it = lt.erase(it);
  271.                         }
  272.                         else
  273.                         {
  274.                                 ++it;
  275.                         }
  276.                 }
  277.                 print_container(lt);
  278.         }
  279.         void test_list3()
  280.         {
  281.                 list<int> lt1;
  282.                 lt1.push_back(1);
  283.                 lt1.push_back(2);
  284.                 lt1.push_back(3);
  285.                 lt1.push_back(4);
  286.                 list<int> lt2(lt1);
  287.                 print_container(lt1);
  288.                 print_container(lt2);
  289.                 list<int> lt3;
  290.                 lt3.push_back(10);
  291.                 lt3.push_back(20);
  292.                 lt3.push_back(30);
  293.                 lt3.push_back(40);
  294.                 lt1 = lt3;
  295.                 print_container(lt1);
  296.                 print_container(lt3);
  297.         }
  298.         void func(const list<int>& lt)
  299.         {
  300.                 print_container(lt);
  301.         }
  302.         void test_list4()
  303.         {
  304.                 // 直接构造
  305.                 list<int> lt0({ 1,2,3,4,5,6 });
  306.                 // 隐式类型转换
  307.                 list<int> lt1 = { 1,2,3,4,5,6,7,8 };
  308.                 const list<int>& lt3 = { 1,2,3,4,5,6,7,8 };
  309.                 func(lt0);
  310.                 func({ 1,2,3,4,5,6 });
  311.                 print_container(lt1);
  312.                 //auto il = { 10, 20, 30 };初始化列表
  313.         /*        initializer_list<int> il = { 10, 20, 30 };
  314.                 cout << typeid(il).name() << endl;
  315.                 cout << sizeof(il) << endl;*/
  316.         }
  317. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表