当前位置: 首页 > news >正文

C++学习之list的实现

在了解学习list实现之前我们首先了解一下关于迭代器的分类:

按功能分类:

正向迭代器    反向迭代器

const正向迭代器  const反向迭代器

按性质分类:

单向迭代器      只能++    例如单链表

 双向迭代器     可++,也可--     例如双链表 ,map和set

 随机迭代器     可加加,可减减,可+,可减  如顺序表(vector string),deque(双端队列)

这些都是由容器的底层实现。

可以看到库中提供的list模板是带头双向链表,故此我们实现它就大部分操作都是在数据结构中实现双链表时是一样。

目录

1.成员变量

节点类型的定义:

迭代器

重载前置++/--

重载后置++/--

重载*与->

重载!=与==

const迭代器

迭代器的优化:

 成员函数

构造函数

析构函数

拷贝构造函数

容量

size

修饰符 

insert()

erase ()

push_front()

pop_front()

push_back()

pop_back()

clear()


1.成员变量

template<class T>class mylist{typedef list_node<T>  Node;typedef _list_iterator<T, T&, T*> iterator;typedef _list_iterator<T,const T&,const T*> const_iterator;
private:Node* _head;size_t _size;
......
}

因为实现的是链表,故此我们的成员变量是链表头节点与链表的大小,这里我们还需要给出

节点类型的定义:

