C++ list 的使用

news2024/11/18 13:51:20

目录

1. 构造函数

1.1 list ()

1.2 list (size_t n, const T& val = T())

1.3 list (InputIterator first, InputIterator last)

2. bool empty() const

3.  size_type size() const

4. T& front()

 4. T& back()

5. void push_front (const T& val)

6. void pop_front()

7. void push_back (const T& val)

8. void pop_back()

9. 迭代器

10. iterator insert (iterator pos, const T& val)

11.  void insert (iterator pos, size_t n, const T& val)

12. iterator erase (iterator pos)

13. void swap (list& x)

14. void resize (size_t n, const T& val = T())

15.  void clear()

16. 下面的这些函数都很好理解 

16.1 void remove (const T& val)

16.2 void unique()

16.2 void merge(list& x)

16.3 void sort()

16.4 void reverse()


list 的介绍,来源:list - C++ Reference (cplusplus.com)

1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。

2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。

3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高 效。

4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率 更好。

5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间 开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这 可能是一个重要的因素)

1. 构造函数

1.1 list ()

这里的 T 是模板参数,list 可以存储任意类型的数据嘛。

通过 list 的简介,我们知道 list 的底层其实是一个带头双向循环链表 (以下简称双链表),在定义 list 的时候,我们需要初始化一个哨兵位的头结点。哨兵位的头结点不存储有效数据。无参构造就是用来初始化哨兵位的头结点的!

1.2 list (size_t n, const T& val = T())

这个构造函数可以初始化一个长度为 n 的,值均为 val 的双链表。

#include<iostream>
#include<list>

using namespace std;

int main()
{
	list<int> lt(5, 8);
	//输出:8 8 8 8 8
	for (auto e : lt)
		cout << e << " ";
	cout << endl;
}

1.3 list (InputIterator first, InputIterator last)

这个构造函数可以用一段迭代器区间来初始化双链表。构造的区间:[first, last)。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	vector<int> arr;
	arr.push_back(1);
	arr.push_back(2);
	arr.push_back(3);
	arr.push_back(4);
	arr.push_back(5);

	list<int> lt(arr.begin(), arr.end());
	//输出:1 2 3 4 5
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

	return 0;
}

2. bool empty() const

判断一个链表是不是空链表!如果有有效数据,返回 true,反之返回 false。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt1;
	cout << lt1.empty() << endl; //输出:1

	list<int> lt2(5, 8);
	cout << lt2.empty() << endl; //输出:0

	return 0;
}

3.  size_type size() const

这个函数可以获取双链表的长度。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt2(5, 8);
	cout << lt2.size() << endl; //输出:5

	return 0;
}

4. T& front()

这个函数可以获取双链表的第一个有效元素。有 const 和非 const 两个版本,支持普通对象和 const 对象的调用。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	vector<int> arr;
	arr.push_back(1);
	arr.push_back(2);
	arr.push_back(3);
	arr.push_back(4);
	arr.push_back(5);

	list<int> lt(arr.begin(), arr.end());

	cout << lt.front() << endl; //输出:1

	return 0;
}

 4. T& back()

这个函数可以获取双链表的最后一个有效元素。有 const 和非 const 两个版本,支持普通对象和 const 对象的调用。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	vector<int> arr;
	arr.push_back(1);
	arr.push_back(2);
	arr.push_back(3);
	arr.push_back(4);
	arr.push_back(5);

	list<int> lt(arr.begin(), arr.end());

	cout << lt.back() << endl; //输出:5

	return 0;
}

5. void push_front (const T& val)

双链表头插元素。因为之前我们都用 C 语言实现过双链表,学习 list 的使用就非常简单啦!

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt;

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

	//输出:1 2 3 4
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

	return 0;
}

6. void pop_front()

双链表头删元素。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt;

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

	//输出:1 2 3 4
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

    lt.pop_front();
    
	//输出:2 3 4
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

	return 0;
}

7. void push_back (const T& val)

双链表尾插元素。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt;

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

	//输出:1 2 3 4
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

	return 0;
}

8. void pop_back()

