C++从入门到起飞之——list使用 全方位剖析!

news2024/11/24 1:26:14

 

🌈个人主页:秋风起,再归来~
🔥系列专栏:C++从入门到起飞          
🔖克心守己,律己则安

目录

1、迭代器

2、push_back与emplace_back

3、list成员函数sort与库sort比较

4、merge

5、unique

6、splice 

7、完结散花


前置声明:本文章对于list常用简单的接口不会介绍!

1、迭代器

假如我们想要在list的正向迭代器后的第三位置插入一个2,在上面的这种写法就不再支持了!而我们之前在string和vector的使用时这样玩是完全没有问题的!那是为什么呢!

通过查阅文档资料,我们可以发

现在list下的的迭代器是bidirectional iterator(双向迭代器)

那双向迭代器又是什么意思呢?下面我就和大家总结一下迭代器从功能和性质上的分类:
>从功能上可分为以下四种:

1、正向迭代器

2、反向迭代器

3、正向常量迭代器

4、反向常量迭代器

所有容器的迭代器都具有以上四种功能,用起来也比较简单。

>从性质上可分为以下四种:

1、随机迭代器(RandomAccessIterator):string、vector、deque……(支持操作++ /-- / + / -)

2、双向迭代器(BidirectionalIterator):list、map、set……(支持操作++ /-- )

3、单向迭代器:forward_list、unordered_map……(支持操作++)

容器间迭代器性质上的差异是由容器的底层结构来决定的!而底层结构又决定容器可以使用库里面哪些算法

举个栗子:

list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
sort(lt.begin(), lt.end());

这段代码在编译上并没有报错,不过在运行时就有问题了!

查看资料我们就可以发现问题所在:

我们可以看到,库里面Sort的参数必须是随机的迭代器,因为该Sort的底层是快排,涉及到了迭代器的+和-的操作。

我们还可以注意到第三个参数comp,这其实是一个比较器。这里只演示一下比较器的用法,其底层后面会详细讲解!

vector<int> v;
v.push_back(3);
v.push_back(4);
v.push_back(1);
v.push_back(7);
v.push_back(5);
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;
sort(v.begin(), v.end());
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;

在默认情况下,Sort是按照从小到大的顺序排列元素的,如果我们想要按从大到小的顺序排列的话,我们就可以再传递一个比较器!

//greater<int> g;
//sort(v.begin(), v.end(),g);  有名对象这里用的有点烦
//这时候用匿名对传递就很香
sort(v.begin(), v.end(), greater<int>());
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;

当然,也有小的比较器,这里我们还是要知道一下(效果其实和默认的没什么区别)!

>我们再来看看reverse:

要求传双向迭代器,不过我们也要明白这里不仅可以传双向迭代器,也可以传随机迭代器,毕竟随机迭代器是特殊的双向迭代器。

>我们再来看看find:

Find里面可以传递所有类型的迭代器! 

2、push_back与emplace_back

先说结论,push_back与emplace_back的最终效果都是尾插一个元素,不过emplace_back在某些情况下比push_back的效率要更高一些!

下面举一个代码示例:

class A
{
public:
	A(int a1 = 0, int a2 = 0)
		:_a(a1)
		, _b(a2)
	{
		cout << "A(int a1 = 0, int a2 = 0)" << endl;
	}

	A(const A& aa)
		:_a(aa._a)
		, _b(aa._b)
	{
		cout << "A(const A& aa)" << endl;
	}
private:
	int _a;
	int _b;
};

