list类底层逻辑实现

  list的底层逻辑是一个双向带头链表。那么list的底层其实就跟我们之前实现的带头双向链表相同,都是开辟一个一个单独的节点,最后再通过指针将各个单独的节点链接起来即可。

  我们来类比之前编写的双向带头链表实现具体的内容。

  创建一个list类的主体

  

  就像我们说的那样,我们需要先创建一个带头的空链表。在编写list的构造函数之前我们需要先实现一个结构体,一个用于创建节点的结构体。之后我们可以直接new一个该节点直接进行链接操作即可。

  

  我们创建一个结构体之后就可以在里面再编写一个构造函数,用于初始化我们节点的内容,在创建的同时可以对节点进行初始化操作。

  那么之后我们就可以进行编写list的构造函数了:

  我们在默认构造当中进行的操作就是开辟好一个头节点,并将该节点单独链接成为带头双向循环链表。

  push_back()尾插函数

  在初始化好链表之后我们就可以进行链表功能的正式编写了。其实插入操作也非常的简单。我们只需要新创建一个节点,并将该节点链接进入带头双向循环链表当中即可。

  我们仔细梳理逻辑可以发现:想要实现尾插操作只需要在头节点之前链接进入新的节点即可。因为我们的头节点的前一个位置就是我们规定链表的最后一个位置。编写代码如下:

  iterator类

  之后我们就会想要测试该函数是否可以正常的运行。所以我们就需要一个可以打印出链表当中元素的函数。所以我们下一步就需要实现我们的迭代器的功能。

  但是我们会发现,list的迭代器跟我们之前编写的vector和string的迭代器有很大程度上的区别。之前编写的迭代器都是顺序存储结构,我们可以使用地址的指针作为迭代器直接使用。但是list是链式存储结构。那么就不能直接使用地址作为迭代器了,所以我们封装了一个新的类作为迭代器。

  在这个迭代器当中我们创建了一个新的node结点用于在链表当中进行移动。(因为我们原有的类list类当中_head指针不能进行改变,所以就需要一个新的node指针适应我们的++操作。)之后我们只需要实现相应的构造函数即可。

  仔细看的话大家肯定会对iterator的构造函数有疑问,这不是进行浅拷贝了吗?那么在释放的时候会不会有歧义呢?在这里确实进行了浅拷贝操作,但是我们想要的就是浅拷贝的效果。因为我们迭代器想要指向的就是我们已经开辟好的地址的指针,所以进行浅拷贝才是我们想要的效果。

  我们可以通过使用库当中的迭代器打印输出链表数据的形式进行反向推导我们想要实现的相关的功能。

    首先我们需要实现的就是begin和end函数。我们需要返回一个迭代器类型的数据。

  让我们进行分析一下:我们只需要返回_head指针的下一个位置即可,因为_head指针的下一个位置表示的是链表当中第一个元素节点的指针,作为返回值我们系统会自动调用iterator的构造函数,参数类型正好相同直接会生成一个对应的_node节点,也就是我们作为变量持续进行循环的对象。

  同样的end函数也是这个道理。我们只需要返回_head指针即可。

  之后我们需要实现的功能就变成了三处:1.实现 !=  2.实现 *  3.实现 ++

  运算符重载*

  对于*的运算符重载函数其实很简单,我们想要的就是打印输出链表当中的数据内容,所以我们只需要返回链表当中存储的数据即可。也就是我们迭代器当中保存的节点_node当中所对应的值。

  运算符重载!=

  我们可以思考一下不等号两边的数据类型。

  仔细观察我们就会发现,不等号两边都是我们重载之后的iterator的类型,而我们想要比较的是迭代器当中保存的节点的指针。所以我们可以直接写出如下的代码:

  第一个_node是我们的左操作数tmp当中的成员变量,我们可以直接使用,而我们的右操作数是一个iterator的类型的数据,所以我们就需要通过 . 操作符找到当中的成员变量。这两个参数就是我们想要比较的对象,我们直接比较并返回比较之后的结果即可。

  运算符重载++

  对于++的运算符重载函数同样很简单,我们只需要修改iterator当中的node节点当中保存的数据即可。也就是将_node指针指向下一个位置即可。

  

  在实现上述的函数之后,我们就可以打印输出链表当中相应的数据了。

  iterator的模板参数

  T&和const T&

  当我们在使用链表进行数据输出的时候很容易会想到:list当中保存的是变量数据,但是如果我们想要保存常量数据,也就是不允许其他人修改链表当中的数据应该怎么做呢?

  我们进行分析可以发现:

  实际上起作用的也就是我们的解引用操作,如果我们对T进行一个限定也就是添加一个const进行修饰不就好了吗?那该如何做呢?直接typedef const list_iterator<T> const_iterator ? 当然不行我们会发现这个const是针对于我们的iterator类并不是仅仅针对于我们的T参数。那么就有人可能会说了:直接复制一份命名为const_list_iteartor,并将模板传承const T不就好了吗?但是我们会发现我们就仅仅修改了一个参数,而我们的代码却变得十分冗余。为什么不直接添加参数呢?

  T*和const T*

  我们只需要添加一个参数进行修改即可。对于不同参数的迭代器类型我们可以命名成不同的形式,之后系统会自动实例化成为相应的类。如果我们调用的是普通的迭代器就会实例化成为T*,如果传入const迭代器就会实例化成为const T*,从而达到我们想要的效果。

  当我们的链表当中保存的是内置类型的数据上述功能已经可以正常使用了,但是如果我们的链表当中保存的是自定义类型的数据呢?我们会不会想到需要重定义一个 -> 方便我们进行查找自定义类型当中的变量呢?

  如果我们不进行重载 -> 操作的时候我们必须进行上述的操作。但是我们如果重载 -> 之后我们就可以通过该操作符直接进行打印操作。

  是不是看起来简洁很多呢?那么我们也将我们的函数进行实现该功能。

  

  实质上就是通过->之后我们可以获得链表节点当中保存的数据的地址,如果该数据是自定义类型我们就可以通过这个指针找到其中的成员变量。

  但是我们会发现有一点奇怪:按照这么说我们应该进行的是两次 -> 呀?事实上确实是两次操作,第一次->是我们的运算符重载,会获得自定义类型的指针,第二次->找到自定义类型当中的成员变量。

  同样的 -> 在使用的时候也会有const的需求,那么我们就可以按照之前的思考,再添加一个参数,用来控制我们的T*是否可以被修改。

  修改代码并运行之后发现结果一切正常。

  insert函数

  实现完成上述代码之后,我们list的大部分逻辑都已经完成了,那么接下来就可以进行相关具体功能性函数的添加操作了。首先我们来实现insert函数。

  我们只需要开辟一个空间,将新开辟的空间链接进入链表当中即可。

  

  erase函数

  对于删除函数,我们只需要取下某个节点,链接前一个节点跟后一个节点即可。但是我们需要注意的是返回值的设置。由于我们的该位置的节点已经释放,所以我们该位置就无法使用,所以为了避免迭代器失效的问题,我们需要主动传出一个返回值,该返回值是我们删除节点的下一个位置。

  

  代码运行一切正常。

  拷贝构造

  之后我们来实现拷贝构造函数。实现拷贝构造函数,首先我们需要获得头节点,由于构造函数都需要执行该功能,所以我们将获取头节点的函数独立封装成为createhead函数方便我们进行复用。

  之后只需要将我们原链表当中的元素依次尾插进入我们的新链表当中即可。

  代码运行一切正常。

  运算符重载=

   对于=的运算符重载同样很简单,我们只需要交换头节点即可。释放的工作完全可以交给析构函数自动进行。

  clear函数

  在完成析构函数之前,我们先完成以下clear函数。该函数的功能是清空链表当中保存的值,但是不释放头节点。我们可以重新进行对链表的操作。

  

  对于该功能的实现,我们直接复用之前实现的erase功能即可。但是需要我们注意的是erase之后我们需要使用it接受删除之后的指针,否则就会产生报错。

  运行结果一切正常。

  析构函数

  析构函数我们直接调用clear函数清空链表当中的节点,最后再释放head节点即可。

  

  退出码为0,代码运行一切正常。

  使用n个相同的参数进行构造

  原理还是相同的,我们只需要初始化头节点之后尾插n个由该数据构造的节点即可。

  

  代码运行一切正常。

  迭代器构造

  首先我们需要进行的是初始化头节点,之后依次拷贝迭代器区间的值即可。

  ​​​​​​​

  同样的当我们使用模板参数初始化迭代器的时候需要重载一份使用n个参数进行构造的构造函数,避免重复,避免适配错误。

    size函数

  这个函数用于返回我们链表当前的元素的个数,我们可以避免麻烦直接创建一个成员变量,当我们对链表当中的数据进行修改的之后产生对应的改变即可。

  代码运行一切正常。

  front函数和back函数

  该函数的功能就是返回链表当中的第一个位置还有最后一个位置。我们分别实现普通版本和const版本。

  ​​​​​​​

  代码运行一切正常。

  头删,头插,尾删,尾插函数

  尾插函数我们已经实现完成了,那么之后我们只需要完成头删头插,尾删操作即可。

  代码运行一切正常。

  重载运算符--

  重载运算符--操作其实跟我们重载运算符++操作很像,我们只需要将移动的指针修改成为prev即可。

  ==运算符重载

  同样的道理其重载过程跟我们的!=完全相同。

  那么到此位置list的底层逻辑实现也就全部完成了。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bazel 快速入门与核心知识