双链表尾删元素。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt;

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

	//输出:1 2 3 4
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

    lt.pop_back();

	//输出:1 2 3
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

	return 0;
}

9. 迭代器

list 的迭代器就不是简单的原生指针了。因为他的物理空间并不连续,因此 list 的迭代器需要进行封装,使得迭代器解引用能够返回节点存储的数据,使得迭代器加加,指向下一个节点,等等。具体的操作到我们模拟实现 list 的时候再说。

下面的图是 list 迭代器 begin() 与 end() 迭代器对应的双链表节点。

10. iterator insert (iterator pos, const T& val)

这个函数可以在 list 的 pos 位置处,插入一个值为 val 的元素。返回值就是返回新插入的元素的位置对应的迭代器。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt;

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

	//在begin() 的位置插入 0 ,相当于头插
	lt.insert(lt.begin(), 0);

	//输出:0 1 2 3 4
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

	//在end() 的位置插入 5 ,相当于尾插
	auto it = lt.insert(lt.end(), 5);

	cout << *it << endl; //输出:5


	//输出:0 1 2 3 4 5
	for (auto e : lt)
		cout << e << " ";
	cout << endl;


	return 0;
}

11.  void insert (iterator pos, size_t n, const T& val)

这个函数可以在 pos 位置插入 n 个值为 val 的节点。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt;

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

	//在begin() 的 位置插入 3 个值为 0 的节点
	lt.insert(lt.begin(), 3, 0);

	//输出:0 0 0 1 2 3 4
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

	return 0;
}

12. iterator erase (iterator pos)

这个函数可以删除 pos 位置的双链表节点。不可以删除 end() 位置的节点,会报错的!VS2022 做了检查的。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt;

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

	//相当于头删
	lt.erase(lt.begin());

	//输出:2 3 4
	for (auto e : lt)
		cout << e << " ";
	cout << endl;

	return 0;
}

13. void swap (list<T>& x)

这个函数可以交换两个链表。我们实现 list 的时候,list 类中维护的是哨兵位的头结点的指针,交换两个链表的指针就能实现这样的效果。仅限于我们自己实现的 list 类哈!list 实现方式多种多样!

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);

	list<int> lt2;
	lt2.push_back(5);
	lt2.push_back(6);
	lt2.push_back(7);
	lt2.push_back(8);

	lt1.swap(lt2);

	//输出:5 6 7 8
	for (auto e : lt1)
		cout << e << " ";
	cout << endl;

	//输出:1 2 3 4
	for (auto e : lt2)
		cout << e << " ";
	cout << endl;


	return 0;
}

14. void resize (size_t n, const T& val = T())

stl 库的接口风格都很相似,list 的resize 和 vector,string 的 resize 简直一毛一样。当 n 小于双链表的长度,直接截断,当 n 大于双链表的长度,会用 val 区初始化新插入的节点。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt;

	lt.push_back(0);
	
	lt.resize(5, 1);

	//输出: 0 1 1 1 1
	for (auto e : lt)
		cout << e << " ";
	cout << endl;


	return 0;
}

15.  void clear()

清空链表,即释放所有链表节点。

#include<iostream>
#include<list>
#include<vector>
using namespace std;

int main()
{
	list<int> lt;

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

	lt.clear();

    //没有输出
	for (auto e : lt)
		cout << e << " ";
	cout << endl;


	return 0;
}

16. 下面的这些函数都很好理解 

16.1 void remove (const T& val)

移除链表中所有值为 val 的节点。

1 2 3 3 4 5 remove(3) :1 2 4 5。

16.2 void unique()

删除链表中重复的节点。

1 2 2 3 3 4 5 1 remove(3) :1 2 3 4 5 1。

这个函数只能对相邻的重复的数去重。因此多用于已经排好序的 list。

16.2 void merge(list<T>& x)

这个函数用于两个 list 的合并,前提是两个 list 都被排好序了!

例如:

list1:-1 2 3 5 8

list2:0 1 2 4 6 7

合并后的结果:-1 0 1 2 2 3 4 5 6 7 8。

16.3 void sort()

