c++编程14——STL(3)list

欢迎来到博主的专栏:c++编程
博主ID:代码小豪


文章目录

    • list
      • 成员类型
      • 构造、析构、与赋值
      • iterator
      • 元素访问
      • 修改元素
      • list的操作

list

list的数据结构是一个链表,准确的说应该是一个双向链表。这是一个双向链表的节点结构:
在这里插入图片描述
list的使用方式和vector大差不差,区别主要还是体现在某些操作的效率方面,如下:

listvector
插入与删除O(1)O(N)
遍历O(N)O(N)
访问O(N)O(1)

总体而言,如果线性表需要大量的删除和插入,那么使用list会更加高效,如果只是单纯的存储数据,vector比list更好用,而且vector的空间还比list小。

OK,话不多说,开始看看list都有什么操作。

成员类型

由于STL中的容器都是模板类,因此数据的类型和常见的内置类型肯定不同,了解成员类型可以更好的读懂list的各个函数原型。

list的模板如下:

template < class T, class Alloc = allocator<T> > 
class list;

函数原型常见类型有:

类型作用
value_type模板当中的第一个类型,即T
referencevalue_type类型的引用,即T&
pointervalue_type类型的指针,即T*
size_type代表无符号整型
difference_type代表有符号整型

希望大家能记住以上类型,因为接下来的list的函数原型经常会出现上述类型的参数。

构造、析构、与赋值

由于博主也不太会使allocator,因此介绍使用list的时候,参数一律使用alloc的缺省值。

default (1)	
explicit list (const allocator_type& alloc = allocator_type());
fill (2)	
explicit list (size_type n, const value_type& val = value_type(),const allocator_type& alloc = allocator_type());
range (3)	
template <class InputIterator>list (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type());
copy (4)	
list (const list& x);
  1. default构造:初始化时不传入任何参数,就能实例化出一个空链表。
	list<int> L1;//实例化一个容纳int变量的空链表list<float> L2;//实例化一个容纳int变量的空链表list<string>L3;//实例化一个容纳string对象的空链表
  1. 填充(fill)构造:构造一个n个值为val的对象的链表。
	list<int>L4(4, 2);//{2,2,2,2}list<float>L5(5, 3.14);//{ 3.14, 3.14, 3.14, 3.14, 3.14}list<string>L6(2, "hello world");//{"hello world","hello world"}
  1. c++11标准还支持使用initializer_list初始化。
list (initializer_list<value_type> il,const allocator_type& alloc = allocator_type());

这种初始化方式非常方便,非常好用。关于initializer_list的介绍可以去看看博主的c++杂谈系列。

使用方法大致如下:

	list<int>L7{ 1,2,3,4,5 };//{1,2,3,4,5}list<string>L8{ "haha","hehe","xixi"};//{"haha","hehe","xixi"}

是不是有点像给数组初始化时的用法,非常方便。

  1. 范围(range)构造

这种该构造是通过使用传入迭代器的方式,将迭代器内的元素传入list容器当中。

list<int>L7{ 1,2,3,4,5 };//{1,2,3,4,5}
list<string>L8{ "haha","hehe","xixi"};//{"haha","hehe","xixi"}
list<int>L9(L7.begin(), L7.end());//{1,2,3,4,5}
list<string>L9(L8.begin(), L8.end());//{"haha","hehe","xixi"}

当然了,这里的迭代器可以是与list<T>相同类型的迭代器。比如这种用法也是合理的。

	string str("hello world");list<char>L11(str.begin(), str.end());//{'h','e','l','l','o',' ','w','o','r','d'}

当然了,上面的说法是存在严重错误的,list<char>和string::iterator的类型当然是不一样的,只是读起来顺口而已。实际上我想表达的是:list<char>容器的元素类型是char,而string::iterator指向的元素也是char类型。因此可以这样构造。

  1. 拷贝(copy)构造,构造一个与x一致的容器。
list<int>L12{ 1,2,3,4,5 };
list<int>L13(L12);//L13与L12一致

赋值运算符重载和拷贝构造的使用方法完全一致

 list& operator= (const list& x);
	list<int> list1{ 1,2,3,4 };list<int>list2;list2 = list1;//list2与list1一致

至于析构函数则没什么需要大家操作的地方了,当list超出作用域时,会自动调用list的析构函数。而且list析构函数还不需要传入参数

iterator

list的迭代器也是分为四种,分别是

(1)正向迭代器
(2)正向定值迭代器
(3)反向迭代器
(4)反向定值迭代器

