C++STL详解(五)——list类的接口详解

一.list的介绍

list容器的底层是双向循环带头链表,在CPP中,我们对双向循环带头链表进行了一定程度的封装。

如果你不了解双向链表,那么可以浏览此片博文:双向链表

二.list的定义方式以及赋值

2.1list的构造方式

在这里我们要学习六种list的构造方式。

构造1:构造一个某类型容器

list<int> list1;

构造2:构造一个含有一个值的某类型容器

list<int> list2(3);//构造只含有一个数值3的结点的list容器

构造3:构造一个含有n个值的某类型容器

list<int> list3(3, 5);//构造含有三个数值都是5的结点的list容器

构造4:复制某个容器构造该容器的复制品

list<int> list4(list3);//拷贝构造

构造5:使用某个迭代器区间进行构造

list<int> list5(list3.begin(), list3.end());//迭代器区间初始化

 构造6:使用列表构造一个某类型容器

	list<int> list6{ 1,2,3,4,5,6 };//使用列表构造

 2.2operator=重载函数

同样的,我们也可以使用重载后的operator=操作符来进行给一个空的list容器赋值。

方式1:将别的同类型容器赋值给该容器

list<int> list7 = list5;

方式2:使用列表

list<int> list8 = { 1,2,3,4,5,6 };

三.list的插入和删除

list库中提供给我们大家的需要我们学习的函数是头插和尾插函数以及头删和尾删函数。

下面我们逐个进行学习。

3.1push_front和pop_front

我们可以通过这两个函数进行头插和头删。

函数原型如下:

	void push_front(const value_type& val);void pop_front();

 我们可以使用这两个函数对list的头部进行删除和插入操作。

如下:

void test2()
{list<int> list1;list1.push_front(3);list1.push_front(4);list1.push_front(5);list1.push_front(6);print(list1);//为了方便写博客,这个是自己写的函数。list1.pop_front();print(list1);
}

结果: 

6 5 4 3
5 4 3

3.2push_back和pop_back

 我们可以通过这两个函数进行尾插和尾删。

函数原型如下:

	void push_back(const value_type& val);void pop_back();

 我们可以使用这两个函数对list的尾部进行删除和插入操作。

void test2()
{list<int> list2;list2.push_back(1);list2.push_back(2);list2.push_back(3);list2.push_back(4);print(list2);list2.pop_back();print(list2);
}

 结果:

1 2 3 4
1 2 3

3.3insert

insert函数用于在指定位置插入数据。 

insert函数的函数原型如下:

iterator insert(iterator position, const value_type& val);//在pos位置插入一个val
void insert(iterator position, size_type n, const value_type& val);//在position位置插入n个val
void insert(iterator position, InputIterator first, InputIterator last);//在position位置插入[first,last)区间的内容。

insert:

  • 函数1:在position位置插入一个val
  • 函数2:在position位置插入n个val
  • 函数3:在position位置插入迭代器区间[first,last)中的内容。
void test3()
{list<int> l1(3, 1);l1.insert(l1.begin(), 2);print(l1);l1.insert(l1.begin(), 3,3);print(l1);list<int> l2{ 3,2,1 };l1.insert(l1.begin(), l2.begin(),l2.end());print(l1);
}

结果: 

2 1 1 1
3 3 3 2 1 1 1
3 2 1 3 3 3 2 1 1 1

3.4erase

 erase函数用于在指定位置删除数据。 

erase函数的函数原型如下:

iterator erase(iterator position);
iterator erase(iterator first, iterator last);

erase:

  • 函数1:删除position位置的数据。
  • 函数2:删除迭代区间[first,last)中的数据。 
void test3()
{list<int> l1(3, 1);l1.insert(l1.begin(), 2);l1.insert(l1.begin(), 3,3);list<int> l2{ 3,2,1 };l1.insert(l1.begin(), l2.begin(),l2.end());l1.erase(l1.begin());print(l1);l1.erase(++l1.begin(), --l1.end());//注意是前置++和--,而不是后置的++--print(l1);
}

结果:

