C++中的List容器用法详解

文章目录

  • C++中的List容器用法详解
  • List 的特点
  • List 的重要接口用法介绍
    • 1.创建和初始化List
      • list
    • 2.插入元素
      • push_back
      • push_fornt
      • insert
    • 删除元素
      • pop_back
      • pop_font
      • clear
      • erase
    • 遍历List
      • 迭代器遍历
      • 范围for遍历
    • 排序List
      • sort
    • 反转List
      • reverse
    • 转移List
      • splice
    • 去重
      • unique
    • 合并
      • merge
    • 总结

C++中的List容器用法详解

在C++标准模板库(STL)中,list 是一种高效的、双向的、动态的容器,它允许在任何位置快速插入和删除元素。list 容器在内部通过节点来存储数据,每个节点都包含数据部分和指向前后节点的指针。这种设计使得 list 在进行插入和删除操作时具有较高的效率,因为只需要修改指针的指向,而不需要移动元素。

List 的特点

std::list 是 C++ 标准模板库(STL)中的一个容器,它具有以下特点:

  1. 双向链表list 是一个双向链表,每个元素都包含一个数据部分和两个指针,分别指向下一个元素和上一个元素。这种结构使得在链表的任何位置插入或删除元素都非常高效。

  2. 动态大小list 容器的大小是动态的,可以随着元素的添加和删除而自动调整。它不需要预先分配固定大小的内存。

  3. 不连续内存分配:与数组或 std::vector 不同,list 的元素不存储在连续的内存块中。每个元素都是独立分配的,这使得 list 在处理大量数据时能够提供更好的内存利用率和性能。

  4. 高效插入和删除:由于其链表结构,list 在任何位置插入或删除元素的时间复杂度都是常数时间(O(1)),这比 std::vector 在中间位置插入或删除元素的线性时间(O(n))要快得多。

  5. 不支持随机访问:由于 list 是一个链表,它不支持像数组或 std::vector 那样的随机访问。访问 list 中的元素需要从头开始遍历,因此其时间复杂度为线性时间(O(n))。

  6. 迭代器支持list 提供了双向迭代器,这意味着可以从两个方向遍历 list,但不支持随机访问迭代器。

  7. 内存管理list 的内存管理是自动的,当元素被插入时,list 会自动分配内存;当元素被删除时,list 会自动释放内存。

  8. 不支持直接访问:不能通过索引直接访问 list 中的元素,必须使用迭代器。

  9. 不支持 at() 方法list 不提供 at() 方法来访问元素,因为这需要随机访问能力,而 list 不支持随机访问。

  10. 不支持 [] 运算符:与 at() 方法类似,list 也不支持 [] 运算符来访问元素,原因同上。

  11. 不支持 resize() 方法list 不提供 resize() 方法来改变容器的大小,因为 list 的大小是动态的,且不连续分配内存。

  12. 不支持 reserve() 方法list 不提供 reserve() 方法来预分配内存,因为 list 的内存分配策略是自动的。

list 的这些特点使得它在需要频繁插入和删除操作的场景中非常有用,但在需要快速随机访问的场景中则不如 std::vector 或数组高效。

List 的重要接口用法介绍

1.创建和初始化List

在C++中,可以使用多种方式创建和初始化 list 容器:
在这里插入图片描述

list

  • (1)
    空容器构造函数(默认构造函数)构造一个没有元素的空容器。
  • (2)
    构造一个包含n个元素的容器。每个元素都初始化为val。
  • (3)
    构造一个包含与[first,last)范围相同数量元素的容器,每个元素以相同的顺序从该范围内的相应元素构造。
  • (4)
    构造了一个包含 x 中每个元素副本的容器,元素顺序与 x 中的顺序相同。
#include <iostream>
#include <list>