STL的迭代器用法基本差不多,这里博主就不多演示怎么使用了,大家可以参考vector和string的迭代器用法。

list迭代器的不同之处在于,vector和string的迭代器都是随机迭代器(random access iterator),而list是双向迭代器(bidirectional iterator),随机迭代器可以支持++,–,以及加减算术的操作,而双向迭代器只能使用++或者–操作。

list<int>list1{ 1,2,3,4,5,6 };
list<int>::iterator it = list1.begin();
it + 1;//error,双向迭代器不支持算术加减
it++;//ok,双向迭代器支持自加自减

这意味着我们可以通过一下两种方式遍历list1.

list<int>list1{ 1,2,3,4,5,6 };
list<int>::iterator it = list1.begin();while (it != list1.end())
{cout << *it;it++;
}for (auto& e : list1)
{cout << e;
}

元素访问

list不支持使用下标访问符([])访问容器内的元素了。实际上,list一共就提供了两个函数,一个front,一个back。用来访问第一个或者最后一个元素。

reference front();
const_reference front() const;
reference back();
const_reference back() const;
list1.front() = 7;//第一个元素1修改成7
list1.back() = 1;//最后一个元素修改成1

修改元素

大家看看list关于修改元素的函数结口,是不是感觉很熟悉
在这里插入图片描述
可以发现list和vector关于修改元素的函数接口简直是如出一辙、

这是因为Victor,string,list都是线性表的结构,因此对元素的修改操作的效果都是一致的,区别只在于涉及的算法不同,这里我打算将算法放在list的模拟实现当中讲解,或者也可以去看博主的C语言数据结构关于双链表的博客。

list的操作

list和vector虽然在逻辑上是一致的,但是在内存结构上却完全不同了,因此list可执行的操作和vector是不同的。

在这里插入图片描述

  1. remove——移除所有值为val的节点
void remove (const value_type& val);
  1. unique——去掉链表中所有的重复元素。(链表需有序)
	list<int>list2{ 5,6,3,2,1,1,5 };list2.sort();//排序list2.unique();//list2={1,2,3,5,6}
  1. sort——排序
(1)	void sort();
(2)	
template <class Compare>void sort (Compare comp);

默认情况下会将链表排成升序,如果想要将链表排成降序,就需要用到仿函数(像函数一样使用的类)。

	list<int>list2{ 5,6,3,2,1,1,5 };list2.sort();//升序for (auto& e : list2){cout << e << ' ';}cout << endl;list2.sort(greater<int>());//降序,这个greater是一个仿函数模板,博主不做说明for (auto& e : list2){cout << e << ' ';}
  1. reverse——逆置链表
void reverse();

reverse可以让链表中的所有元素的顺序颠倒过来。

  1. merge——合并链表
(1)	void merge (list& x);
(2)	
template <class Compare>void merge (list& x, Compare comp);

(1)
list容器将与x合并,merge会将x的所有成员都转移到list容器当中。(x会变成一个空链表,而list则会变大)。合并的两个链表必须拥有相同的顺序(升序,不能是逆序)。合并后的链表也会呈升序

list<int>list4{6,5,5,3,5};list<int>list5{ 7,9,3,4,2 };list4.sort();//list4排成升序list5.sort();//list5排成升序list4.merge(list5);//将list5和list4合并for (auto& e : list4){cout << e << ' ';//{2,3,3,4,5,5,5,6,7,9}}

(2)
如果我们想要让合并后的链表是逆序的,那就将待合并的链表排成逆序,再传入仿函数comp,可以让合并后的链表呈逆序。

list<int>list4{6,5,5,3,5};list<int>list5{ 7,9,3,4,2 };list4.sort(greater<int>());//排成逆序list5.sort(greater<int>());//排成逆序list4.merge(list5,greater<int>());//合并成逆序for (auto& e : list4){cout << e << ' ';//{9,7,6,5,5,5,4,3,3,2}}
  1. splice——粘接(感觉像是剪切)
entire list (1)	
void splice (iterator position, list& x);
single element (2)	
void splice (iterator position, list& x, iterator i);
element range (3)	
void splice (iterator position, list& x, iterator first, iterator last);

splice重载了三个版本,每个版本都有不一样的效果