2 1 3 3 3 2 1 1 1
2 1

四.list的迭代器使用

list和别的容器不同的地方在于:list的迭代器只支持++和--,不支持+和-。

因此,下面的操作是不合法的:

	list<int>::iterator it = find(3, l1.begin(), l1.end());it + 1;

4.1begin和end

begin()end()是list的正向迭代器函数

  • begin()函数返回list容器的第一个位置
  • end()函数返回list容器的最后一个位置的下一个位置

图解如下:

4.2rbegin和rend

rbegin()rend()是list的反向迭代器函数 

  • rbegin()函数返回vector容器的最后一个位置
  • rend()函数返回vector容器的第一个位置的前一个位置

图解如下: 

同样的,我们可以使用以上的两种迭代器对list内的元素进行遍历。

如下:

void test4()
{list<int> l1{ 1,2,3,4 };//正向迭代器list<int>::iterator it1 = l1.begin();while (it1 != l1.end()){cout << *it1 << ' ';it1++;}cout << endl;//反向迭代器list<int>::reverse_iterator it2 = l1.rbegin();while (it2 != l1.rend()){cout << *it2 << ' ';it2++;}cout << endl;
}

结果: 

1 2 3 4
4 3 2 1

五.list的元素获取

5.1front和back

front用于获取头部元素,back用于获取尾部元素。

这两个函数比较简单,我们使用一下即可。

void test5()
{list<int> l1{ 1,2,3,4 };cout << l1.front() << endl;cout << l1.back() << endl;
}

结果:

1

4

六.list的空间控制

6.1size

我们在初始化一个list容器之后,可以通过这个函数查看该容器的有效数据个数。

函数原型如下:

void size();

在我们用两个1初始化一个list容器之后,可以使用这个函数查看它的有效数据个数。 

6.2resize

使用这个函数可以重设函数的有效数据。

函数原型如下:

void resize(size_type n, value_type val = value_type());

resize:

  • 如果有效数据个数大于当前size,若规定了特定值则用特定值填充,否则用数据类型的默认值填充
  • 如果有效数据个数小于当前size,则只保留前size个数据。
void test6()
{list<int> l1(2, 1);cout << l1.size() << endl;l1.resize(5);print(l1);//1 1 0 0 0 l1.resize(10, 1); print(l1);//1 1 0 0 0 1 1 1 1 1l1.resize(3);print(l1);//1 1 0
}

6.3empty

empty函数判断list容器是否为空的函数。

empty:

  • 如果vector容器为空,则返回真
  • 如果vector容器不为空,则返回假。
	list<int> l1(2, 1);list<int> l2;cout << l1.empty() << endl;//0-->假cout << l2.empty() << endl;//1-->真

6.4clear

clear函数用于清除list容器中的数据并置size为0.

clear:

  • 清除掉list容器内所有的元素,并将size置为0
list<int> l1(2, 1);
cout << l1.empty() << endl;//0-->假
l1.clear();
cout << l1.empty() << endl;//1-->真

6.5assign

assign函数用于将新内容分配给容器,替换其当前内容。

assign函数原型如下:

	void assign(InputIterator first, InputIterator last);void assign(size_type n, const value_type & val);

assign: 

  • 函数2:将所给迭代器区间当中的内容分配给容器。
  • 函数1:将n个值为val的数据分配给容器。
void test13()
{list<int> l1(3, 1);list<int> l2(3,2);print(l1);//1 1 1l1.assign(5, 2);print(l1);///2 2 2 2 2l1.assign(l2.begin(), l2.end());print(l1);//2 2 2
}

结果:

1 1 1
2 2 2 2 2
2 2 2

 

七.list的操作相关函数

7.1sort

sort函数是用于升序排列list内的元素的。

函数原型如下:

void sort();

sort:

  • 将list内的元素默认排为升序。 
void test7()
{list<int> l1{ 10,9,8,7,6,5,4,3,2,1 };print(l1);//10 9 8 7 6 5 4 3 2 1l1.sort();print(l1);//1 2 3 4 5 6 7 8 9 10
}

结果:

10 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 10