void test3()
{
	list<A> lt;
	A a1(3, 3);
	lt.push_back(a1);//有名对象传参
	lt.push_back(A(2,2));//匿名对象传参
	//lt.push_back(3,3);  报错!

	A a2(3, 3);
	lt.emplace_back(a2);
	lt.emplace_back(A(2, 2));
	cout << endl;
	lt.emplace_back(3,3);//emplace_back还支持直接传递构造A对象的参数!

那emplece_back到底高效在哪些地方呢?

通过函数调用在屏幕上打印的结果我们发现,前面的传参都是构造加拷贝构造,唯有最后的传参是直接调用构造而并没有调用拷贝构造。这说明emplace_back的直接传递构造对象的参数是可以减少拷贝构造的,这也在一定程度上提高了效率。

至于其底层原理还不是我们目前可以明白的,以后我们再细说啦~

3、list成员函数sort与库sort比较

由于不能直接使用库里面的sort,所以list自己实现了一个sout(底层实际上用的是归并)

 下面我们来比较一下在相同数据情况下vector调库里面的sortlist调自己的sort性能之间的优劣

srand((unsigned int)time(nullptr));
const int N = 1000000;

list<int> lt1;
vector<int> v;

for (int i = 0; i < N; ++i)
{
	auto e = rand() + i;
	lt1.push_back(e);
	v.push_back(e);
}

int begin1 = clock();
// 排序
sort(v.begin(), v.end());
int end1 = clock();

int begin2 = clock();
lt1.sort();
int end2 = clock();

printf("vector sort:%d\n", end1 - begin1);
printf("list sort:%d\n", end2 - begin2);

 在debug模式下,库里面的sort略胜一筹

release模式下速度是list的将近4倍! 

>下面我们再来看一段更有意思的比较

下面这段代码主要的意思我们先在lt1和lt2中存储相同的数据,我们再分别计算两段时间进行比较!

第一段计算的时间是我们先把lt1中的数据拷贝到v中,在通过v调用库里面的sort来排序,最后再从v中将有序的数据拷贝回lt1中。

第二段计算的时间是我们直接通过lt2调用自己的sort来将数据进行排序!

void test_op2()
{
	srand(time(0));
	const int N = 1000000;

	list<int> lt1;
	list<int> lt2;

	for (int i = 0; i < N; ++i)
	{
		auto e = rand() + i;
		lt1.push_back(e);
		lt2.push_back(e);
	}

	int begin1 = clock();
	// 拷贝vector
	vector<int> v(lt2.begin(), lt2.end());

	// 排序
	sort(v.begin(), v.end());

	// 拷贝回lt2
	lt2.assign(v.begin(), v.end());

	int end1 = clock();

	int begin2 = clock();
	lt1.sort();
	int end2 = clock();

	printf("list copy vector sort copy list sort:%d\n", end1 - begin1);
	printf("list sort:%d\n", end2 - begin2);
}

 在debug测试版本下我们相差不多

不过,在release发行版本下,第一段的速度依旧接近你的2倍! 

通过这段测试想要告诉你们的是list内部实现的sort用起来方便,可效率却不高,我们写程序首先要确保层序的正确性,二是要追求程序的高效与安全!我们以后在用list存储数据进行排序时最好不要用它内置的sort,绕一下弯就可以大大提高效率!

4、merge

接口merge的主要功能是合并两个链表(但是要注意其中一个链表会变空,相当于把其中一个链表的节点连接到另一个链表的后面去了!)

std::list<double> first, second;

first.push_back(3.1);
first.push_back(2.2);
first.push_back(2.9);

second.push_back(3.7);
second.push_back(7.1);
second.push_back(1.4);

first.sort();
second.sort();

first.merge(second);

// (second is now empty)

合并后链表是有序的!

注意:使用该接口时要确保两个链表的数据是有序的并且类型要匹配! 

5、unique

unique是去重算法,使用的前提条件是链表必须有序!

std::list<int> lt;

lt.push_back(3);
lt.push_back(1);
lt.push_back(2);
lt.push_back(4);
lt.push_back(4);
lt.push_back(5);
lt.push_back(5);
lt.push_back(5);

lt.sort();
lt.unique();

6、splice 

用splice 将lt2的所有元素剪切到 lt.end()前面!

std::list<int> lt;
std::list<int> lt2;

lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);

lt2.push_back(2);
lt2.push_back(3);
lt2.push_back(4);
lt2.push_back(5);

lt.splice(lt.end(),lt2);

 用splice将lt2的第一个元素剪切到 lt.begin()前面!

