ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【C++】list(上) [打印本页]

作者: 锦通    时间: 2024-9-8 09:38
标题: 【C++】list(上)

个人主页~
list这一篇章格式以及调试方式都类似于vector和string,学完前面的两个再学这个就很简单了,接口也都大差不差,有了数据结构链表的底子就很好理解


  
一、list的先容和使用

1、list的先容

list是可以在常数范围内在恣意位置进行插入和删除的序列式容器,而且该容器可以前后双向迭代
list的底层是双向链表结构,双向链表中每个元素存储在互不相关的节点中,在节点中通过指针与前一个和后一个元素创建联系
list的优点是在恣意位置进行插入和移除元素执行效率高,缺点就是不能支持随机访问
2、list的使用

(1)list的构造

构造函数接口说明list(size_type n,const value_type& val = value_type())构造的list中包含n个值为val的元素list()构造空listlist(const list& x)拷贝构造函数list(InputIterator first,InputIterator last)用迭代器区间中的元素构造list
  1. void test1()
  2. {
  3.         list<int> lt1(10, 1);
  4.         list<int> lt2;
  5.         list<int> lt3(lt1);
  6.         list<int> lt4(lt1.begin(), lt1.end());
  7.         for (auto e : lt1)
  8.         {
  9.                 cout << e << " ";
  10.         }
  11.         cout << endl;
  12.         for (auto e : lt3)
  13.         {
  14.                 cout << e << " ";
  15.         }
  16.         cout << endl;
  17.         for (auto e : lt4)
  18.         {
  19.                 cout << e << " ";
  20.         }
  21.         cout << endl;
  22. }
复制代码
构造函数、拷贝构造函数正常

这里的lt2还有原始视图是空构造

(2)list 迭代器的使用

函数声明接口说明begin和end返回第一个元素的迭代器为begin和返回末了一个元素下一个位置的迭代器为endrbegin和rend返回第一个元素的迭代器为end和返回末了一个元素下一个位置的迭代器为begin 值得注意的是,rbegin和rend为反向迭代器,对迭代器执行++操纵,迭代器向前移动,也就是说forward_list也就是单链表是没有rbegin和rend迭代器的
  1. void test2()
  2. {
  3.         list<int> lt1(10, 0);
  4.         auto it = lt1.begin();
  5.         int i = 1;
  6.         for (auto& e : lt1)
  7.         {
  8.                 e += i;
  9.                 i++;
  10.         }
  11.         for (auto e : lt1)
  12.         {
  13.                 cout << e << " ";
  14.         }
  15.         cout << endl;
  16. }
复制代码

(3)list 容量的使用

函数声明接口说明empty检测list是否为空size返回list中节点的有效个数
  1. void test3()
  2. {
  3.         list<int> lt1(10, 0);
  4.         list<int> lt2;
  5.         cout << lt1.empty() << " ";
  6.         cout << lt1.size() << endl;
  7.         cout << lt2.empty() << " ";
  8.         cout << lt2.size() << endl;
  9. }
复制代码

(4)list元素访问

函数声明接口说明front返回list第一个节点值的引用back返回list末了一个节点值的引用
  1. void test4()
  2. {
  3.         list<int> lt1(10, 0);
  4.         lt1.front() = 1;
  5.         lt1.back() = 2;
  6.         for (auto e : lt1)
  7.         {
  8.                 cout << e << " ";
  9.         }
  10.         cout << endl;
  11. }
复制代码

(5)list修改

函数声明接口说明push_front在list第一个元素之前插入一个元素pop_front删除list第一个元素push_back在list末了一个元素之后插入一个元素pop_back删除list末了一个元素insert在pos位置插入一个元素erase删除pos位置的元素swap交换两个list中的元素clear清空list中的有效元素
  1. void test5()
  2. {
  3.         list<int> lt1(10, 0);
  4.         //插入
  5.         lt1.push_front(1);
  6.         lt1.push_back(2);
  7.         for (auto e : lt1)
  8.         {
  9.                 cout << e << " ";
  10.         }
  11.         cout << endl;
  12.         //删除
  13.         lt1.pop_front();
  14.         lt1.pop_back();
  15.         for (auto e : lt1)
  16.         {
  17.                 cout << e << " ";
  18.         }
  19.         cout << endl;
  20.         int i = 1;
  21.         for (auto& e : lt1)
  22.         {
  23.                 e += i;
  24.                 i++;
  25.         }
  26.         //insert/erase
  27.         auto it = find(lt1.begin(), lt1.end(), 5);
  28.         lt1.insert(it, 11);
  29.         lt1.erase(it);
  30.         for (auto e : lt1)
  31.         {
  32.                 cout << e << " ";
  33.         }
  34.         cout << endl;
  35.         //swap
  36.         list<int> lt2(10, 1);
  37.         lt1.swap(lt2);
  38.         for (auto e : lt2)
  39.         {
  40.                 cout << e << " ";
  41.         }
  42.         cout << endl;
  43.         //clear
  44.         lt1.clear();
  45.         cout << lt1.empty() << endl;
  46. }