7.2splice

splice的功能类似于vector的insert函数,它可以用于在指定位置将另一个list容器插入。

但是,这个和insert函数不同的是,splice函数本质是一种转移,而不是复制。

splice的函数原型如下:

void splice(iterator position, list& x);
void splice(iterator position, list& x, iterator i);
void splice(iterator position, list& x, iterator first, iterator last);

splice:

  • 函数1:在position位置转移x容器的所有元素
  • 函数2:在position位置转移xi位置的元素
  • 函数3:   在position位置转移x的[first,last)区间内的元素。
void test8()
{list<int> l1{ 5,4,3,2,1 };list<int> l2{ 6,7,8,9,10 };list<int> l3{ 0,11,12,13 };list<int> l4{ 0,11,12,13 };l1.splice(l1.end(), l2);print(l1);//5 4 3 2 1 6 7 8 9 10l1.splice(l1.end(), l3,++l3.begin());print(l1);//5 4 3 2 1 6 7 8 9 10 11 print(l3);//0 12 13l3.splice(l3.begin(), l4,++l4.begin(),--l4.end());print(l3);//11 12 0 11 12print(l4);//0 13
}

 结果:

5 4 3 2 1 6 7 8 9 10
5 4 3 2 1 6 7 8 9 10 11
0 12 13
11 12 0 12 13
0 13
 

这里需要大家注意的是,splice函数的本质是转移!

现在我通过画图的形式来解析这段代码:

四个容器:

第一次转移:

第二次转移:

第三次转移:

7.3remove

remove函数是用来删除list容器内的值的。

函数原型如下:

void remove (const value_type& val);

remove:

  • remove函数可以删除掉容器内所有值是val的结点 
void test9()
{list<int> l1{ 5,4,4,3,2,1 };print(l1);//5 4 4 3 2 1l1.remove(4);print(l1);//5 3 2 1
}

 结果:

5 4 4 3 2 1
5 3 2 1

7.4unique

这个函数是用来去除相同的元素的。

它会拿当前的元素和下一个元素进行比较,如果和下一个元素相同的话,则删掉下一个元素。

因为它的这个特性,我们常用于有序列表的去重。

函数原型如下:

void unique();

我们可以通过下面这段代码体会到这个函数的性质:相邻比较,相等删除。 

void test10()
{list<int> l1{ 1,1,3,3,4,1 };l1.unique();print(l1);//1 3 4 1
}

结果:

1 3 4 1 

7.5merge

merge函数用于合并两个有序list容器。

merge函数的原型如下:

 void merge (list& x);

merge:

  • merge函数用于合并两个有序的list容器,合并后的list容器依旧有序。
  • 作为参数被传递的容器被合并后会为空
void test11()
{list<int> l1{1,3,5,7,9};list<int> l2{2,4,6,8,10};l1.merge(l2);print(l1);//1 2 3 4 5 6 7 8 9 10print(l2);//
}

结果:

1 2 3 4 5 6 7 8 9 10

 7.6reverse

reverse用于翻转链表。

函数原型如下: 

void reverse();
void test12()
{list<int> l1{ 1,3,5,7,9 };l1.reverse();print(l1);
}

结果:

9 7 5 3 1 

7.7swap

swap函数用于交换两个容器的内容。

void test14()
{list<int> l1(3, 1);list<int> l2(3, 2);l1.swap(l2);print(l1);//2 2 2print(l2);//1 1 1
}

结果:

2 2 2
1 1 1 

八.list的迭代器失效问题

在之前的文章中提过这个问题,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,而双向循环链表的扩容和顺序表不同,是不会出现异地扩容的现象的。因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

下面的这段代码就是非常典型的一段迭代器失效的代码: 

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

和vector一样,我们在使用前给迭代器赋值即可。

void test15()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array + sizeof(array) / sizeof(array[0]));list<int>::iterator it = l.begin();while (it != l.end()){it=l.erase(it);++it;//这行代码和上面两行代码等效//l.erase(it++)}
}

九.后记

有关list的模拟实现可参考博主的下篇博文。

