【1++的C++初阶】之list

👍作者主页:进击的1++
🤩 专栏链接:【1++的C++初阶】

文章目录

  • 一,什么是list
  • 二,构造与析构
    • 2.1 结点结构
    • 2.2 链表结构
    • 2.3 迭代器结构
  • 三,部分重要接口的作用及其实现
    • 3.1 迭代器相关的接口
    • 3.2 list相关接口

一,什么是list

list是可以在常数范围内进行任意插入和删除的序列式容器。
list底层是前后循环链表,因此可以双向前后迭代。与其他序列式容器相比,list的最大缺陷是不支持任意位置的随机访问。并且list还需要一些额外的空间来保存结点与结点间的相关联信息。

二,构造与析构

2.1 结点结构

template<class T>
	struct list_node
	{
		list_node* prev;//指向上一个结点
		list_node* next;//指向下一个结点
		T data;
		//构造
		list_node(const T& val = T())
			:data(val)
			, prev(nullptr)
			, next(nullptr)
		{}
	};

在此结构中,定义出来了指向结点的前后指针,结点数据类型并对上述成员变量进行了初始化。

2.2 链表结构

template<class T>
	class list
	{
	public:
		typedef list_node<T> Node;
		//构造
		list()
		{
			_head = new Node;
			_head->prev = _head;
			_head->next = _head;
		}

      void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it);
			}
			
		}

//拷贝构造

template <class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			_head = new Node;
			_head->prev = _head;
			_head->next = _head;
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

		//拷贝构造
		//现代写法
		list(const list<T>& lt)
		{
			_head = new Node;
			_head->prev = _head;
			_head->next = _head;
			list<T> tmp(lt.begin(), lt.end());
			std::swap(_head, tmp._head);
		}

       ~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
	private:
		Node* _head;	
	};

此结构中定义了头结点,并对头结点进行了初始化,使其指向上一个的指针指向自己,指向下一个的指针指向自己。
拷贝构造我们用的是现代写法,通过迭代器构造,构造出一个临时对象,再将其头结点指针进行交换。需要注意的是:在拷贝前都要进行初始化,防止其成为野指针。
在析构之前先将哨兵位头结点前的结点进行释放,因此就有了clear()函数,最后在析构时就只需将头结点释放。

2.3 迭代器结构

template<class T, class Ref, class Ptr>
	struct list_iterator
	{
		typedef list_iterator<T,Ref,Ptr> iterator;
		typedef list_node<T> Node;
		//申请一个结点指针
		Node* _node;
		//构造
		list_iterator(Node* node)
			:_node(node)
		{}
	};

list迭代器的本质就是一个指向结点的指针。先是申请结点指针,进行初始化,使其指向传过来的结点指针。

三,部分重要接口的作用及其实现

3.1 迭代器相关的接口

bool operator !=(const iterator& it)const
		{
			return _node != it._node;
		}

		bool operator == (const iterator& it)const
		{
			return _node == it._node;
		}

		Ref operator *()
		{
			return _node->data;
		}

		Ptr operator->()
		{
			return &(operator*());
		}

		iterator& operator++()
		{
			_node = _node->next;
			return *this;
		}

		iterator operator++(int)
		{
			iterator tmp = *this;
			_node = _node->next;
			return tmp;
		}

		iterator& operator--()
		{
			_node = _node->prev;
			return *this;
		}

		iterator operator--(int)
		{
			iterator tmp = *this;
			_node = _node->prev;
			return tmp;
		}

因为list迭代器是自定义类型,因此迭代器之间的一些操作,我们就必须要进行函数重载。我们解释几个比较重要的函数重载 。

   Ptr operator->()
		{
			return &(operator*());
		}

此重载所适合的环境:当list中存储的也是一个结构体是,此运算符就能够使用。
例:


  struct pos
  {
    int a;
    int b;
  };
  list<pos> lt;
  list<pos>::iterator it=lt.begin();
  it->a;

在此函数内部,返回了&(operator*()),而operator*()我们也进行了重载,返回的是结点数据–data,要是按此形式,那么此函数最终返回的就是data的地址。这与我们上述it->a不符合。原因在于,此处还有个隐藏的->,其最终形式为:it->data->a;这是编译器为了语法的可读性,而进行的的特殊处理。
在这里插入图片描述