lt.splice(lt.begin(),lt2,lt2.begin());

还可以将自己的元素进行剪切拼接!

假如我想要将元素5插入到2前面,我们可以这样操作!

std::list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);
auto pos1 = find(lt.begin(), lt.end(), 2);
auto pos2 = find(lt.begin(), lt.end(), 5);
lt.splice(pos1,lt,pos2)

7、完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​​​​​

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

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

相关文章

2024117读书笔记|《李煜词(果麦经典)》——一壶酒,一竿身,快活如侬有几人?一片芳心千万绪,人间没个安排处

2024117读书笔记|《李煜词&#xff08;果麦经典&#xff09;》——一壶酒&#xff0c;一竿身&#xff0c;快活如侬有几人&#xff1f;一片芳心千万绪&#xff0c;人间没个安排处 《李煜词&#xff08;果麦经典&#xff09;》李煜的词很美&#xff0c;插图也不错&#xff0c;很值…

基于粒子群优化算法的六自由度机械臂三维空间避障规划

摘要&#xff1a;本研究旨在解决机械臂在复杂环境中避障路径规划的问题。本文提出了一种利用粒子群优化算法&#xff08;PSO&#xff09;进行机械臂避障规划的方法&#xff0c;通过建立机械臂的运动模型&#xff0c;将避障问题转化为优化问题。PSO算法通过模拟群体中个体的社会…

ggml 简介

ggml是一个用 C 和 C 编写、专注于 Transformer 架构模型推理的机器学习库。该项目完全开源&#xff0c;处于活跃的开发阶段&#xff0c;开发社区也在不断壮大。ggml 和 PyTorch、TensorFlow 等机器学习库比较相似&#xff0c;但由于目前处于开发的早期阶段&#xff0c;一些底层…

8月28c++

c手动封装顺序表 #include <iostream>using namespace std; using datatype int;//类型重命名struct SeqList { private:datatype *data;//顺序表数组int size0;//数组大小int len0;//顺序表实际长度 public:void init(int s);//初始化函数bool empty();//判空函数bool …

python有主函数吗

python和C/Java不一样&#xff0c;没有主函数一说&#xff0c;也就是说python语句执行不是从所谓的主函数main开始的。 当运行单个python文件时&#xff0c;如运行a.py&#xff0c;这个时候a的一个属性__name__是__main__。 当调用某个python文件时&#xff0c;如b.py调用a.p…

HDD介绍

HDD是“Hard Disk Drive”的缩写&#xff0c;意为“硬盘驱动器”&#xff0c;是计算机中用于存储数据和程序的主要设备之一。 硬盘有机械硬盘(Hard Disk Drive&#xff0c;HDD)和固态硬盘(SSD)之分。机械硬盘即是传统普通硬盘&#xff0c;主要由&#xff1a;盘片&#xff0c;磁…

2024年华侨生联考英语真题全析:难度变化与备考策略

导读 在前面我们和大家一起分享了2024年华侨生联考各科真题的难度情况。今天我们就来和大家具体的看一下2024年港澳台华侨生联考英语真题试卷具体分析哈。 听力部分 今年的听力和去年的听力总体难度差别不大&#xff0c;一段听力材料对应一道听力题目&#xff08;简称一对一…

谐波电抗器选择的最佳方法

选择谐波电抗器的最佳方法取决于系统的具体要求和条件。 以下是选择谐波电抗器时需要考虑的关键因素和方法&#xff1a; 1、确定系统谐波频率 谐波分析&#xff1a;使用谐波分析仪测量系统中的谐波频率&#xff0c;确定主要的谐波频率和幅值。谐波电抗器的选择需要针对这些谐…

2024年6月GSEP(python)一级认证真题讲解

注意&#xff01;做题时长为2小时&#xff0c;孩子做完题目后对照讲解视频和讲解分析&#xff0c;针对薄弱点&#xff0c;进行有效的专项提高。 &#x1f451;讲解视频 &#xff08;暂无&#xff09; &#x1f451;讲解分析 1 单选题&#xff08;每题 2 分&#xff0c;共 3…