链表的排序。

16.4 void reverse()

链表的逆置。

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

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

相关文章

【Java系列】Java 基础

目录 基础1.JDK和JRE的区别2.Java为什么不直接实现lterator接口&#xff0c;而是实现lterable?3.简述什么是值传递和引用传递?4.概括的解释下Java线程的几种可用状态? 中级1.简述Java同步方法和同步代码块的区别 ?2.HashMap和Hashtable有什么区别?3.简述Java堆的结构? 什…

生命礼赞,带动世界第三次文化复兴——非洲回顾篇

一个民族的复兴需要强大的物质力量&#xff0c;也需要强大的精神力量。大型玉雕群组《生命礼赞》是对中华民族伟大生命的讴歌&#xff0c;是对百姓美好生活的赞美&#xff0c;完美诠释了中华民族的伟大图腾&#xff0c;它象征着中华民族在党的带领下艰苦奋斗&#xff0c;江山稳…

嵌入式软件工程师面试题——2025校招专题(二)

说明&#xff1a; 面试题来源于网络书籍&#xff0c;公司题目以及博主原创或修改&#xff08;题目大部分来源于各种公司&#xff09;&#xff1b;文中很多题目&#xff0c;或许大家直接编译器写完&#xff0c;1分钟就出结果了。但在这里博主希望每一个题目&#xff0c;大家都要…

美团动态ThreadPoolExecutor底层实现源码实战

开篇&#xff1a;介绍springboot连接nacos实现动态线程池&#xff0c;同时得安装nacos&#xff0c;同时代码将有两个模块&#xff0c;dtp-spring-boot-starter 与 user 模块&#xff0c;前者将是独立的动态线程池&#xff0c;可以引入自己的项目中&#xff0c;后者模块主要用于…

面试官:听说你很了解Java8特性,给我优化一下这段代码吧?

文章目录 前言我的想法面试官 前言 在之前的一次面试过程中&#xff0c;我被问到了一道代码优化题&#xff1a;对于下面的代码&#xff0c;你有什么优化的思路呢&#xff1f; boolean handleStrList(String strList){for (String s :strList){if(s.length()%20){return true;…

测试用例的设计方法(全):等价类划分方法

一.方法简介 1.定义 是把所有可能的输入数据,即程序的输入域划分成若干部分&#xff08;子集&#xff09;,然后从每一个子集中选取少数具有代表性的数据作为测试用例。该方法是一种重要的,常用的黑盒测试用例设计方法。 2.划分等价类&#xff1a; 等价类是指某个输入域的…

祝各位程序员节日快乐

今天是1024程序员节&#xff0c;小编祝各位Windows开机蓝屏&#xff0c;Linux开机Kernel Panic&#xff0c;macos开机五国&#xff0c;服务器iDRAC/ iLO/IPMI/KVM全部失联&#xff0c;路由器全爆炸&#xff0c;路由表内存全溢出&#xff0c;交换机全环路&#xff0c;防火墙全阻…

Spring Security加密和匹配

一. 密码加密简介 1. 散列加密概述 我们开发时进行密码加密&#xff0c;可用的加密手段有很多&#xff0c;比如对称加密、非对称加密、信息摘要等。在一般的项目里&#xff0c;常用的就是信息摘要算法&#xff0c;也可以被称为散列加密函数&#xff0c;或者称为散列算法、哈希…

清华训练营悟道篇之浅谈操作系统

文章目录 前言系统软件执行环境操作系统的功能操作系统组成 前言 操作系统是一个帮助用户和应用程序使用和管理计算机资源的软件&#xff0c;它控制着嵌入式设备、更通用的系统&#xff08;如智能手机、台式计算机和服务器&#xff09;以及巨型机等各种计算机系统 系统软件 …

【模型部署】c++部署yolov5使用openvino

1. 推理方式 CPU推理GPU推理&#xff08;要求电脑具备核显&#xff0c;即CPU中有嵌入显卡&#xff09; 2. openvino依赖项下载 https://github.com/openvinotoolkit/openvino/releases 直接解压&#xff08;随便放到哪个路径&#xff09; 环境配置 ********&#xff08;…