int main() {
    // (1)创建一个空的list
    std::list<int> mylist;
	
	// (2)创建一个有n个空间每个空间都存val的list
	std::list<int> mylist2(5,10);
	// 使用初始化列表创建list
    std::list<int> mylist3 = {1, 2, 3, 4, 5};

	// (3)创建一个包含一些整数的数组
	int arr[] = { 10, 20, 30, 40, 50 };
	// 创建一个指向数组的迭代器范围
	int* first = arr;
	int* last = arr + sizeof(arr) / sizeof(arr[0]);
	// 使用迭代器范围创建一个list
	std::list<int> mylist3(first, last);
	
    // (4)使用另一个list初始化
    std::list<int> mylist4(mylist2);

    return 0;
}

2.插入元素

在这里插入图片描述

push_back

  • list 容器的末尾添加了一个新元素,位于其当前的最后一个元素之后。val 的内容被复制(或移动)到新元素中,就是尾插个节点
	std::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);

在这里插入图片描述

push_fornt

  • 就是头插个节点
    std::list<int> lt;
	lt.push_front(1);
	lt.push_front(2);
	lt.push_front(3);

在这里插入图片描述

insert

  • (1)
    就是指定位置的元素之前进行插入新元素
  • (2)
    选择插入位置进行单个或者多个元素的插入
  • (3)
    进行[first,last)范围的插入
	std::list<int> mylist1 = { 1, 2, 3, 4, 5 }; // 初始化列表
	std::list<int>::iterator it1 = mylist1.begin(); // 获取迭代器
	// 在迭代器 it 指向的位置之前插入值为 10 的元素
	it1 = mylist1.insert(it1, 10);//(1)

	std::list<int> mylist2 = { 1, 2, 3, 4, 5 }; // 初始化列表
	std::list<int>::iterator it2 = mylist2.begin(); // 获取迭代器
	// 在迭代器 it 指向的位置之前插入 2 个值为 10 的元素
	mylist2.insert(it2, 2, 10);//(2)

	std::list<int> mylist3 = { 1, 2, 3, 4, 5 }; // 初始化列表
	std::vector<int> myvector = { 6, 7, 8 }; // 初始化向量
	std::list<int>::iterator it3 = mylist3.begin(); // 获取迭代器
	// 在迭代器 it 指向的位置之前插入 myvector 中的元素
	mylist3.insert(it3, myvector.begin(), myvector.end());//(3)

删除元素

在这里插入图片描述

pop_back

  • 删除末尾元素

在这里插入图片描述


pop_font

  • 删除开头元素

在这里插入图片描述


clear

  • 清空整个list
mylist.pop_back(); 
mylist.pop_front(); 
mylist.clear();  

在这里插入图片描述

erase

  • (1)
    接受一个迭代器 position ,它指向你想要删除的单个元素。这个元素会被从容器中移除,容器的大小会减一。返回值是一个迭代器,指向被删除元素之后的元素,如果 position 是容器中的最后一个元素,则返回 end() 。
  • (2)
    接受一对迭代器 first 和 last ,它们定义了一个范围。这个范围内的所有元素都会被从容器中移除。返回值是一个迭代器,指向被删除范围之后的第一个元素,如果 last 是容器中的最后一个元素,则返回 end() 。
	std::list<int> mylist1 = { 1, 2, 3, 4, 5 };
	std::list<int>::iterator it = mylist1.begin();
	// 删除迭代器 it 指向的元素
	it = mylist1.erase(it);//(1)

	std::list<int> mylist2 = { 1, 2, 3, 4, 5 };
	std::list<int>::iterator it1 = mylist2.begin();
	std::list<int>::iterator it2 = mylist2.begin();
	std::advance(it2, 3); // 移动 it2 到第四个元素
	// 删除从 it1 到 it2 范围内的元素
	it1 = mylist2.erase(it1, it2);//(2)

遍历List

迭代器遍历

for (std::list<int>::iterator it = mylist.begin(); it != mylist.end(); ++it) {
    std::cout << *it << " ";
}

