List的模拟实现 迭代器

————————————————————
list与vector相比,插入、删除等操作实现的成本非常低,如果在C语言阶段熟悉理解过链表,那么现在实现起来list就显得比较简单,可以说操作层面上比vector更简洁,因为list没有扩容这个繁琐而耗时的操作,就不需要实现reserve函数了,

唯一的难点在于实现链表遍历,当然这里说得不是像C语言下通过原生节点跳转遍历,而是采用迭代器遍历。

STL中所有的容器都采用迭代器++ or --的方式进行访问,对于string和vector来说,迭代器是非常好理解的,得益于string和vector的物理存储空间连续,迭代器可以视作原生指针。

But,对于链表而言,每一个节点的位置都是随机存储的,如果还是使用原生节点去访问,那么势必为出现野指针导致访问权限冲突的问题。故而需要借助类和模板进行封装模拟原生指针的效果。

故而可以 得出:STL中的迭代器可以分为两类
1、原生指针
2、模拟指针效果的对象

因此文章主要谈论list迭代器的模拟实现,具体代码请参考gitee仓库👇

https://gitee.com/chxchenhaixiao/test_c/blob/master/List/List/list.h

首先需要定义节点的结构,数值+前驱指针+后继指针的结构体

template<typename T>
struct list_node{T _data;list_node<T>* _next;		//带上<T>才是一个类型噢list_node<T>* _prev;list_node(const T& val= T()):_next(nullptr),_prev(nullptr){_data=val;}
}

其次需要实现list的主题框架,我们所实现的是双向带哨兵位循环链表

template<typename T>
class list{
private:typedef list_node<T> node;	//内部typedef,方便起见node* _head;		//_head是哨兵位节点
public:list(){_head = new node;_head->_prev=_head->_next=_head;}void push_back(const T& val = x){node* new_node = new node(x);new_node->_prev = _head->_prev;_head->_prev->_next=new_node;new_node->_next = _head;_head->_prev=new_node;}//此处非最优版本,只是为了后续方便测试
}

现在我声明了一个list< int > 类型的 lst 对象,并对它进行尾插操作,使得lst存有整型数据1,2,3,4

现在需要遍历链表,就要去定义迭代器iterator

so,我们开始遍写迭代器

template<typename T>
struct _list_iterator{typedef list_node<T> node;typedef _list_iterator<T> self;node* _node;_list_iterator(node* val):_node(val){}T& operator * (){return _node->_data;}self& operator ++(){_node=_node->_next;return *this;}self& operator --(){_node=_node->_prev;return *this;}bool operator !=(const self& val)const{return _node!=val._node;}

其实这就是对原生指针的一个封装

接着,我们自然而然会想到,既然已经实现了迭代器,那么我们遍历的时候肯定要通过迭代器类型去访问,则就需要在list类中补充返回迭代器类型的成员函数begin和end

template<typename T>
class list{
private:typedef list_node<T> node;	//内部typedef,方便起见node* _head;		//_head是哨兵位节点public:typedef _list_iterator<T> iterator;	//typedef _list_iterator<T,T&> iterator;	//typedef _list_iterator<T,const T&> cosnt_iterator;list(){_head = new node;_head->_prev=_head->_next=_head;}iterator begin(){return iterator(_head->_next);}	//哨兵位下一个节点才是第一个数据iterator end(){return iterator(_head);}void push_back(const T& val = x);
}

这样就可以实现一个普通list对象的遍历了,
目前还欠缺的是const list对象的遍历实现,因此还需要补充const迭代器,const迭代器的写法可以说是照抄普通迭代器的写法了,但是为了代码变得更为简洁,可以在定义迭代器类型的时候多设置一个模板参数,变成
template<typename T,typename Ref> //Ref指引用

而list中的typedef语句可以更新为
typedef _list_iterator<T,T&> iterator;
typedef _list_iterator<T,const T&> cosnt_iterator;

list类中增设成员函数