typedef list_node<T>  Node;
template<class T>struct list_node{//我们给一个缺省值为T的匿名对象list_node(const T& x = T()):data(x), _next(nullptr), _prev(nullptr){}T data;list_node<T>* _next;list_node<T>* _prev;};

迭代器

因为我们实现的是链表,那么迭代器的操作也就是链表节点的操作,节点并非一般的数据类型,

故此我们这里需要封装迭代器,迭代器本质是节点的地址:

//迭代器//认真思考的话,迭代器模拟的是一个双链表节点的运动,故我们封装迭代器里面一定是节点,这里放入节点的地址//并且重载对应的运算符,封装之后,我们在定义为iteratortemplate<class T>struct _list_iterator{//利用节点的指针实现迭代器typedef list_node<T>  Node;typedef _list_iterator<T> self;Node* _node;_list_iterator(Node* node):_node(node){}};

封装之后,我们还需要重载对于迭代器的运算符,这些重载都是在迭代器中的,我只是为了吧方法一个个体现出来,分开了。

重载前置++/--

       //重载加加self& operator++(){_node = _node->_next;return *this;}self& operator--(){_node = _node->_prev;return *this;}

重载后置++/--

       self& operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(int){self tmp(*this);_node = _node->prev;return tmp;}

重载*与->

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

重载!=与==

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

const迭代器

const迭代器对应const对象,指的是内容不能被修改,而非指针(迭代器)本身,因此我们不能直接const iterator去认为是const迭代器,这样反而不能对迭代器进行++等操作,而需要我们去重新定义
 定义const迭代器,即内容是无法被修改,由于我们访问内容是通过解引用的方法故我们需要修改访问的的这两个操作符其引用返回为const,即内容无法被修改了。

template<class T>struct _list_const_iterator{typedef list_node<T>  Node;typedef _list_const_iterator<T> self;Node* _node;_list_const_iterator(Node* node):_node(node){}//迭代器的运算符重载self& operator++(){_node = _node->_next;return *this;}self& operator--(){_node = _node->prev;return *this;}self& operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(int){self tmp(*this);_node = _node->prev;return tmp;}const T* operator->(){return &_node->data;}const T& operator*(){return &_node->data;}bool operator!=(const self& s){return _node != s._node;}bool operator==(const self& s){return _node == s._node;}};

由于const迭代器与普通的迭代器区别也就在于访问的内容无法被修改,也就是修改*与->这两个访问内容的操作符,重新实现较为麻烦,库中实现是增加了两个模板参数Ref,Ptr,利用我们传的参数不一样,从而决定用的是哪一个迭代器。

迭代器的优化:

多出两个模板参数之后,我们的*与->返回类型就是到时候传入时候的类型,故这里我们直接用Ref与Ptr代替即可。

template<class T,class Ref,class Ptr>struct _list_iterator{//利用节点的指针实现迭代器typedef list_node<T>  Node;typedef _list_iterator<T,Ref,Ptr> self;Node* _node;_list_iterator(Node* node):_node(node){}
}
        Ptr operator->(){return _node->data;}Ref operator*(){return &_node->data;}

 在list中,对于模板迭代器我们传参不一样,决定了是const还是普通

typedef _list_iterator<T, T&, T*> iterator;
typedef _list_iterator<T,const T&,const T*> const_iterator;iterator begin(){//return iterator(_head->data);return _head->_next;}iterator end(){return _head;//哨兵位就是链表的结束标志}const_iterator begin()const{return _head->_next;}const_iterator end()const{return _head;}

 成员函数

构造函数

       //通过调用一个初始化链表的函数来实现构造函数mylist(){empty_init();}

析构函数

      //通过调用clear函数释放链表的节点,在释放哨兵位,即为析构~mylist(){clear();delete _head;_head = nullptr;}

拷贝构造函数

//拷贝构造,将节点尾插入新的对象mylist(mylist<T>& p){empty_init(p);for (auto it : p){push_back(it);}}

容量

size

size_t size(){return _size;}

修饰符 

insert()

在基于实现insert,我们的其他对list的操作都可以调用insert,不需要都去对链表节点一个个操作,

其次我们设计insert的返回值及参数位置都是迭代器,直接用。

iterator insert(iterator pos, const T x)//插入也会使迭代器失效,原位置节点找不到了{Node* cur = pos._node;Node* newnode = new Node(x);Node* prev = cur->_prev;//链接节点prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;_size++;return iterator(newnode);}

erase ()

//删除   这里删除cur节点释放掉,会导致迭代器失效,因此要返回下一节点的迭代器iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;delete cur;prev->_next = next;next->_prev = prev;_size--;return iterator(next);}

push_front()

void push_front(){insert(begin());}

pop_front()

//头删void pop_front(){erase(begin());}

push_back()

//尾插void push_back(const T& x){//Node* tail = _head->preav;//Node* newnode = new Node(x);连接节点//tail->_next = newnode;//newnode->_next = _head;//newnode->prev = tail;//tail->_prev = newnode;//tail = newnode;//return (tail);insert(end(), x);}

pop_back()

//尾删void pop_back(){erase(end());}

clear()

//清数据void clear(){iterator it = begin();while (it != end()){it = erase(it);}}

至此我们对list的简单实现就完成了。

相关文章:

C++学习之list的实现

在了解学习list实现之前我们首先了解一下关于迭代器的分类&#xff1a; 按功能分类&#xff1a; 正向迭代器 反向迭代器 const正向迭代器 const反向迭代器 按性质分类&#xff1a; 单向迭代器 只能 例如单链表 双向迭代器 可&#xff0c;也可-- 例如双…...

一种高效且节约内存的聚合数据结构的实现

一种高效且节约内存的聚合数据结构的实现 在特定的场景中&#xff0c;特殊定制数据结构能够得到更加好的性能且更节约内存。 聚合函数GroupArray的问题 GroupArray聚合函数是将分组内容组成一个个数组&#xff0c;例如下面的例子&#xff1a; SELECT groupArray(concat(ABC…...

机器学习(10)---特征选择

文章目录 一、概述二、Filter过滤法2.1 过滤法说明2.2 方差过滤2.3 方差过滤对模型影响 三、相关性过滤3.1 卡方过滤3.2 F检验3.3 互信息法3.4 过滤法总结 四、Embedded嵌入法4.1 嵌入法说明4.2 以随机森林为例的嵌入法 五、Wrapper包装法5.1 包装法说明5.2 以随机森林为例的包…...

Python之数据库(MYSQL)连接

一&#xff09;数据库SQL语言基础 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的 RDBMS (Relational Database…...

【建站教程】使用阿里云服务器怎么搭建网站?

使用阿里云服务器快速搭建网站教程&#xff0c;先为云服务器安装宝塔面板&#xff0c;然后在宝塔面板上新建站点&#xff0c;阿里云服务器网以搭建WordPress网站博客为例&#xff0c;阿小云来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流程&#x…...

【自然语言处理】关系抽取 —— MPDD 讲解

MPDD 论文信息 标题:MPDD: A Multi-Party Dialogue Dataset for Analysis of Emotions and Interpersonal Relationships 作者:Yi-Ting Chen, Hen-Hsen Huang, Hsin-Hsi Chen 期刊:LREC 2020 发布时间与更新时间:2020 主题:自然语言处理、关系抽取、对话场景、情感预测 数…...

深入理解JVM虚拟机第三篇:JVM的指令集架构模型和JVM的生命周期

文章目录 一:JVM的指令集架构模型 1:基于栈式架构的特点...

[小尾巴 UI 组件库] 组件库配置与使用

文章归档于&#xff1a;https://www.yuque.com/u27599042/row3c6 组件库地址 npm&#xff1a;https://www.npmjs.com/package/xwb-ui?activeTabreadme小尾巴 UI 组件库源码 gitee&#xff1a;https://gitee.com/tongchaowei/xwb-ui小尾巴 UI 组件库测试代码 gitee&#xff1a…...

Linux系统中fork()函数的理解

fork() 函数是一个在Unix和类Unix操作系统中常见的系统调用&#xff0c;用于创建一个新的进程&#xff0c;该进程是调用进程&#xff08;父进程&#xff09;的副本。fork() 函数的工作原理如下&#xff1a; 1. 当父进程调用 fork() 时&#xff0c;操作系统会创建一个新的进程&a…...

Linux网络编程:网络协议及网络传输的基本流程

目录 一. 计算机网络的发展 二. 网络协议的认识 2.1 对于协议分层的理解 2.2 TCP/IP五层协议模型 2.3 OSI七层模型 三. 网络传输的流程 3.1 同一网段中计算机通信的流程 3.2 不同网段中计算机设备的通信 3.3 对于IP地址和MAC地址的理解 3.4 数据的封装和解包 四. 总结…...

【大数据之Kafka】十、Kafka消费者工作流程

1 Kafka消费方式 &#xff08;1&#xff09;pull&#xff08;拉&#xff09;模式&#xff1a;消费者从broker中主动拉取数据。&#xff08;Kafka中使用&#xff09; 不足&#xff1a;如果Kafka中没有数据&#xff0c;消费者可能会陷入循环&#xff0c;一直返回空数据。 &#…...

如何确保ChatGPT的文本生成对特定行业术语的正确使用?

确保ChatGPT在特定行业术语的正确使用是一个重要而复杂的任务。这涉及到许多方面&#xff0c;包括数据预处理、模型训练、微调、评估和监控。下面我将详细介绍如何确保ChatGPT的文本生成对特定行业术语的正确使用&#xff0c;并探讨这一过程中的关键考虑因素。 ### 1. 数据预处…...

行业追踪,2023-09-11

自动复盘 2023-09-11 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…...

LVS + Keepalived群集

文章目录 1. Keepalived工具概述1.1 什么是Keepalived1.2 工作原理1.3 Keepailved实现原理1.4 Keepalived体系主要模块及其作用1.5 keepalived的抢占与非抢占模式 2. 脑裂现象 &#xff08;拓展&#xff09;2.1 什么是脑裂2.2 脑裂的产生原因2.3 如何解决脑裂2.4 如何预防脑裂 …...

springboot将jar改成war

一、maven项目 1、修改pom文件 <packaging>war</packaging>2、添加Servlet API依赖&#xff0c;Spring Boot的Starter依赖通常会包含这个依赖&#xff0c;所以你可能已经有了&#xff0c;没有就需要添加 <dependency><groupId>javax.servlet</gr…...

从9.10拼多多笔试第四题产生的01背包感悟

文章目录 题面基本的01背包问题本题变式 本文参考&#xff1a; 9.10拼多多笔试ak_牛客网 (nowcoder.com) 拼多多 秋招 2023.09.10 编程题目与题解 (xiaohongshu.com) 题面 拼多多9.10笔试的最后一题&#xff0c;是一道比较好的01背包变式问题&#xff0c;可以学习其解法加深对…...

搭建自己的OCR服务,第一步:选择合适的开源OCR项目

一、OCR是什么&#xff1f; 光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;是指对文本资料的图像文件进行分析识别处理&#xff0c;获取文字及版面信息的过程。 亦即将图像中的文字进行识别&#xff0c;并以文本的形式返回。 二、OCR的基本流程 1…...

【C++】VScode配置C/C++语言环境(简洁易懂版)

目录 一、下载VScode&#xff08;装好直接跳第五步&#xff09;二、安装VScode三、VScode设置语言为中文四、VScode切换主题&#xff08;个人爱好&#xff09;五、下载C语言编译器&#xff08;MinGW-W64 GCC&#xff09;六、配置编译器环境变量七、配置VScode八、使用单独窗口…...

【hive】—原有分区表新增加列(alter table xxx add columns (xxx string) cascade;)

项目场景&#xff1a; 需求&#xff1a;需要在之前上线的分区报表中新增加一列。 实现方案&#xff1a; 1、创建分区测试表并插入测试数据 drop table test_1; create table test_1 (id string, score int, name string ) partitioned by (class string) row format delimit…...

verilog学习笔记7——PMOS和NMOS、TTL电路和CMOS电路

文章目录 前言一、PMOS和NMOS1、NMOS2、PMOS3、增强型和耗尽型4、两者面积大小 二、CMOS门电路1、非门2、与非门3、或非门4、线与逻辑5、CMOS传输门6、三态门 三、TTL电路四、TTL电路 VS CMOS电路五、数字电平六、使用CMOS电路实现逻辑函数1、上拉网络 PUN2、下拉网络 PDN3、实…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...