C++ List (带你一篇文章搞定C++中的List类)

news2024/12/25 23:38:42

感谢大佬的光临各位,希望和大家一起进步,望得到你的三连,互三支持,一起进步

数据结构习题_LaNzikinh篮子的博客-CSDN博客

初阶数据结构_LaNzikinh篮子的博客-CSDN博客

收入专栏:C++_LaNzikinh篮子的博客-CSDN博客

其他专栏:c语言基础_LaNzikinh篮子的博客-CSDN博客

个人主页:LaNzikinh-CSDN博客

文章目录

  • 前言
  • 一.迭代器
  • 二.list的底层实现
  • 三.list使用和细节
  • 总结

前言

经过前面两个容器的讲解,其实已经对很多接口的使用都了解的差不多了,容器之间接口的使用真的都是大体相同的,但是底层的实现是不同的,今天我们来看看列表是如何实现这个功能的,在讲解列表的实现之前,我们先要再次来讲解这个迭代器


一.迭代器

迭代器的功能分为四种迭代器,反向迭代器,常数迭代器,反向常数迭代器,他的性质有三种,单向迭代器,双向迭代器和随机迭代器,性质的意思就是底层结构,底层结构可以决定可以用哪些算法

举个例子来说,比如说我们之前学过的排序算法,他在库里面就一个专门这样子的函数sort,他支持的就是随机的代替其他不支持,所以说在list创建的类就不能用这个库里面的算法,只能自己实现一个,又比如说逆置算法reverse(需要++/--)他支持双向迭代器,所以说随机的也可以,但是单向的就不行

我们的list就是双向迭代器,我们之前学过的vector和string就是随机迭代器,那我们后面的栈和队列是什么呢?

答案是根本不支持迭代,栈的特性是先进后出,队列的特性是先进先出,如果都满足了迭代器的遍历,那这些特性就不存在了,你支持了迭代器,那你的特性的意义在什么地方呢

二.list的底层实现

我们之前讲过了库函数的使用,直接看文档即可,在这里就不做多的了解了,和之前的使用string,vector是大致相同的,主要还是来看list的底层,他是一个带头双向循环列表,不是我们以前C语言学过的单链表

接下来了,我们先要来定义两个结构体,一个就是节点本身,还有一个就是指向节点的指针,即便它是一个带头双向循环列表,这两个也是必不可少的

2.1定义两个结构体

结点

const T& data = T();利用缺省参数来进行初始化

template<class T>
struct list_node
{
	T _data;
	list_node<T>* _next;
	list_node<T>* _prev;

	list_node(const T& data = T())
		:_data(data)
		, _next(nullptr)
		, _prev(nullptr)
	{}
};

指向节点的指针

注意:这里获取的迭代器,就是一个节点的指针

因为他是一个指针,所以说我们要用函数重载来定义它的加加减减和判断等于,还有解引用

template<class T>
struct list_iterator
{
	typedef list_node<T> Node;
	typedef list_iterator<T> Self;
	Node* _node;

	list_iterator(Node* node)
		:_node(node)
	{}

	T& operator*()
	{
		return _node->_data;
	}

	Self& operator++()
	{
		_node = _node->_next;
		return *this;
	}

	Self& operator--()
	{
		_node = _node->_prev;
		return *this;
	}

	bool operator!=(const Self& s) const
	{
		return _node != s._node;
	}

	bool operator==(const Self& s) const
	{
		return _node == s._node;
	}
};

2.2insert()和 erase()

迭代器失效问题

前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

insert()

void insert(iterator pos, const T& x)
{
	Node* cur = pos._node;
	Node* prev = cur->_prev;

	Node* newnode = new Node(x);

	// prev newnode cur
	newnode->_next = cur;
	cur->_prev = newnode;
	newnode->_prev = prev;
	prev->_next = newnode;

	++_size;
}

erase()

只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响

void erase(iterator pos)
{
	assert(pos != end());

	Node* prev = pos._node->_prev;
	Node* next = pos._node->_next;

	prev->_next = next;
	next->_prev = prev;
	delete pos._node;

	--_size;
}

所以要用返回值来改正,防止迭代器失效

int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
list<int> l(array, array+sizeof(array)/sizeof(array[0]));
auto it = l.begin();
while (it != l.end())
{
l.erase(it++); // it = l.erase(it);
}

2.3头插尾插一个数据

直接复用就可以了

void push_back(const T& x)
{
	insert(end(), x);
}

void push_front(const T& x)
{
	insert(begin(), x);
}

2.4析构函数和迭代器函数

iterator begin()
{
	return _head->_next;
}

iterator end()
{
	return _head;
}

list()
{
	_head = new Node;
	_head->_next = _head;
	_head->_prev = _head;
	_size = 0;
}