	const_iterator begin(){return const_iterator(_head->_next);}const_iteraotr end(){return const_iterator(_head);}

到这里为止,迭代器基本上已经是大致功能健全了,list的大部分操作借助我们定义的迭代器可以说说非常容易了,这里就不做过多展开。

最后,为了方便读者更好理解,文末献上模板实例化的过程:

在这里插入图片描述

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

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

相关文章

【JavaEE进阶】 图书管理系统开发日记——伍

文章目录 &#x1f38b;前言&#x1f332;需求分析&#x1f384;约定前后端交互接口&#x1f333;实现服务器代码&#x1f6a9;控制层&#x1f6a9;业务层&#x1f6a9;数据层 &#x1f343;修改前端代码⭕总结 &#x1f38b;前言 这次我们来实现图书管理系统的增加图书模块。…

一文学会yum源配置(联网/未联网)以及yum常用命令

1、yum源介绍 yum&#xff08;Yellow dog Updater Modified的简称&#xff09;&#xff0c;yum的宗旨是自动化地升级&#xff0c;安装/移除rpm包&#xff0c;收集rpm包的相关信息&#xff0c;检查依赖性并自动提示用户解决。yum的关键之处是要有可靠的repository&#xff0c;顾…

超维机器人年终总结大事记回顾

2023年&#xff0c;对于超维机器人来说&#xff0c;是充满挑战和机遇的一年。在这一年里&#xff0c;我们攻坚克难&#xff0c;持续创新&#xff0c;深度聚焦智能巡检机器人的发展&#xff0c;加强合作伙伴关系&#xff0c;不断优化产品和服务&#xff0c;不断提升客户体验&…

华为配置接口二三层切换示例

配置接口二三层切换示例 组网图形 图1 配置非自协商模式下速率和双工模式组网图 二三层切换简介配置注意事项组网需求配置思路操作步骤配置文件 二三层切换简介 基于接口板的硬件构造&#xff0c;某些形态设备上接口只能作为二层以太网接口&#xff0c;某些形态设备上接口…

Java锁原理剖析

1.AQS——锁的底层支持 AbstractQueuedSynchronizer抽象同步队列简称AQS,它是实现同步器的基础组件&#xff0c;并发包中锁的底层就是使用AQS实现的。 如图所示&#xff0c;AQS是一个FIFO的双向队列&#xff0c;其内部通过节点head和tail记录队首和队尾元素&#xff0c;队列元…

ANN(MLP) 三种预测

目录 介绍&#xff1a; 一、Mlp for binary classification 数据&#xff1a; 模型&#xff1a; 预测&#xff1a; 二、Mlp for Multiclass Classification 数据&#xff1a; 模型&#xff1a; 预测&#xff1a; 三、MLP for Regression 数据&#xff1a; 模型&a…

山西电力市场日前价格预测【2024-02-04】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-02-04&#xff09;山西电力市场全天平均日前电价为367.56元/MWh。其中&#xff0c;最高日前电价为441.08元/MWh&#xff0c;预计出现在18:30。最低日前电价为324.52元/MWh&#xff0c;预计…

2.4 假期作业

const char *p; 值不能变 const (char*) p; 值不能变 char *const p; 地址不能变 const char* const p; 地址和值都不能变 char const *p; 值不能变 (char *)const p; 地址不能变 char con…

‘begin_code.h‘ file not found 问题解决办法

/usr/include/x86_64-linux-gnu/SDL2/SDL_platform.h:179:10: fatal error: ‘begin_code.h’ file not found 问题解决办法 问题 在使用SDL2库时编译程序出现如下问题&#xff1a; 解决办法 在Google搜索未果后&#xff0c;考虑到对于头文件找不到问题&#xff0c;可以通…

推荐系统|概要03_AB测试

文章目录 A/B测试问题流量不够用解决方案——分层实验 Holdout 机制 A/B测试 其中小流量是指对部分的用户先尝试改进的算法模型&#xff0c;而非全部。若为全部&#xff0c;如果算法模型存在问题&#xff0c;可能会导致用户体验差&#xff0c;导致用户流失&#xff0c;而小流量…

SpringCloud + Nacos环境下抽取Feign独立模块并支持MultipartFile

文章目录 一、前提条件和背景1. 前提2. 背景 二、Feign模块1. 依赖引入2. application.yaml配置3. 扩展支持MultipartFile4. 将media-api注册到feign 三、Media模块四、Content模块1. 引入依赖2. 启用FeignClient3. 测试 五、需要澄清的几点 一、前提条件和背景 1. 前提 已经…

【git】本地项目推送到github、合并分支的使用

1. github上创建仓库信息 点击个人头像&#xff0c;选择【你的仓库】 点击【新增】 填写仓库信息 2. 本地项目执行的操作 1.生成本地的git管理 (会生成一个.git的文件夹) git init 2.正常提交到暂存区&#xff0c;并填写提交消息 git add . git commit -m "init…