如果你想更深入的了解list的相关内容,可参考cpp官网:cpp官网

码字不易,给个点赞收藏叭~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/51492.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

英特尔宣布针对对Llama 3.1进行优化 以提升所有产品的性能

日前Meta正式发布了Llama 3.1开源大模型&#xff0c;以其庞大的参数量和卓越性能&#xff0c;首次在多项基准测试中击败了GPT-4o等业界领先的闭源模型。允许开发者自由地进行微调、蒸馏&#xff0c;甚至在任何地方部署&#xff0c;这种开放性为AI技术的普及和创新提供了无限可能…

具备音视频指挥调度能力的指挥中心需要接入哪些设备呢?

近年来&#xff0c;具备音视频能力的指挥调度系统在各行各业中应用广泛&#xff0c;通过音视频的通信调度能力&#xff0c;为行业提供灵活的指挥调度功能&#xff0c;实现行业多种音视频应用场景的运用&#xff0c;满足企业更好地完成企业安全生产、应急协调等工作的需求。 华…

代码随想录训练营 Day13打卡 二叉树 part01 递归遍历 迭代遍历 层序遍历

代码随想录训练营 Day13打卡 二叉树 part01 一、 二叉树理论基础 二叉树是一种重要的数据结构&#xff0c;用于表示具有层次关系的数据。二叉树的每个节点最多有两个子节点&#xff0c;通常称为左子节点和右子节点。 种类 普通二叉树&#xff1a; 节点最多有两个子节点&…

Hadoop3:HDFS的客户端工具Big Data Tools(IDEA版本)

1、安装插件 在Plugins里搜索Big Data Tools 安装完成后&#xff0c;重启IDEA 2、配置Windows环境 主要是配置Hadoop环境&#xff0c;否则无法通过插件远程连接HDFS 1、解压hadoop安装包 2、进入hadoop的bin目录 放入图中标红的两个文件 3、配置hadoop环境变量 新建HAD…

这个暑假适合港澳游?免税额度提升、专属暑期活动、餐饮娱乐攻略

2024年7月1日免税额度的新政实施&#xff0c;在香港澳门消费的免税额度将达到15000元。这也让今年夏天的港澳旅游多了几分吸引力&#xff0c;如果有计划趁着这个暑假前往港澳旅游的话&#xff0c;这篇港澳游攻略一定能帮到你&#xff01; 【民以食为天&#xff0c;旅游第一步—…

“多分辨率图网络”的模型:准确识别卵巢癌各种亚型

卵巢癌发病率居我国女性生殖系统恶性肿瘤第3位&#xff0c;死亡率居妇科恶性肿瘤之首&#xff0c;其特点是存在异质性的组织学亚型。最常见的五种亚型&#xff0c;占所有卵巢癌的90%&#xff0c;分别是高级别浆液性癌&#xff08;HGSC&#xff09;、低级别浆液性癌&#xff08;…

项目实战--JUC之CompletableFuture温故

CompletableFuture温故 一、前言二、Future三、CompletableFuture3.1 CompletableFuture定义3.2 CompletableFuture使用场景3.3 CompletableFuture 常见操作3.3.1 创建CompletableFuture3.3.2 使用CompletableFuture3.3.3 异常处理3.3.4 注意事项 四、CompletableFuture处理工具…

阿里云创建的SpringBoot项目打包时找不到主清单属性

原因是因为maven配置文件中有一个打包属性配置 <configuration><mainClass>com.yang.ExamSystemApplication</mainClass><!-- 找到这个<skip>true</skip>标签关闭&#xff0c;或者属性改为false --><skip>true</skip> </c…

Hive环境搭建(Mysql数据库)

【实验目的】 1) 了解hive的作用 2) 熟练hive的配置过程&#xff08;Mysql数据库&#xff09; 【实验原理】 Hive工具中默认使用的是derby数据库&#xff0c;该数据库使用简单&#xff0c;操作灵活&#xff0c;但是存在一定的局限性&#xff0c;hive支持使用第三方数据库&…