Text Classification via Large Language Models

Abstract 表达大模型在文本分类上做的不好。 原因&#xff1a; 1、处理复杂语境时缺少推理能力。(e.g… 类比、讽刺) 2、限制学习的上下文的token数。 提出了自己的策略&#xff1a; ** Clue And Reasoning Prompting (CARP).线索与推理提示** 1、能用prompt找到clue(语境线索…

Mysql进阶-存储引擎篇

MySQL体系结构 其他数据库相比&#xff0c;MySQL有点与众不同&#xff0c;它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎上&#xff0c;插件式的存储引擎架构&#xff0c;将查询处理和其他的系统任务以及数据的存储提取分离。 这种架构可以根据业务的需…

RK3568平台开发系列讲解(应用篇)串口应用编程之串口的使用步骤

🚀返回专栏总目录 文章目录 一、配置参数1.1、获取当前串口的配置参数1.2、修改和写入串口的配置参数二、模式2.1、输入模式2.2、输出模式2.3、控制模式2.4、本地模式2.5、特殊控制字符沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 串口设备是嵌入式开发中最常用的…

Facebook批量注册如何做?一文教会你

我们都知道单个代理地址注册多个社媒账号&#xff0c;基本第二天都会进入到一个风控状态&#xff0c;要申诉或者封号&#xff0c;批量注册需要用不同的地址进行注册&#xff0c;推荐使用动态代理代理,下面是需要准备到的环境和材料以及注册的全流程。 一、环境需求 1、接码平…

STM32定时器介绍

STM32F103系列单片机定时器主要有&#xff1a;系统定时器SysTick&#xff0c;2个高级定时器TIM1和TIM8&#xff0c;4个通用定时器TIM2/3/4/5&#xff0c;2个基本定时器TIM6和TIM7。下面先简单介绍一下&#xff1a; 基本定时器&#xff1a;基本定时器只能计时&#xff0c;不能产…

MIT-BIH-AF 数据集开发库

目录 1 介绍数据集2 本博客函数库代码地址以及介绍读取dat,qrc,atr文件&#xff0c;获得 ECG_rpeaks&#xff0c;ann_aux_note&#xff0c;ann_sample&#xff0c;ECG0寻找时间点函数----signal_time_sample寻找R_R峰信号以及其位置----find_R_R_peak寻找 nR 峰信号以及位置---…

springboot实现邮箱发送(激活码)功能

第一步&#xff1a;现在邮箱里面开启smtp服务 这里用163邮箱举例&#xff0c;配置一下授权密码&#xff0c;这个要提前记住 第二步&#xff1a;引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/P…

大语言模型(LLM)综述(三):大语言模型预训练的进展

A Survey of Large Language Models 前言4. PRE-TRAINING4.1数据收集4.1.1 数据源4.1.2 数据预处理4.1.3 预训练数据对LLM的影响 4.2 模型架构4.2.1 典型架构4.2.2 详细配置 前言 随着人工智能和机器学习领域的迅速发展&#xff0c;语言模型已经从简单的词袋模型&#xff08;B…

Banana Pi 开源社区发布BPI-M6开源硬件开发板,支持6.75TOPs算力

香蕉派BPI-M6 采用深蕾半导体Vs680芯片设计&#xff0c;板载4G LPDDR4和16G eMMC存储 香蕉派BPI-M6是香蕉派社区在2022年推出的新一代单板计算机&#xff0c;它采用深蕾半导体(Synaptics) VS680四核Cortex-A73 (2.1GHz)和一个Cortex-M3处理器&#xff0c;Imagination GE9920 G…

【C++面向对象】6. 指向类的指针

文章目录 【 1. 基本原理 】【 2. 实例 】 【 1. 基本原理 】 一个指向 C 类的指针与指向结构体的指针类似&#xff0c;访问指向类的指针的成员&#xff0c;需要使用 成员访问运算符 ->&#xff0c;就像访问指向结构的指针一样。 【 2. 实例 】 // 使用指向类的指针&…