【C++初阶】八、STL---list(总)|list的介绍|list的使用
创始人
2024-05-23 06:25:56
0

目录

一、list的介绍

二、list的使用

2.1 Construct

2.2 operator=

2.3 Iterators

2.4 Capacity

2.5 Element access

2.6 Modifiers

2.7 Operations


一、list的介绍

        有数据结构作为基础,STL 上手很快,学习成本也低,本文也是讲解 list 常用重点接口,其它有需要再查询文档,重点也是放在 list 的模拟实现上面

list 文档介绍

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

         class Alloc = allocator 是空间配置器(内存池),暂时不用理会,它也给了缺省值,目前不用我们自己传,使用默认缺省值就可以了

使用 list 要包含 list 的头文件:

#include 

        list 要重点使用迭代器了,因为 list 不能支持随机访问了,即不能使用 “[]” + 下标 进行访问

二、list的使用

 list 也是掌握一些常用的接口,其它有需要在查询文档

先说一下成员变量

        value_type 就是第一个模板参数 (T);size_type 与 size_t 的用法一致,无符号

2.1 Construct

 接口简单说明:

构造函数接口说明
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

构造某个类型的 list 

list l1;//构造int类型的list
list l2;//构造double类型的list

测试代码

void Test_list()
{list l1;                         // 构造空的l1list l2(10, 3);                 // l2中放10个值为3的元素list l3(l2.begin(), l2.end());  // 用l2的[begin(), end())左闭右开的区间构造l3list l4(l3);                    // 用l3拷贝构造l4//以数组为迭代器区间构造l5int array[] = { 1,2,3,4 };list l5(array, array + sizeof(array) / sizeof(int));
}

2.2 operator=

测试代码

void Test_list()
{list l1(10, 3);// l1中构造10个值为3的元素list l2 = l1;//赋值重载list l3;l3 = l1;//赋值重载
}

析构函数不解释了,程序结束自动调用 

2.3 Iterators

        list 的迭代器不再是简单的原生指针了,指针要经过封装和重载才能支持 list 的迭代器的使用,范围 for 的底层就是迭代器。此处可暂时将迭代器理解成一个指针,该指针指向list中的某个节点,到 list 模拟实现再细讲

常用接口

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

示意图

 

注意:遍历 list 只能用迭代器和范围for 

 测试代码

void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));list::iterator it = l.begin();//迭代器判断结束只能使用 !=while (it != l.end()){cout << *it;++it;}cout << endl;for (auto e : l){cout << e;}cout << endl;
}

运行结果

注意:迭代器判断结束条件只能使用  != ,因为 list 的每个节点的空间的大小是不确定的,不能使用 it < l.end();之前 vector 和 string 的迭代器结束可以使用 < 判断迭代器结束,因为它们的空间是连续的

反向迭代器使用

void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));list::reverse_iterator it = l.rbegin();//迭代器判断结束只能使用 !=while (it != l.rend()){cout << *it;++it;}cout << endl;}

注意

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

 运行结果

2.4 Capacity

 常用接口

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

不演示,直接使用即可

2.5 Element access

常用接口

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

 

测试代码

void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));cout << l.front() << endl; //1cout << l.back() << endl; //0
}

 运行结果

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

 

测试代码

void Test_list()
{list l;l.push_back(1);//尾插数据l.push_back(2);l.push_back(3);l.push_back(4);for (auto e : l)cout << e;cout << endl;l.pop_back();//删除 4for (auto e : l)cout << e;cout << endl;l.push_front(0);//头插0for (auto e : l)cout << e;cout << endl;l.pop_front();//头删for (auto e : l)cout << e;cout << endl;
}

 运行结果

erase

测试代码

void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));list::iterator pos = find(l.begin(), l.end(), 2);l.erase(pos); //删除2for (auto e : l)cout << e;cout << endl;
}

运行结果

insert

测试代码

void Test_list()
{int array[] = { 1, 2, 4, 5, 6, 7, 8, 9 };list l(array, array + sizeof(array) / sizeof(array[0]));list::iterator pos = find(l.begin(), l.end(), 4);l.insert(pos, 3); //在4的位置的前一个插入3for (auto e : l)cout << e;cout << endl;
}

 运行结果

 list 的迭代器失效问题

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

        所以 insert 并不会造成迭代器失效,而 erase 之后则会造成 pos 迭代器失效,因为 pos 迭代器指向的空间已经被释放了

测试代码

void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));auto it = l.begin();while (it != l.end()){// erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给其赋值l.erase(it);++it;}
}

 运行结果

修改代码

void Test_list()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list l(array, array + sizeof(array) / sizeof(array[0]));auto it = l.begin();while (it != l.end()){l.erase(it++); // it = l.erase(it);}
}

 修改之后,程序就可以正常运行了

2.7 Operations

        这些接口不怎么使用,就不介绍了,有需要再查询文档,其中的 sort 排序数据量大的时候,效率低,也不怎么使用

----------------我是分割线---------------

文章到这里就结束了,下一篇即将更新

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...