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

news2025/3/17 18:14:58

欢迎来到博主的专栏: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.coloradmin.cn/o/1694682.html

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

相关文章

Java轻松转换Markdown文件到Word和PDF文档

Markdown 凭借其简洁易用的特性&#xff0c;成为创建和编辑纯文本文档的常用选择。但某些时候我们需要更加精致的展示效果&#xff0c;例如在专业分享文档或打印成离线使用的纸质版时&#xff0c;就需要将Markdown文件以其他固定的文档格式呈现。通过将 Markdown 转换为 Word 和…

PostgreSQL用户与角色简述

简述 PostgreSQL通过角色&#xff08;role&#xff09;来控制数据库的访问权限。角色可以拥有数据库对象&#xff08;比如表、函数等&#xff09;&#xff0c;并允许将这些对象的权限授予其他角色&#xff0c;从而实现对象访问的控制。角色&#xff08;role&#xff09;包含了…

llama3-8b-instruct-262k微调过程的问题笔记(场景为llama论文审稿)

目录 一、环境配置 1.1、模型 1.2、微调环境 1.3、微调数据 二、发现的问题 2.1、过拟合问题 2.2、Qlora zero3 保存模型时OOM问题(已解决) 一、环境配置 1.1、模型 llama3-8b-instruct-262k &#xff08;英文&#xff09; 1.2、微调环境 Package Version ------------------…

军队仓库管理系统|DW-S301系统特点

部队仓库管理系统DW-S301系统通过数据采集、互联网和物联网技术&#xff0c;实现数字化智能管控&#xff0c;以提高军用物资的仓储准确率和流转率&#xff0c;缩短周转时间&#xff0c;降低库存成本&#xff0c;也有助于消除生产过程中的不确定性。 系统功能&#xff1a;通过部…

ComfyUI完全入门:图生图局部重绘

大家好&#xff0c;我是每天分享AI应用的萤火君&#xff01; 这篇文章的主题和美女有关&#xff0c;不过并不是教大家生产美女视频&#xff0c;而是讲解 ComfyUI 的图生图局部重绘&#xff0c;其中将会以美女图片为例&#xff0c;来展示局部重绘的强大威力。 先看看效果&…

STM32学习和实践笔记(30):窗口看门狗(WWDG)实验

1.WWDG介绍 1.1 WWDG简介 上一章我们已经介绍了IWDG&#xff0c;知道它的工作原理就是一个12位递减计数器不断递减计数&#xff0c;当减到0之前还未进行喂狗的话&#xff0c;产生一个MCU复位。 窗口看门狗WWDG其实和独立看门狗类似&#xff0c;它是一个7位递减计数器不断的往…

网络模型-策略路由配置

在实际网络应用中&#xff0c;策略路由也是一种重要的技术手段。尽管在考试并不注重策略路由&#xff0c;但是实际上应用较多建议考生除了掌握基本的静态路由协议IP route-static&#xff0c;动态路由协议RIP、还要掌握如何配置策略路由。策略路由的基本原理:根据ACL定义的不同…

基于高通公司AI Hub Models的On-Device AI学习:Introduction to On-Device AI

Introduction to On-Device AI 本文是学习 https://www.deeplearning.ai/short-courses/introduction-to-on-device-ai/这门课的学习笔记。 What you’ll learn in this course As AI moves beyond the cloud, on-device inference is rapidly expanding to smartphones, IoT…

前端-移动端布局

如何在PC端模拟移动端设备 可以在浏览器里打开检查 点击一下移动端按钮 然后选择一下对应的手机型号可以切换到对应的手机端 响应式布局实现方法 Viewport Flex 弹性盒子 Flex容器属性 flex-direction flex-wrap justify-content align-items align-content 进阶学习建议 Vu…

Point-Nerf 理论笔记和理解

文章目录 什么是point nerf 和Nerf 有什么区别Point Nerf 核心结构有哪些&#xff1f;什么是point-based radiance field? 点云位置以及置信度是怎么来Point pruning 和 Point Growing 什么是point nerf 和Nerf 有什么区别 基本的nerf 是通过过拟合MLP来完成任意视角场景的重…