2.4成员对象

private:
	Node* _head;
	size_t _size;

三.list使用和细节

还是补充几个list一些独特的函数使用方式和一些使用它的细节

emplace:构造和插入元素

他是支持直接传构造函数对象的参数的

list<A> lt;
A a1(1,1);
lt.push_back(3,3);//不合理,不存在
lt.emplace_back(3,3);//可以

unique:删除重复值

注意:前提要有序不然删不完全

merge:合并排序列表

注意:合并排序列表,v1会被滞空

it.merge(v1);

补:

如果要在pos的位置插入一个30大小的元素

auto it = lt.begin();
int k = 3;
while (k--)
{
	++*it;
}
it.insert(it, 30);

因为他的迭代器只支持++


总结

链表容器结构到这里就结束了,下一章,我们将引入一个适配器的概念去完成栈与队列的知识

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

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

相关文章

0基础带你入门Linux之使用

1.Ubuntu软件管理 回顾一下&#xff0c;我们之前使用su root切换到root模式&#xff0c;使用who 发现为什么显示的还是bd用户呢&#xff1f;为什么呢&#xff1f; 这个who是主要来查看的是我们登录的时候是以什么用户登录的 所以即使我们使用who进行查看的时候显示的还是bd用…

如何扫描试卷去除笔迹?4种方法还原整洁试卷

如何扫描试卷去除笔迹&#xff1f;扫描试卷去除笔迹&#xff0c;作为现代学习管理与评估的革新手段&#xff0c;不仅显著提升了试卷的整洁美观度&#xff0c;更在环保和资源再利用层面发挥了积极作用。它使得试卷的保存、分享与复习变得更加便捷高效&#xff0c;减少了纸质资源…

2024年9月12日美国Embarcadero公司正式发布RAD Studio Delphi/C++ Builder 12.2 雅典

Embarcadero 非常高兴地宣布&#xff0c;从今天开始&#xff0c;RAD Studio 12.2 Athens 以及 Delphi 12.2 和 CBuilder 12.2 可供客户使用。RAD Studio 12.2 Athens 版本提供了我们在 IDE 中的第一次生成式 AI 集成、用于 Web 开发的新模板库、基于 C Win64 Clang 的新编译器和…

【MATLAB源码-第266期】基于Matlab的k-means算法遥感图像分割系统仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 基于K-means算法的图像分割在遥感图像处理中的应用十分广泛&#xff0c;尤其是对于需要自动提取特定区域或目标的场景。遥感图像通常包含了大量的地物信息&#xff0c;不同的地物如水体、建筑物、植被等在遥感图像中会表现出…

电脑的主板,内存条插多少合适?

首先&#xff0c;不是插满4条内存就是最好的。 内存条插得多&#xff0c;确实可以扩充容量&#xff0c;提升性能。但是有些低端的主板配低端CPU&#xff0c;插满4条内存&#xff0c;稳定性下降。这里的稳定性包括供电&#xff0c;单独的内存供电容量等。此时CPU会通过降低内存…

为什么使用 Rust over C++ 进行 IoT 解决方案开发

物联网已成为我们日常生活中不可或缺的一部分&#xff0c;设备也越来越智能。随着该领域的扩展&#xff0c;迫切需要保证这些支持软件的设备的安全性、生产力和效率。因此&#xff0c;Rust 编程语言正在成为 IoT 设备开发人员仅次于 C 的第二大热门选择。本文将探讨为什么 Rust…

《机器学习》周志华-CH7(贝叶斯分类)

7.1贝叶斯决策论 对分类任务而言&#xff0c;在所有相关概率已知的理想情形下&#xff0c;贝叶斯决策论考虑如何基于这些概率核误判损失来选择最优的类别标记。 R ( x i ∣ x ) ∑ j 1 N λ i j P ( c j ∣ x ) \begin{equation} R(x_{i}|x)\sum_{j1}^{N}\lambda_{ij}P(c_{j}…

【C++】vector详解,模拟实现

目录 1. vector的介绍 2. vector的使用 2.1 构造函数 2.2 遍历方式 2.3 reserve与resize 2.4 shrink_to_fit 2.5 insert&#xff0c;erase&#xff0c;find 3. vector模拟实现 3.1 初始结构 3.2 析构函数 3.3 获取容量和元素个数 3.4 扩容reserve 3.5 resize改变…

最新简洁大方的自动发卡网站源码/鲸发卡v11.61系统源码/修复版

源码简介&#xff1a; 最新简洁大方的自动发卡网站源码&#xff0c;它就是鲸发卡v11.61系统源码&#xff0c;它是修复版。 说到鲸发卡系统&#xff0c;鲸发卡系统在发卡圈很多人都知道的&#xff0c;它是市面最好发卡系统之一&#xff0c;操作起来简单得很&#xff0c;界面也…