【CVPR‘23】CompletionFormer:用于深度补全的 Transformer 网络!已开源

【CVPR23】CompletionFormer:用于深度补全的 Transformer 网络! 摘要方法3.1 RGB 和深度嵌入3.2 联合卷积注意力和 Transformer 编码器3.3 解码器3.4 SPN 精化和损失函数主要贡献实验结果论文地址:https://openaccess.thecvf.com/content/CVPR2023/papers/Zhang_CompletionF…

C语言指针重学

学习要纲:建议掌握 gdb调试(b ,d ,fin ,bt ,print ,awatch ,up ,down ,set pretty等) SourceInsight软件看代码(全局搜索 文件搜索等) git如何调取分支合并(git branch,git blame,git log,git pull,git reset --hard等) 等内容,下面是对于指针的一个重新学习. C语言的指针&…

如何使用ssm实现基于java web的计算机office课程平台设计与实现+vue

TOC ssm277基于java web的计算机office课程平台设计与实现vue 绪论 1.1 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利…

WireShark网络分析~部署方式

一、《Wireshark网络分析就这么简单》 第一章学习 声明&#xff1a;文章只限于网络学习和实验&#xff0c;请遵守《网络安全法》。 第一章问题一&#xff1a;两台服务器A和B的网络配置如下(见图1)&#xff0c;B的子网掩码本应该是255.255.255.0&#xff0c;被不小心配成了255.…

LeetCode 热题100-37 二叉树的最大深度

二叉树的最大深度 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;ro…

py 可视化图层

五张图&#xff1a;数据资源可联系1493175691qq.com import numpy as np import matplotlib.pyplot as plt from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter import cartopy.crs as ccrs import cartopy.feature as cfeature from cartopy.io.shaperead…

长亭雷池 WAF 部署及使用过程中遇到的问题

1、安装过程中遇到的问题 这里推荐使用官方的脚本命令&#xff0c;大概看了一下是先判断是否有容器&#xff0c;如果没有容器环境就安装&#xff0c;但是这一步就报错了。这里需要更换成阿里云或是国内其它的源来安装。 bash -c "$(curl -fsSLk https://waf-ce.chaitin.…

黑神话悟空丨资源合集,光追配置+修改器+各种奇奇怪怪的MOD

国产3A大作 黑神话悟空 推出了一些奇奇怪怪的mod(非官方)&#xff0c;作为一款备受瞩目的单机作品&#xff0c;黑神话悟空 不仅在剧情和画面上表现出色&#xff0c;同时也为玩家提供了丰富的Mod支持。 哈哈哈哈&#xff0c;总是就是奇奇怪怪&#xff0c;悟空被玩坏了&#xff…

unicode编码存在转义字符,导致乱码问题的解决方案

【前言】   本篇是为了记录一次解码出现乱码的解决方案&#xff0c;篇幅较短&#xff0c;废话不多说&#xff0c;请食用 【问题】后端针对一个字符串进行unicode编码后的&#xff0c;前端解码后出现乱码问题 unicode编码后的字符串&#xff0c;直接交给前端解码&#xff0c;…

【搜索引擎】ElasticSearch 8.x版本

1 ElasticSearch 8.x概述 1.1 Elasticsearch 8.X 来了 1.2 Elasticsearch 新特性 1.3 Elasticsearch 课程升级 2 ElasticSearch 安装 & 使用 2.1 Java 17 安装 2.1.1 下载软件 2.1.2 软件升级 2.2 Elasticsearch 安装 & 使用 2.2.1 下载软件 2.2.2 安装软件 2.2.3…

Visio po解版的详细介绍

一、Visio简介 Visio是一款流程图、组织结构图、地平图、工程图等各类专业图表的制作软件。自问世以来&#xff0c;凭借其友好的用户界面、丰富的图形库和强大的编辑功能&#xff0c;已成为行业内使用最广泛的图形设计软件之一。无论是初学者还是专业人士&#xff0c;都能在Vi…