Bazel 快速入门与核心知识 Bazel 简介 Bazel 是一款与 Make、Maven 和 Gradle 类似的开源构建和测试工具。 它使用人类可读的高级构建语言。Bazel 支持多种语言的项目 (C/C, Java, Python, …)&#xff0c;可为多个平台构建输出。Bazel 支持跨多个代码库和大量用户的大型代码…

ncnn之yolov5(7.0版本)目标检测pnnx部署

一、pnxx介绍与使用 pnnx安装与使用参考&#xff1a; https://github.com/pnnx/pnnxhttps://github.com/Tencent/ncnn/wiki/use-ncnn-with-pytorch-or-onnxhttps://github.com/Tencent/ncnn/tree/master/tools/pnnx 支持python的首选pip&#xff0c;否则就源码编译。 pip3 …

opencv/c++的一些简单的操作(入门)

目录 读取图片 读取视频 读取摄像头 图像处理 腐蚀 膨胀 调整图像大小 裁剪和缩放 绘制 绘制矩形 绘制圆形 绘制线条 透视变换 颜色检测 轮廓查找 人脸检测 检测人脸 检测嘴巴 可适当调整参数 读取图片 读取路径widows使用vis sto一定是\斜杠 #include <o…

界面控件Telerik UI for ASP.NET Core 2024 Q2亮点 - AI与UI的融合

