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的简单实现就完成了。

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

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

相关文章

服务端 TCP 连接的 TIME_WAIT 过多问题的分析与解决

https://blog.csdn.net/zxlyx/article/details/120397006 本文给出一个 TIME_WAIT 状态的 TCP 连接过多的问题的解决思路&#xff0c;非常典型&#xff0c;大家可以好好看看&#xff0c;以后遇到这个问题就不会束手无策了。 问题描述 模拟高并发的场景&#xff0c;会出现批量…

《Python深度学习-Keras》精华笔记3:解决深度学习多分类问题

公众号&#xff1a;机器学习杂货店作者&#xff1a;Peter编辑&#xff1a;Peter 持续更新《Python深度学习》一书的精华内容&#xff0c;仅作为学习笔记分享。 本文是第三篇&#xff1a;介绍如何使用Keras解决Python深度学习中的多分类问题。 多分类问题和二分类问题的区别注意…

Linux dup dup2函数

/*#include <unistd.h>int dup2(int oldfd, int newfd);作用&#xff1a;重定向文件描述符oldfd 指向 a.txt, newfd 指向b.txt,调用函数之后&#xff0c;newfd和b.txt close&#xff0c;newfd指向a.txtoldfd必须是一个有效的文件描述符 */ #include <unistd.h> #i…

Vue 2 条件渲染

条件渲染相关的指令有哪些&#xff1f; v-if、v-else、v-else-ifv-show v-if 的作用 <div v-if"expression"></div>v-if 根据表达式 expression 返回的值是否为 truthy 来决定其内容是否被渲染。 Vue还实现了 v-else 和 v-else-if&#xff1a; <d…

排序算法:快速排序(三种排序方式、递归和非递归)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关排序算法的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通…

autojs修改顶部标题栏颜色

顶部标题栏的名字是statusBarColor 不是toolbar。难怪我搜索半天搜不到 修改之后变成这样了 代码如下&#xff1a; "ui"; importClass(android.view.View); importClass(android.graphics.Color); ui.statusBarColor(Color.parseColor("#ffffff")); ui.…

【Spring Cloud系统】- 轻量级高可用工具Keepalive详解

【Spring Cloud系统】- 轻量级高可用工具Keepalive详解 文章目录 【Spring Cloud系统】- 轻量级高可用工具Keepalive详解一、概述二、Keepalive分类2.1 TCP的keepalive2.2 HTTP的keep-alive2.3 TCP的 KeepAlive 和 HTTP的 Keep-Alive区别 三、nginx的keepalive配置3.1 nginx保持…

NPM使用技巧

NPM使用技巧 前言技巧全局模块位置PowerShell报错安装模块冲突 NPM介绍NPM命令使用方法基本命令模块命令查看模块运行命令镜像管理 常用模块rimrafyarn 前言 本文包含NodeJS中NPM包管理器的使用技巧&#xff0c;具体内容包含NPM介绍、NPM命令、常用模块等内容&#xff0c;还包…

【STM32】学习笔记-时间戳RTC

Unix时间戳 Unix 时间戳&#xff08;Unix Timestamp&#xff09;定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数&#xff0c;不考虑闰秒 时间戳存储在一个秒计数器中&#xff0c;秒计数器为32位/64位的整型变量 世界上所有时区的秒计数器相同&#xff0c;不同时区通…

upload-labs 16/17关

16 将gif文件和包含一句话木马的php文件放在同一目录下&#xff0c;用cmd的copy命令将php文件整合进文件中。 可以看到最后一行包含了注入代码 将b1文件上传到服务器后&#xff0c;发现并未能正常执行代码&#xff0c;将上传后的文件下载到本地&#xff0c;打开后发现最后的代…

XML解析 不允许有匹配 _[xX][mM][lL]_ 的处理指令目标

以上错误是在解析xml参数时候报出的。 我这里错误的原因在于&#xff0c;<?xml version\"1.0\" encoding\"UTF-8\"?>少了个空格&#xff0c;参考下图&#xff1a; 下面一行才是对的。

发收一体的2.4G射频合封芯片Y62G,内置九齐MCU

宇凡微2.4GHz发收一体合封芯片Y62G是一款高度集成的系统芯片&#xff0c;融合了2.4G芯片G350和微控制器&#xff08;MCU&#xff09;功能&#xff0c;为开发人员提供了更好的设计自由度和成本效益的解决方案。以下是Y62G芯片的主要特点和优势&#xff1a; 高度合封集成 Y62G芯…

SQL4 查询结果限制返回行数

描述 题目&#xff1a;现在运营只需要查看前2个用户明细设备ID数据&#xff0c;请你从用户信息表 user_profile 中取出相应结果。 示例&#xff1a; iddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male复旦大学Shanghai36543female20北京大学Beijin…

SpringMvc 之crud增删改查应用

目录 1.创建项目 2.配置文件 2.1pom.xml文件 2.2 web.xml文件 2.3 spring-context.xml 2.4 spring-mvc.xml 2.5 spring-MyBatis.xml 2.6 jdbc.properties 数据库 2.7 generatorConfig.xml 2.8 日志文件log4j2 3.后台代码 3.1 pageBean.java 3.2切面类 3.3 biz层…

【Spring Boot】JPA — JPA入门

JPA简介 1. JPA是什么 JPA是Sun官方提出的Java持久化规范&#xff0c;它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据&#xff0c;通过注解或者XML描述“对象-关系表”之间的映射关系&#xff0c;并将实体对象持久化到数据库中&#xff0c;极大地简…

公司内部传文件怎么安全——「用绿盾透明加密软件」

为保证公司内部文件传递的安全性&#xff0c;可以使用天锐绿盾透明加密软件来进行保护。以下是具体的操作步骤&#xff1a; 在公司内部部署天锐绿盾加密软件&#xff0c;确保需要传递的文件都能受到加密保护。 在员工的工作电脑上安装天锐绿盾客户端&#xff0c;并设置好相关的…

Grafana配置邮件告警

1、创建一个监控图 2、grafana邮件配置 vim /etc/grafana/grafana.ini [smtp] enabled true host smtp.163.com:465 user qinziteng05163.com password xxxxx # 授权码 from_address qinziteng05163.com from_name Grafanasystemctl restart grafana-serv…

本地启动 Falcon-180B

本地启动 Falcon-180B 通过 Gradio 的 load 函数&#xff0c;我们可以在本地加载 HuggingFace 的 Spaces 上面的 demo。 那就运行 Falcon-180B 来试试吧。 创建 falcon_demo.py 文件&#xff0c; cat << EOF > falcon_demo.py import gradio as grdemo gr.load(&q…

亚马逊云科技与德勤中国推出新工具,有效缓解生成式AI时代下的安全问题

随着人工智能技术的飞速发展&#xff0c;生成式AI应用越发广泛&#xff0c;在各领域迎来了新的机遇&#xff0c;但同时也在安全层面给企业带来了新的挑战。网络攻击、数据泄露、隐私侵犯等安全威胁&#xff0c;以及法律法规的不断更新&#xff0c;使跨区域运营过程中的网络安全…

Apipost:API开发者的协同工作神器

在当今快速发展的数字化时代&#xff0c;API已成为企业与开发者实现数据互通、应用集成的重要桥梁。然而&#xff0c;随着API数量的不断增加&#xff0c;API开发、调试、测试、文档等工作也变得越来越复杂。为了解决这一痛点&#xff0c;一款名为Apipost的API协同研发工具应运而…