说完->重载,我们在来说说++的重载。

iterator& operator++()//前置++
		{
			_node = _node->next;
			return *this;
		}

由于list的空间是不连续的,因此迭代器++,就是到下一结点。

3.2 list相关接口

inert的实现

iterator insert(iterator pos,const T& val)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(val);
			Node* prev = cur->prev;
			prev->next = newnode;
			newnode->prev = prev;
			newnode->next = cur;
			cur->prev = newnode;
			return iterator(newnode);

		}

在这里插入图片描述
在这里插入图片描述
erase的实现

iterator erase(iterator pos)
		{
			assert(pos != end());
			Node* cur = pos._node;
			Node* prev = cur->prev;
			Node* next = cur->next;
			prev->next = next;
			next->prev = prev;
			delete cur;
			return iterator(next);
		}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

【网络安全】DVWA靶场实战BurpSuite内网渗透

BurpSuite 内网渗透 一、 攻击模式介绍1.1 Sniper&#xff08;狙击手&#xff09;1.2 Battering ram&#xff08;攻城锤&#xff09;1.3 Pitchfork&#xff08;草叉&#xff09;1.4 Cluster bomb&#xff08;榴霰弹&#xff09; 二、 DVWA靶场搭建2.1 下载DVWA工程2.2 添加网站…

redis中使用bloomfilter的白名单功能解决缓存预热问题

一 缓存预热 1.1 缓存预热 将需要的数据提前缓存到缓存redis中&#xff0c;可以在服务启动时候&#xff0c;或者在使用前一天完成数据的同步等操作。保证后续能够正常使用。 1.2 解决办法PostConstruct注解初始化

WebRTC Simulcast介绍

原文地址&#x1f447; https://blog.livekit.io/an-introduction-to-webrtc-simulcast-6c5f1f6402eb/ 你想知道的关于Simulcast的一切 Simulcast是WebRTC中最酷的功能之一,它允许WebRTC会议在参与者网络连接不可预测的情况下进行扩展。在这篇文章中,我们将深入探讨Simulcas…

Databend 开源周报第 103 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 创建网络策略 …

Centos7 扩容(LVM 和非 LVM)

一、磁盘扩容方式 CentOS 系统的磁盘扩容可以分为两种方式&#xff1a;LVM 管理和非 LVM 管理。 LVM 管理的分区和传统分区方式是可以共存的。在同一个系统中&#xff0c;你可以同时使用 LVM 管理的分区和传统分区。 例如&#xff0c;在 CentOS 系统中&#xff0c;你可以选择将…

第一次编程测试(分频器)

一&#xff0c;分频器 定义 分频器&#xff08;Divider&#xff09;是一种电子电路或设备&#xff0c;用于将输入信号的频率降低到较低的频率。它常用于数字系统、通信系统和计时应用中。原理 整数分频器使用计数器来实现频率的降低。计数器根据输入信号的边沿触发进行计数&am…

(三)RabbitMQ七种模式介绍与代码演示

Lison <dreamlison163.com>, v1.0.0, 2023.06.22 七种模式介绍与代码演示 文章目录 七种模式介绍与代码演示四大交换机四种交换机介绍 工作模式简单模式&#xff08;Hello World&#xff09;工作队列模式&#xff08;Work queues&#xff09;订阅模式&#xff08;Publis…

macOS Big Sur 11.7.9 (20G1426) 正式版 ISO、PKG、DMG、IPSW 下载

macOS Big Sur 11.7.9 (20G1426) 正式版 ISO、PKG、DMG、IPSW 下载 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Window…

【FPGA/D6】

2023年7月25日 VGA控制器 视频23notecodetb 条件编译error时序图保存与读取&#xff1f;&#xff1f;RGBTFT显示屏 视频24PPI未分配的引脚或电平的解决方法 VGA控制器 视频23 note MCU单片机 VGA显示实时采集图像 行消隐/行同步/场同步/场消隐 CRT&#xff1a;阴极射线管 640…

94.qt qml-分页Table表格组件