Express 的 req 和 res 对象

新建 learn-express文件夹&#xff0c;执行命令行 npm init -y npm install express 新建 index.js const express require(express); const app express();app.get(/, (req, res, next) > {res.json(return get) })app.post(/, (req, res, next) > {res.json(retur…

在 Ubuntu 22 上深入了解和搭建 Minikube

在 Ubuntu 22 上深入了解和搭建 Minikube Minikube 是一个开源工具&#xff0c;使开发者能够在本地计算机上运行单节点的 Kubernetes 集群&#xff0c;非常适合于开发、测试和学习 Kubernetes 的基础知识。在这篇文章中&#xff0c;我们将深入了解 Minikube 的工作原理&#x…

【vue echart】完成一个简单echart图表+自适应

实现效果&#xff1a; html&#xff1a; <divref"echartOne"id"echartOne"style"width: 100%; height: 100%" ></div> js: getEchartOne() {let chart this.$echarts.init(this.$refs.echartOne);chart.setOption({title: {text:…

【全部更新完毕】2024电工杯A题数学建模详细思路代码文章分享

A 题&#xff1a;园区微电网风光储协调优化配置 摘要 在全球范围内&#xff0c;气候变化和环境污染问题日益严重&#xff0c;减少碳排放和实现可持续发展成为各国的共同目标。新能源&#xff0c;尤其是风能和光伏发电&#xff0c;因其清洁、可再生的特性&#xff0c;正在全球范…

Python vscode debug: Error while enumerating installed packages.解决

记录一个vscode python debug时出现的错误&#xff1a; 具体错误如下&#xff1a; E00000.030: Error while enumerating installed packages. Traceback (most recent call last): File “/root/.vscode-server/extensions/ms-python.debugpy-2024.0.0-linux-x64/bundled/lib…

【C++11】lambda匿名函数和包装器

目录 一&#xff0c;lambda匿名函数 1-1&#xff0c;lambda的引入 1-2&#xff0c;lambda表达式书写格式 1-3&#xff0c;lambda函数的名称 1-4&#xff0c;lambda捕获列表的使用 1-5&#xff0c;函数对象与lambda表达式 二&#xff0c;包装器 2-1&#xff0c;function…

逻辑这回事(一)----编码规范

说明&#xff1a;优先级是M的规则为强制项&#xff0c;优先级为R的规则为建议项。 通用约束 应有全局观念。 优先级&#xff1a;M 说明&#xff1a;你所编写的代码在成为最终硅片上的一部分之前&#xff0c;需要经过许多设计者利用各种各样的工具进行各种各样的处理。有时&…

【编译原理】LL(1)预测分析法

一、实验目的 LL(1)的含义&#xff1a;第一个L表明自顶向下分析是从左向右扫描输入串&#xff0c;第2个L表明分析过程中将使用最左推导&#xff0c;1表明只需向右看一个符号便可决定如何推导&#xff0c;即选择哪个产生式进行推导。 LL(1) 预测分析方法是确定的自顶向下的语…

[保姆式教程]使用目标检测模型YOLO V8 OBB进行旋转目标的检测:训练自己的数据集(基于卫星和无人机的农业大棚数据集)

最近需要做基于卫星和无人机的农业大棚的旋转目标检测&#xff0c;基于YOLO V8 OBB的原因是因为尝试的第二个模型就是YOLO V8&#xff0c;后面会基于YOLO V9模型做农业大棚的旋转目标检测。YOLO V9目前还不能进行旋转目标的检测&#xff0c;需要修改代码 PS:欢迎大家分享农业大…

Capture One Studio for Mac:打造完美影像的利器

对于摄影师而言&#xff0c;每一次按下快门都是一次对完美影像的追求。而Capture One Studio for Mac正是这样一款能够帮助你实现这一追求的利器。 Capture One Studio for Mac v16.4.2.1中文直装版下载 首先&#xff0c;Capture One Studio for Mac拥有出色的图像处理能力。它…