Telerik UI for ASP.NET Core是用于跨平台响应式Web和云开发的最完整的UI工具集&#xff0c;拥有超过60个由Kendo UI支持的ASP.NET核心组件。它的响应式和自适应的HTML5网格&#xff0c;提供从过滤、排序数据到分页和分层数据分组等100多项高级功能。 本文将介绍界面组件Teler…

【服务对接】✈️SpringBoot 项目整合华为云 obs 对象存储服务

目录 &#x1f44b;前言 &#x1f440;一、环境准备 &#x1f331;二、整合实现 1.依赖引入 2.准备 AK 和 SK ​ 3.配置类 4.obs 工具类封装 &#x1f49e;️三、测试使用 &#x1f37b;四、 obs 客户端 &#x1f4eb;五、章末 &#x1f44b;前言 小伙伴们大家好&…

Oracle查询优化--分区表建立/普通表转分区表

本文介绍了Oracle表分区的方法&#xff0c;将已有的非分区表转化为分区表&#xff0c;也可以直接建立新的分区表&#xff0c;从而实现大表查询的优化。主要通过DBMS_REDEFINITION 和 alter table xxx modify 方法&#xff0c;DBMS_REDEFINITION 适用于所有版本&#xff0c;操作…

计算机毕业设计选题推荐-大学生竞赛管理系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

【C++ 第十六章】哈希

1. unordered系列关联式容器 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到 &#xff0c;即最差情况下需要比较红黑树的高度次&#xff0c;当树中的节点非常多时&#xff0c;查询效率也不理想。最好 的查询是&#xff0c;进行…

基于爬山法MPPT和PI的直驱式永磁同步风力发电机控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 PMSM 4.2 MPPT 4.3 PI 控制器原理 5.完整工程文件 1.课题概述 基于爬山法最大功率点跟踪 (Maximum Power Point Tracking, MPPT) 和比例积分控制器 (Proportional Integral, PI) 的直驱式永磁同步…

两个月冲刺软考——关系模式中的候选关键字与如何分解为无损连接并保持函数依赖的解法(例题讲解,看完必会)