在我们之前学习了87.qt qml-分页组件控件(支持设置任意折叠页数等)_qt分页控件_诺谦的博客-CSDN博客 然后我们又学习了Table实现,所以本章实现一个分页Table表格组件,配合分页控件, 模拟请求服务器数据来实现数据分解效果,因为一般使用分页的时候,一般都是分页请求,避免数…

Android TelephonyManager双卡获取数据开启状态异常的可能原因

背景 应用内不指定subId获取数据状态可能会错误&#xff0c;因为可能拿到voice的能力&#xff0c;而非data。 代码逻辑 1、通过TelephonyManager的isDataEnabled()没有指定subId时&#xff0c;调用内部方法isDataEnabledForReason&#xff0c;传入getId()参数以指定subid&am…

Hadoop——Hive运行环境搭建

Windows&#xff1a;10 JDK&#xff1a;1.8 Apache Hadoop&#xff1a;2.7.0 Apache Hive&#xff1a;2.1.1 Apache Hive src&#xff1a;1.2.2 MySQL&#xff1a;5.7 1、下载 Hadoop搭建 Apache Hive 2.1.1&#xff1a;https://archive.a…

【ArcGIS Pro微课1000例】0029:绘制全球海洋波纹荡漾效果图

本文讲解ArcGIS Pro3.0中,基于全球航洋面状矢量数据,绘制震撼全球海洋波纹荡漾效果图。 文章目录 一、效果预览二、效果制作三、参数详解一、效果预览 绘制好的海水波纹荡漾效果图如下: 下面我们来学习绘制过程。 二、效果制作 波纹荡漾效果需要在全局或者局部场景中制作…

【JVM】浅看JVM的运行流程和垃圾回收

1.JVM是什么 JVM&#xff08; Java Virtual Machine&#xff09;就是Java虚拟机。 Java的程序都运行在JVM中。 2.JVM的运行流程 JVM的执行流程&#xff1a; 程序在执行之前先要把java代码转换成字节码&#xff08;class文件&#xff09;&#xff0c;JVM 首先需要把字节码通过…

macbook 软件iMovie for Mac(专业视频剪辑工具)中文版

iMovie mac中文版是一款针对Mac平台量身定做的视频编辑工具&#xff0c;软件凭借流线型设计和直观的编辑功能&#xff0c;可以让您感受前所未有的方式制作好莱坞风格的预告片和精美电影&#xff0c;并且还可以浏览视频资料库&#xff0c;快速共享挚爱瞬间&#xff0c;创建精美的…

结构型设计模式之装饰器模式【设计模式系列】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everythi…

如何在Windows上恢复已删除的文件?

大多数人在无意中删除了一些重要文件后无法恢复。这些文件被暂时删除&#xff0c;直到我们清空回收站才会消失。你可以通过右键单击回收站中的文件并选择还原选项来轻松恢复这些文件。但是&#xff0c;如果你清理回收站删除了文件怎么办&#xff1f;或者不小心使用Shift Delet…

SpringCloud学习路线(10)——分布式搜索ElasticSeach基础

一、初识ES &#xff08;一&#xff09;概念&#xff1a; ES是一款开源搜索引擎&#xff0c;结合数据可视化【Kibana】、数据抓取【Logstash、Beats】共同集成为ELK&#xff08;Elastic Stack&#xff09;&#xff0c;ELK被广泛应用于日志数据分析和实时监控等领域&#xff0…

【数据挖掘】将NLP技术引入到股市分析

一、说明 在交易中实施的机器学习模型通常根据历史股票价格和其他定量数据进行训练&#xff0c;以预测未来的股票价格。但是&#xff0c;自然语言处理&#xff08;NLP&#xff09;使我们能够分析财务文档&#xff0c;例如10-k表格&#xff0c;以预测股票走势。 二、对自然语言处…

2023年Q2京东环境电器市场数据分析(京东数据产品)

今年Q2&#xff0c;环境电器市场中不少类目表现亮眼&#xff0c;尤其是以净水器、空气净化器、除湿机等为代表的环境健康电器。此外&#xff0c;像冷风扇这类具有强季节性特征的电器也呈现出比较好的增长态势。 接下来&#xff0c;结合具体数据我们一起来分析Q2环境电器市场中…