第一百八十三节 Java IO教程 - Java目录事件、Java异步I/O

Java IO教程 - Java目录事件 当文件系统中的对象被修改时&#xff0c;我们可以监听watch服务以获取警报。 java.nio.file包中的以下类和接口提供watch服务。 Watchable接口WatchService接口WatchKey接口WatchEvent接口WatchEvent.Kind接口StandardWatchEventKinds类 可监视对…

FPGA开发——按键控制LED的实现

一、概述 在上一篇文章中我们学习了按键的相关消抖及其使用&#xff0c;在这篇文章当中我们就针对通过按键实现LED的控制。 1、按键原理图 2、基本框架 通过我们前面编写的按键消抖的文件和LED文件将按键和LED两个模块进行交互&#xff0c;从而达到按键控制LED的目的。 二、…

计算机毕业设计碾压导师Python+Django农产品推荐系统 农产品爬虫 农产品商城 农产品大数据 农产品数据分析可视化 PySpark Hadoop

基于Spark的农产品个性推荐系统 相关技术介绍: 1. Python Python是一种高级编程语言&#xff0c;具有简洁、易读、易学的特点&#xff0c;被广泛应用于Web开发、数据分析、人工智能等领域。 在此系统中&#xff0c;我们使用Python进行后端开发&#xff0c;利用其强大的语法…

Mysql 输出本月初至当前的全部天数

代码&#xff1a; SELECT DATE_FORMAT(DATE_ADD(CONCAT(DATE_FORMAT(CURDATE(), "%Y-%m-01")),INTERVAL (CAST(help_topic_id AS SIGNED)) DAY),%Y-%m-%d) as DATE FROMmysql.help_topic WHERE help_topic_id < TIMESTAMPDIFF(DAY, CONCAT(DATE_FORMAT(CURDATE…

【最优化方法】随笔 - 基本概念简单整理

文章目录 前言1.背景知识两个概念&#xff1a; 2.最优化问题2.1应用2.2 最优化问题的数学形式极小化目标函数可行区域可行解 2.3 举例说明2.4 最优化问题不同的类型2.5 一些概念 3.凸集和凸函数3.1 范数3.2 矩阵范数&#xff08;扩展&#xff09;3.3 凸集与凸函数凸集凸函数 写…

无人机像素经纬度识别

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

旅美钢琴学者何超东北巡演启幕,精湛演绎肖邦全套作品

7月26日、28日&#xff0c;旅美钢琴学者何超在长春和哈尔滨两地成功开启了他的暑期钢琴独奏音乐会东北巡演。在这两场演出中&#xff0c;何超为观众带来了全套肖邦的「谐谑曲」与「叙事曲」&#xff0c;以娴熟的技巧、惊人的记忆力和体力&#xff0c;将八首曲目一气呵成&#x…

这可能是开源界最好用的能源管理系统

&#x1f482; 个人网站: IT知识小屋&#x1f91f; 版权: 本文由【IT学习日记】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦 文章目录 写在前面项目简介项目特点项目架构模块展示项目获取 写在前面 大…

buu做题(9)

[MRCTF2020]PYWebsite 有个二维码 扫了一下啊二维码 function enc(code){hash hex_md5(code);return hash;}function validate(){var code document.getElementById("vcode").value;if (code ! ""){if(hex_md5(code) "0cd4da0223c0b280829dc3ea4…

Java之归并排序

归并排序 归并排序(Merge Sort)算法&#xff0c;使用的是分治思想。分治&#xff0c;顾名思义&#xff0c;就是分而治之&#xff0c;将一个大问题分解成小的子问题来解决。小的子问题解决了&#xff0c;大问题也就解决了。 核心源码: mergeSort(m->n) merge(mergeSort(m-&g…

什么是等保测评?

信息安全等级保护测评&#xff0c;简称等保测评&#xff0c;是根据我国《信息安全等级保护管理办法》的规定&#xff0c;对国家重要信息系统进行的安全评估制度。等保测评的频率、必要性以及在实际操作中的常见误区&#xff0c;是企业和机构在进行等保测评时需要了解的重要内容…