范围for遍历

	list<int> lt = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

排序List

在这里插入图片描述

sort

  • (1)
    升序排序
  • (2)
    降序排序(得需要仿函数)
	list<int> lt = { 1, 3, 2, 5, 4, 9, 8, 7, 6 };
	//排序升序
	lt.sort();
	lt.sort(greater<int>());//降序,greater<int>()//仿函数

反转List

在这里插入图片描述

reverse

  • 反转或者说逆置list
mylist.reverse(); // 反转list中的元素顺序

转移List

在这里插入图片描述

splice

  • 注意:
    转移之后lt3直接转移走,lt3里面什么都没有了就
  • 吐槽:
    虽说起名字叫splice但是还是感觉transfers更贴近一点
	//splice (transfers) 转移
	list<int> lt2;
	lt2.push_back(1);
	lt2.push_back(3);
	lt2.push_back(5);
	lt2.push_back(4);
	lt2.push_back(2);

	for (auto e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;

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

	for (auto e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;

	list<int> lt3;
	lt3.push_back(1);
	lt3.push_back(2);
	lt3.push_back(3);

	for (auto e : lt3)
	{
		cout << e << " ";
	}
	cout << endl;

	lt2.splice(lt2.end(), lt3);
	for (auto e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;

	//转移之后lt3直接转移走,lt3里面什么都没有了就
	for (auto e : lt3)
	{
		cout << e << " ";
	}
	cout << endl;

去重

在这里插入图片描述

unique

  • (1)
    去除list中重复的元素
  • (2)
    接受一个二元谓词( BinaryPredicate ),用于定义两个元素是否相等。默认情况下,如果两个元素相等(即它们的值相同),则认为它们是重复的。unique 函数会遍历列表,并移除所有相邻的重复元素,只保留第一个元素。新列表的大小会减小,但元素的顺序不会改变。
  • 注意:
    在用去重函数之前一定要进行排序
	//去重 unique(得先排序)
	lt.unique();//(1)

	//(2)
	#include <iostream>
	#include <list>
	#include <algorithm> // for std::equal_to

	bool is_equal(const int& a, const int& b) {
    return a == b;
	}

	int main() {
    std::list<int> mylist = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};

    // 使用自定义的二元谓词来定义相等性
    mylist.unique(is_equal);

    // 打印列表以查看结果
    for (int& elem : mylist) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

合并

在这里插入图片描述

merge

  • 用于合并两个有序序列。 std::merge 函数定义在 头文件中,它接受两个有序序列的迭代器范围,并将它们合并成一个有序序列。
#include <iostream>
#include <list>
#include <algorithm> // for std::merge
#include <iterator>   // for std::ostream_iterator

int main() {
    std::list<int> list1 = {1, 3, 5, 7};
    std::list<int> list2 = {2, 4, 6, 8};
    std::list<int> merged_list;

     // 使用 std::merge 合并两个有序列表
     std::merge(list1.begin(), list1.end(),
                list2.begin(), list2.end(),
                std::back_inserter(merged_list));

     // 打印合并后的列表
     std::copy(merged_list.begin(), merged_list.end(),
               std::ostream_iterator<int>(std::cout, " "));
     std::cout << std::endl;

     return 0;
}

总结

list 是C++标准模板库中非常强大的容器之一,它提供了快速的插入和删除操作,并且支持双向迭代。通过本文的介绍,你应该对 list 的基本用法有了一个大致的了解。在实际编程中,根据具体需求选择合适的容器是非常重要的,list 适合于那些需要频繁插入和删除元素的场景。

希望这篇文章能够帮助你更好地理解和使用C++中的 list 容器。如果你有任何问题或需要进一步的解释,请随时在评论区留言。

小卷王们,用你们勤劳的小手给我点点赞,蟹蟹

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

语言模型进化史(上)

由于篇幅原因&#xff0c;本文分为上下两篇&#xff0c;上篇主要讲解语言模型从朴素语言模型到基于神经网络的语言模型&#xff0c;下篇主要讲解现代大语言模型以及基于指令微调的LLM。文章来源是&#xff1a;https://www.numind.ai/blog/what-are-large-language-models 一、语…

【国信华源2024年首场春季校园招聘面试会举办】

阳春三月&#xff0c;春意盎然&#xff0c;北京国信华源科技有限公司2024年校园招聘活动如期展开。4月2日&#xff0c;成功举办了“国信华源2024年首场春季校园招聘面试会”。 国信华源公司人力资源部热情接待了前来参加面试的同学们&#xff0c;并亲自陪同他们深入探访了企业。…

《pytorch深度学习实战》学习笔记第1章

第1章 深度学习和pytorch库简介 1.1 深度学习革命 机器学习依赖特征工程。而深度学习是从原始数据中自动找出这样的特征。 1.2 pytorhc深度学习 pytorch是一个python程序库。pytorch为深度学习提供了入门指南。pytorch的核心数据结构——张量&#xff0c;为一个多维数组&…

人工智能上手 Pytorch

人工智能上手 Pytorch 1、人工智能框架历史走向 2015年&#xff0c; caffe&#xff0c;优势配置简单&#xff0c;缺点安装麻烦&#xff0c;且不更新维护 2016年&#xff0c;tensorflow 1.x&#xff0c;定义太严格&#xff0c;很复杂。开发成本高。简单的任务&#xff0c;也很…

Ardupilot无人船(车)各控制模式简介

本文介绍了Ardupilot固件无人船(车)的各种模式。 用户通常使用遥控器开关设置无人船(车)模式。也可以使用地面站更改模式。 对于3档开关&#xff0c;通常最好将一个开关位置设置为HOLD&#xff0c;另一个设置为MANUAL&#xff0c;第三个设置为STEERING或AUTO。 一、ACRO模式 …

C++中的string类模拟实现

目录 string类的模拟实现 string类的构造函数 string类拷贝构造函数 string类析构函数 string类c_str()函数 string类中的[]运算符重载函数 string类中的赋值运算符重载 string类中获取字符串有效字符个数 string类中获取字符串存储空间大小&#xff08;不包括\0&…

把标注数据导入到知识图谱

文章目录 简介数据导入Doccano标注数据&#xff0c;导入到Neo4j寻求帮助 简介 团队成员使用 Doccano 标注了一些数据&#xff0c;包括 命名实体识别、关系和文本分类 的标注的数据&#xff1b; 工作步骤如下&#xff1a; 首先将标注数据导入到Doccano&#xff0c;查看一下标注…

配置vite配置文件更改项目端口、使用@别名

一、配置vite配置文件更改项目端口 vite官方文档地址&#xff1a;开发服务器选项 | Vite 官方中文文档 (vitejs.dev) 使用&#xff1a; 二、使用别名 1. 安装 types/node types/node 包允许您在TypeScript项目中使用Node.js的核心模块和API&#xff0c;并提供了对它们的类型…

嵌入式面试八股文

大家好&#xff0c;今天给大家介绍嵌入式面试八股文&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 嵌入式面试中&#xff0c;常被问到的问题通常涉及嵌入式系统的基础知识、应用…

zabbix源码安装

目录 一.安装php和nginx客户端环境 二.修改php配置 三.修改nginx配置文件 四.下载并编译zabbix 五.创建zabbix需要的用户及组 六.安装编译需要的依赖 七.配置zabbix文件 八.数据库配置 九.配置zabbix 十.web界面部署 十一.遇到无法创建配置文件 十二.登录zabbix 前…

非关系型数据库-----------Redis的主从复制、哨兵模式

目录 一、redis群集有三种模式 1.1主从复制、哨兵、集群的区别 1.1.1主从复制 1.1.2哨兵 1.1.3集群 二、主从复制 2.1主从复制概述 2.2主从复制的作用 ①数据冗余 ②故障恢复 ③负载均衡 ④高可用基石 2.3主从复制流程 2.4搭建redis主从复制 2.4.1环境准备 2.4…

Sy6 编辑器vi的应用(+shell脚本3例子)

实验环境&#xff1a; 宿主机为win11&#xff0c;网络&#xff1a;10.255.50.5 6389 WSL2 ubuntu 目标机的OS&#xff1a;Ubuntu 内核、版本如下&#xff1a; linuxpeggy0223:/$ uname -r 5.15.146.1-microsoft-standard-WSL2 linuxpeggy0223:/$ cat /proc/version Linux vers…

解析二极管的单向导电性

二极管是电子电路中很常用的元器件&#xff0c;非常常见&#xff0c;二极管具有正向导通&#xff0c;反向截止的特性。 在二极管的正向端&#xff08;正极&#xff09;加正电压&#xff0c;负向端&#xff08;负极&#xff09;加负电压&#xff0c;二极管导通&#xff0c;有电流…

云计算的安全需求

目录 一、概述 二、云安全服务基本能力要求 三、信息安全服务&#xff08;云计算安全类&#xff09;资质要求 3.1 概述 3.2 资质要求内容 3.2.1 组织与管理要求 3.2.2 技术能力要求 四、云安全主要合规要求 4.1 安全管理机构部门的建立 4.2 安全管理规范计划的编制 4…

计算机视觉之三维重建(5)---双目立体视觉

文章目录 一、平行视图1.1 示意图1.2 平行视图的基础矩阵1.3 平行视图的极几何1.4 平行视图的三角测量 二、图像校正三、对应点问题3.1 相关匹配法3.2 归一化相关匹配法3.3 窗口问题3.4 相关法存在的问题3.5 约束问题 一、平行视图 1.1 示意图 如下图即是一个平行视图。特点&a…

大数据设计为何要分层,行业常规设计会有几层数据

大数据设计通常采用分层结构的原因是为了提高数据管理的效率、降低系统复杂度、增强数据质量和可维护性。这种分层结构能够将数据按照不同的处理和应用需求进行分类和管理&#xff0c;从而更好地满足不同层次的数据处理和分析需求。行业常规设计中&#xff0c;数据通常按照以下…

java框架学习——注解/元注解概述及使用案例

前言&#xff1a; 整理下学习笔记&#xff0c;打好基础&#xff0c;daydayup!!! 注解 注解&#xff08;Annotation&#xff09;是java代码里的特殊标记。作用为&#xff1a;让其他程序根据注解信息来决定怎么执行该程序&#xff0c;如&#xff1a;Override,Test等。同时可以根…

安装pillow库的方法最终解答!

安装pillow库&#xff0c;记录留痕。 Pillow库是一个非常强大的图像处理库。它提供了广泛的图像处理功能&#xff0c;让我们可以轻松地操作图像&#xff0c;实现图像的转换、裁剪、缩放、旋转等操作。此外&#xff0c;Pillow还支持多种图像格式的读取和保存&#xff0c;包括JP…

「每日跟读」句型公式 第2篇

「每日跟读」句型公式 第2篇 1. I’m thinking about____ 我在考虑____ I’m thinking about my future career (我正在思考我未来的职业) I’m thinking about our marriage (我在考虑我们的婚姻) I’m thinking about taking a vacation (我在考虑度一个假) I’m think…

【RedHat9.0】Timer定时器——创建单调定时器实例

一个timer&#xff08;定时器&#xff09;的单元类型&#xff0c;用来定时触发用户定义的操作。要使用timer的定时器&#xff0c;关键是要创建一个定时器单元文件和一个配套的服务单元文件&#xff0c;然后启动这些单元文件。 定时器类型&#xff1a; 单调定时器&#xff1a;即…