1. 数据库中的简单属性、多值属性、复合属性、派生属性 简单属性&#xff1a;指不能够再分解成更小部分的属性&#xff0c;通常是数据表中的一个列。例如学生表中的“学号”、“姓名”等均为简单属性。 多值属性&#xff1a;指一个属性可以有多个值。例如一个学生可能会有多个…

栈OJ题——有效的括号

文章目录 一、题目链接二、解题思路三、解题代码 一、题目链接 有效的括号 题目描述&#xff1a;给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。括号匹配。 二、…

异业联盟的巅峰之作!某店生活 两年百亿销售额!

大家好 我是一家软件开发公司的产品经理 吴军 最近有个爆火的商业模式 带动了三方消费 平台能赚到钱 消费者能省钱 商家也能获取到客源甚至还能赚钱 他究竟是怎么样做到三方都赚到钱的&#xff1f; 在当前经济形势下&#xff0c;许多消费者变得谨慎&#xff0c;减少了不必…

100天带你精通Python——第8天面向对象编程

文章目录 前言面向对象技术简介类&#xff08;Class&#xff09;对象&#xff08;Object&#xff09;继承&#xff08;Inheritance&#xff09;封装&#xff08;Encapsulation&#xff09;多态&#xff08;Polymorphism&#xff09;Python类详解静态变量&#xff08;Static Var…

day39(8/29)——harbor私有仓库管理

一、harbor私有仓库管理 是python的包管理工具&#xff0c;和yum对redhat的关系是一样的 yum -y install epel-release yum -y install python2-pip pip install --upgrade pip pip list pip 8x pip install --upgrade pip pip install --upgrade pip20.3 -i https://mirror…

应用层(Web与HTTP)

目录 常见术语 1.HTTP概况 2.HTTP连接 非持久HTTP流程 响应时间模型 持久HTTP 3.HTTP报文 3.1HTTP请求报文 3.2HTTP响应报文 HTTP响应状态码 4.Cookies&#xff08;用户-服务器状态&#xff09; cookies&#xff1a;维护状态 Cookies的作用 5.Web缓冲&#xff08;…

yolo格式数据集|自动驾驶|5类别|数据集已划分好|可以直接使用|yolov5|v6|v7|v8|v9|v10通用

本数据为自动驾驶检测数据集&#xff0c;数据集是车类摄像头在不同场景下拍摄&#xff0c;有5类&#xff0c;分别为car、truck、person、bicycle、traffic_light。数据集整理不易&#xff0c;获取地址在最后。 数据集数量如下&#xff1a; 总共有:18000张 训练集&#xff1a;14…

【卷起来】VUE3.0教程-01-环境搭建与安装

​分享不易&#xff0c;耗时耗力&#xff0c;麻烦给个不要钱的关注和赞吧 &#x1f332; 什么是VUE Vue 是一个框架&#xff0c;也是一个生态。其功能覆盖了大部分前端开发常见的需求。但 Web 世界是十分多样化的&#xff0c;不同的开发者在 Web 上构建的东西可能在形式和规模…

算法-最长连续序列

leetcode的题目链接 这道题的思路主要是要求在O&#xff08;n)的时间复杂度下&#xff0c;所以你暴力解决肯定不行&#xff0c;暴力至少两层for循环&#xff0c;所以要在O&#xff08;n)的时间复杂度下&#xff0c;你可以使用HashSet来存储数组&#xff0c;对于每个数字&#…

给鼠标一个好看的指针特效 鼠标光标如何修改形状?

许多爱美的小伙伴们都想着如何给自己的电脑打扮一下&#xff0c;用各种各样的途径来美化我们的电脑。今天我们给大家分享一下&#xff0c;如何美化鼠标效果&#xff0c;给鼠标指针修改成一个非常好看的形状~ 一起来看几组鼠标的效果&#xff0c;小编我给大家做了个录屏&#x…

YoloV8实战:使用YoloV8实现OBB框检测

定向边框(OBB)数据集概述 使用定向边界框(OBB)训练精确的物体检测模型需要一个全面的数据集。本文解释了与Ultralytics YOLO 模型兼容的各种 OBB 数据集格式,深入介绍了这些格式的结构、应用和格式转换方法。数据集使用DOTA。 YOLO支持的 OBB 格式 在Ultralytics YOLO …