复制代码

使用方面都挺简单的,不再叙述了,参数直接查cplusplus就行
(6)list迭代器失效

由于list的底层结构为带头节点的双向循环链表,所以在list中进行插入是不会导致list的迭代器失效的,只有在删除时才会失效,而且失效的只是指向被删除节点的迭代器,其他的迭代器不受影响
二、list与vector的对比

list和vector都是STL中重要的序列式容器,二者在接口上基本相同,但在底层实现上有巨大的差别,我们来对比一下
对比vectorlist底层结构动态顺序表,一段一连空间带头节点的双向循环列表随机访问支持随机访问,访问某个元素效率O(1)不支持随机访问,访问某个元素效率O(N)插入和删除恣意位置插入和删除效率低,需要移动元素,时间复杂度为O(N),插入时有可能需要增容,开辟新空间,拷贝元素,开释旧空间,导致效率更低恣意位置插入和删除效率高,不需要移动元素,时间复杂度为O(1)空间使用率底层为一连空间,不容易造成内存碎片,空间使用率高,缓存使用率高底层节点动态开辟,小节点容易造成内存碎片,空间使用率低,缓存使用率低迭代器原生态指针对原生态指针进行封装迭代器失效在插入元素时,要给所有的迭代器重新赋值,由于插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效插入元素不会导致迭代器失效,删除元素时,只会导致当前迭代器失效,其他迭代器不受影响使用场景需要高效存储,支持随机访问,不关心插入删除效率大量的插入和删除操纵,不关心随机访问 两者使用场景差别,各有千秋,在使用的时候合理搭配,就可以发挥最大价值
三、list其他接口


在图中可以看到,list除了常用的几种接口以外,还有其他的功能的接口,这里简单先容一下,学习还需要到cplusplus网站上详细参考参数返回值以及一系列的内容
1、splice

将某个list移动到另一个容器当中,有三种方式:一是将list中的所有元素都传输到容器中,二是仅将迭代器指向的元素从list传输到另一个容器当中,第三个就是迭代器范围传输,从first迭代器到last迭代器的元素传输到另一个容器当中
  1. void test6()
  2. {
  3.         list<int> lt1(10, 0);
  4.         list<int> lt2(10, 1);
  5.         lt1.splice(lt1.begin(),lt2);
  6.         for (auto e : lt1)
  7.         {
  8.                 cout << e << " ";
  9.         }
  10. }
复制代码

2、remove

与erase可以相比较,它们都是删除接口,而erase的参数是一个迭代器,而remove的参数是一个值,它的作用是删除所有等于某个值的元素,然后调解容器巨细
  1. void test7()
  2. {
  3.         list<int> lt1(10, 0);
  4.         int i = 1;
  5.         for (auto& e : lt1)
  6.         {
  7.                 e += i;
  8.                 i++;
  9.         }
  10.         for (auto e : lt1)
  11.         {
  12.                 cout << e << " ";
  13.         }
  14.         cout << endl;
  15.         lt1.remove(5);
  16.         for (auto e : lt1)
  17.         {
  18.                 cout << e << " ";
  19.         }
  20. }
复制代码

3、unique

删除一连相等的除了一个以外的元素
  1. void test8()
  2. {
  3.         list<int> lt1(10, 0);
  4.         list<int> lt2(10, 1);
  5.         lt1.splice(lt1.begin(), lt2);
  6.         for (auto e : lt1)
  7.         {
  8.                 cout << e << " ";
  9.         }
  10.         cout << endl;
  11.         lt1.unique();
  12.         for (auto e : lt1)
  13.         {
  14.                 cout << e << " ";
  15.         }
  16. }
复制代码

4、sort

  1. void test9()
  2. {
  3.         list<int> lt1(10, 0);
  4.         int i = 10;
  5.         for (auto& e : lt1)
  6.         {
  7.                 e += i;
  8.                 i--;
  9.         }
  10.         for (auto e : lt1)
  11.         {
  12.                 cout << e << " ";
  13.         }
  14.         cout << endl;
  15.         lt1.sort();
  16.         for (auto e : lt1)
  17.         {
  18.                 cout << e << " ";
  19.         }
  20. }
复制代码


本日分享就到这了~


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4