【数据结构】排序算法---快速排序

文章目录 1. 定义2. 算法步骤3. 动图演示4. 性质5. 递归版本代码实现5.1 hoare版本5.2 挖坑法5.3 lomuto前后指针 6. 优化7. 非递归版本代码实现结语 1. 定义 快速排序是由东尼霍尔所发展的一种排序算法。在平均状况下&#xff0c;排序 n 个项目要 O ( n l o g n ) Ο(nlogn) …

在 Windows 上恢复已删除的 PDF 文件的最佳方法

如果您不小心删除了 PDF 文件或由于系统突然崩溃而无法再找到它们&#xff0c;本指南介绍了恢复已删除文件的最佳方法。 帖子中列出的方法简单、有效且可行。我们在列出它们之前对其进行了测试。 什么是 PDF&#xff0c;Adobe 将未保存的 PDF 存储在哪里&#xff1f; 自从 Ad…

数据清洗-缺失值填充-K-NN算法(K-Nearest Neighbors, K-NN算法)

目录 一、安装所需的python包二、采用K-NN算法进行缺失值填充2.1可直接运行代码2.2以某个缺失值数据进行实战2.2.1代码运行过程截屏&#xff1a;2.2.2填充后的数据截屏&#xff1a; 三、K 近邻算法 (K-Nearest Neighbors, KNN) 介绍3.1 K 近邻算法定义3.2 K 近邻算法的基本思想…

Linux 文件与目录操作命令详解

文章目录 前言创建文件1. touch2. vim 文件内容显示3. cat4. more5. less6. head7. tail 文件&#xff08;目录&#xff09;复制、删除和移动8. cp9. rm10. mv 压缩文件与解压缩11. gzip12. zip 和 unzip 创建目录13. mkdir 删除目录14. rmdir 改变工作目录15. cd16. pwd 显示目…

六、二分搜索-算法总结

文章目录 六、二分搜索6.1 简介6.2 典型实例 -- 二分查找6.2 模板6.3 常见题目6.3.1 搜索插入位置6.3.2 搜索二维矩阵6.3.3 寻找旋转排序中数组中的最小值6.3.4 寻找旋转排序数组中的最小值 II6.3.5 搜索旋转排序数组6.3.6 搜索旋转排序数组 II 总结 六、二分搜索 6.1 简介 给…

Java或者前端 实现中文排序(调API的Demo)

目录 前言1. 前端2. Java 前言 前端 Vue 中的中文排序通常使用 JavaScript 提供的 localeCompare 方法来比较中文字符串 Java 后端可以使用 Collator 类来实现中文排序 1. 前端 在 Vue 中&#xff0c;使用 localeCompare 来实现中文字符串的排序&#xff1a; <template&…

Skyeye 云智能制造 v3.14.5 发布,ERP 商城

Skyeye 云智能制造&#xff0c;采用 Springboot winUI 的低代码平台、移动端采用 UNI-APP。包含 30 多个应用模块、50 多种电子流程&#xff0c;CRM、PM、ERP、MES、ADM、EHR、笔记、知识库、项目、门店、商城、财务、多班次考勤、薪资、招聘、云售后、论坛、公告、问卷、报表…

SAM 2: Segment Anything in Images and Videos

SAM2: 在图像和视频中分割任何内容 作者 Nikhila Ravi, Valentin Gabeur, Yuan-Ting Hu, Ronghang Hu 等 (Meta FAIR) 论文&#xff1a;SAM2: Segment Anything in Images and Videos项目代码&#xff1a;GitHub Repository互动演示&#xff1a;Demo 摘要 SAM2 是一个用于处…

基于51单片机的锅炉温度控制系统PID调节proteus仿真

地址&#xff1a; https://pan.baidu.com/s/17oMgAnUBUKKEVnv5hNRQmQ 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectro…

招聘数据分析师,HR会考察候选人哪些方面?

数据分析是必须具备深厚的专业技能底蕴&#xff0c;这是最基本的要求&#xff0c;其中包括对数据分析工具和编程语言的精通&#xff0c;以及对数据库管理的实验操作。 在数据分析师的招聘过程中&#xff0c;必须要注重对方掌握的知识&#xff0c;比如数据挖掘数据可视化等先进…

Qt构建JSON及解析JSON

目录 一.JSON简介 JSON对象 JSON数组 二.Qt中JSON介绍 QJsonvalue Qt中JSON对象 Qt中JSON数组 QJsonDocument 三.Qt构建JSON数组 四.解析JSON数组 一.JSON简介 一般来讲C类和对象在java中是无法直接直接使用的&#xff0c;因为压根就不是一个规则。但是他们在内存中…