第一版:全部粘接,将x的全部元素粘接到list容器的迭代器指向的位置。x会变成一个空链表。

	list<int>list1{ 1,2,3,4 };list<int>list2{ 10,20,30,40 };list1.splice(list1.begin(), list2);for (auto& e : list1){cout << e << ' '; //{10, 20, 30, 40, 1, 2, 3, 4};}

第二版,单元素粘接,将x中的迭代器i指向的元素粘接到容器position指向的位置。

	list<int>list1{ 1,2,3,4 };list<int>list2{ 10,20,30,40 };list1.splice(list1.begin(), list2,list2.begin());for (auto& e : list1){cout << e << ' '; //{10,1, 2, 3, 4};}

第三版,迭代区间粘接。将x中[first,last)区间内的所有元素都粘接到list容器的position位置上。

	list<int>list1{ 1,2,3,4 };list<int>list2{ 10,20,30,40 };list1.splice(++list1.begin(), list2,++list2.begin(),--list2.end());for (auto& e : list1){cout << e << ' '; //{1,20,30 2, 3, 4};}

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

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

相关文章

Vue学习笔记3——事件处理

事件处理 1、事件处理器&#xff08;1&#xff09;内联事件处理器&#xff08;2&#xff09;方法事件处理器 2、事件参数3、事件修饰符 1、事件处理器 我们可以使用v-on 指令(简写为)来监听DOM事件&#xff0c;并在事件触发时执行对应的JavaScript。 用法: v-on:click"me…

JVM学习-执行引擎

执行引擎 执行引擎是Java虚拟机核心组成部分之一虚拟机是一个相对于物理机的概念&#xff0c;这两种机器都有代码执行能力&#xff0c;其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的&#xff0c;而虚拟机的执行引擎是由软件自行实现的&#xf…

【算法】递归、搜索与回溯——简介

简介&#xff1a;递归、搜索与回溯&#xff0c;本节博客主要是简单记录一下关于“递归、搜索与回溯”的相关简单概念&#xff0c;为后续算法做铺垫。 目录 1.递归1.1递归概念2.2递归意义2.3学习递归2.4写递归代码步骤 2.搜索3.回溯与剪枝 递归、搜索、回溯的关系&#xff1a; …

ICML2024 定义新隐私保护升级:DP-BITFIT新型微调技术让AI模型学习更安全

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; 引言&#xff1a;差分隐私在大模型微调中的重要性和挑战 在当今的深度学习领域&#xff0c;大型预训练模型的微调已成为提高各种任务性能的关键技术。然而&am…

推特热帖:大语言模型自荐能够替代的20种人类工作!快来看你是否需要转行!

最近推特上有一个例子引起了广泛的讨论&#xff0c;事情的起因是这样的&#xff1a;网友让 GPT-4o 预测一下自己未来将会替代人类哪些工作&#xff1f; 这听起来很有趣&#xff01;GPT-4o会给出什么样的预测呢&#xff1f; 3.5研究测试&#xff1a;hujiaoai.cn 4研究测试&…

02-Linux【基础篇】

一、Linux的目录结构 1.基本介绍 Linux的文件系统采用层级式的树状目录结构&#xff0c;在此结构中的最上层是根目录"/"&#xff0c;然后在此目录下再创建其他的目录 深刻理解Linux树状文件目录是非常重要的 记住一句经典的话&#xff1a;在Linux世界里&#xff…

如何在 DigitalOcean Droplet 云主机上创建 Ubuntu 服务器

在本文中&#xff0c;你将通过 DigitalOcean 的管理面板创建一个 Ubuntu 服务器&#xff0c;并将其配置为使用你的 SSH 密钥。设置好服务器后&#xff0c;你可以在其上部署应用程序和网站。 本教程是DigitalOcean云课程简介的一部分&#xff0c;它指导用户完成将应用程序安全地…

win10右键没有默认打开方式的选项的处理方法

问题描述 搞了几个PDF书籍学习一下&#xff0c;不过我不想用默认的WPS打开&#xff0c;因为WPS太恶心人了&#xff0c;占用资源又高。我下载了个Sumatra PDF&#xff0c;这时候我像更改pdf文件默认的打开程序&#xff0c;发现右击没有这个选项。 问题解决 右击文件–属性–…

汽车以太网发展现状及挑战

一、汽车以太网技术联盟 目前推动汽车以太网技术应用与发展的组织包括&#xff1a;OPEN Alliance&#xff08;One-Pair Ether-Net Alliance SIG&#xff09;联盟&#xff0c;主要致力于汽车以太网推广与使用&#xff0c;该联盟通过推进 BroadR- Reach 单对非屏蔽双绞线以太网传…

设计新境界:大数据赋能UI的创新美学

设计新境界&#xff1a;大数据赋能UI的创新美学 引言 随着大数据技术的蓬勃发展&#xff0c;它已成为推动UI设计创新的重要力量。大数据不仅为界面设计提供了丰富的数据资源&#xff0c;还赋予了设计师以全新的视角和工具来探索美学的新境界。本文将探讨大数据如何赋能UI设计…

面试八股之JVM篇3.5——垃圾回收——G1垃圾回收器

&#x1f308;hello&#xff0c;你好鸭&#xff0c;我是Ethan&#xff0c;一名不断学习的码农&#xff0c;很高兴你能来阅读。 ✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。 &#x1f3c3;人生之义&#xff0c;在于追求&#xff0c;不在成败&#xff0c;勤通…

常见 JVM 面试题补充

原文地址 : 26 福利&#xff1a;常见 JVM 面试题补充 (lianglianglee.com) CMS 是老年代垃圾回收器&#xff1f; 初步印象是&#xff0c;但实际上不是。根据 CMS 的各个收集过程&#xff0c;它其实是一个涉及年轻代和老年代的综合性垃圾回收器。在很多文章和书籍的划分中&…

SpringCloud Alibaba的相关组件的简介及其使用

Spring Cloud Alibaba是阿里巴巴为开发者提供的一套微服务解决方案&#xff0c;它基于Spring Cloud项目&#xff0c;提供了一系列功能强大的组件&#xff0c;包括服务注册与发现、配置中心、熔断与限流、消息队列等。 本文将对Spring Cloud Alibaba的相关组件进行简介&#xff…

ROCm上运行预训练BERT

14.10. 预训练BERT — 动手学深度学习 2.0.0 documentation (d2l.ai) 下载数据集 在d2l-zh/pytorch/data目录解压&#xff1a; ~/d2l-zh/pytorch/data$ unzip wikitext-2-v1.zip Archive: wikitext-2-v1.zipcreating: wikitext-2/inflating: wikitext-2/wiki.test.tokens …

数据库--数据库基础(一)

目录 第一章 绪论 一.数据库的基本概念 1. 数据库的4个基本概念 2、数据库系统的特点 二.数据库和文件 三.数据模型 1.概念模型 2.逻辑模型(物理模型) 2.1关系模型 四.数据库系统的三级模式结构&#xff1a; 五数据库的二级映像功能与数据独立性 第二章 关系数据库…

2024电工杯数学建模B题高质量成品论文,包括代码数据

2024电工杯数学建模B题高质量成品论文&#xff0c;包括代码数据 完整内容见文末名片 摘要 大学时期是学生们知识学习和身体成长的重要阶段&#xff0c;良好的饮食习惯对于促进生长发育和保证身体健康具有重要意义。针对当前大学生中存在的饮食结构不合理及不良饮食习惯的问题…

为了性能,放弃tft_eSPI,选择arduino_gfx吧

本来对于tft_espi和arduino_gfx没啥特别的感觉&#xff0c;都是tft屏幕驱动,arduino_gfx的好处就是除了支持tft外还支持一些oled屏幕。 谁知道在探寻我那个在单片机项目上显示中文方案 https://github.com/StarCompute/tftziku 时候&#xff0c;寻求极致性能测了一些东西。 t…

算法之背包问题

可分的背包问题是可以用贪心法来解决&#xff0c;而0-1背包问题通常使用动态规划方法来解决。 可分背包问题&#xff1a; 在可分背包问题中&#xff0c;物品可以被分割&#xff0c;您可以取走物品的一部分以适应背包的容量。这里的关键是物品的价值密度&#xff0c;即单…

VTK9.2.0+QT5.14.0绘制三维显示背景

背景 上一篇绘制点云的博文中&#xff0c;使用的vtkCameraOrientationWidget来绘制的坐标轴&#xff0c;最近又学习到两种新的坐标轴绘制形式。 vtkOrientationMarkerWidget vtkAxesActor 单独使用vtkAxesActor能够绘制出坐标轴&#xff0c;但是会随着鼠标操作旋转和平移时…

微服务中使用Maven BOM来管理你的版本依赖

摘要: 原创出处 sf.gg/a/1190000021198564 「飘渺Jam」欢迎转载&#xff0c;保留摘要&#xff0c;谢谢&#xff01; 为什么要使用BOM? 如何定义BOM? 项目使用方法? BOM&#xff08;Bill of Materials&#xff09;是由Maven提供的功能,它通过定义一整套相互兼容的jar包版…