【C++】STL中list的模拟实现(增删查改,迭代器封装,运算符重载)

文章目录

  • 前言
    • 大体框架:
  • 一、节点的封装(list_node)
  • 二、迭代器的封装(_list_iterator)
    • 1.类模板的定义:
    • 2.构造函数
    • 3.前置++,后置++
    • 4.前置--,后置--
    • 5.解引用(operator*())
    • 6. ->重载(operator- >())
    • 7.比较运算符的重载:
  • 三、list成员函数
    • 1.构造函数
    • 2.begin(),end()
    • 3.插入(insert)在pos之前一个位置插入
    • 4.删除(erase)
    • 5.尾插尾删
    • 6.头插头删
    • 7.析构函数
    • 8.赋值运算符重载
    • 9.拷贝构造函数
    • 10.大小(size)


前言

list的底层结构为带头结点的双向循环链表

大体框架:

namespace simulation {template <class T>struct list_node {//成员函数};
template<class T,class Ref,class Ptr>struct _list_iterator {//成员函数};template<class T>class list {typedef list_node<T> Node;public:typedef _list_iterator<T, T&, T*> iterator;typedef _list_iterator<T, const T&, const T*>  const_iterator;//成员函数private:Node* _head;size_t _size;};}

一、节点的封装(list_node)

template <class T>struct list_node {//带头的双向循环链表//在类模板中://类名不等于类型,所以定义指针时类名要显示实例化list_node<T>* _prev;list_node<T>* _next;T _val;list_node(const T&val=T())//T()相当于调用构造函数;:_prev(nullptr),_next(nullptr),_val(val){}};

二、迭代器的封装(_list_iterator)

因为list的数据不是在一片连续的内存中(像vector,string那样)
所以我们不能用原生指针来当迭代器iterator,我们要自己设计一个
迭代器,自己去实现其++以及比较等操作

1.类模板的定义:

//设计const迭代器:可以把迭代器理解为类似指针// 错误示范: typedef const __list_iterator<T> const_iterator;// 这样设计const迭代器是不行的,因为const迭代器期望指向内容不能修改// 这样设计是迭代器本身不能修改//为了设计不那么繁琐,我们传入三个模板参数template<class T,class Ref,class Ptr>//相当于:// typedef __list_iterator<T, T&, T*> iterator;// typedef __list_iterator<T, const T&, const T*> const_iterator;

2.构造函数

typedef list_node<T> Node;typedef _list_iterator<T, Ref, Ptr> self;Node* _node;//成员变量_list_iterator(Node* node):_node(node){}

3.前置++,后置++

self& operator++() {//前置++//typedef _list_iterator<T, Ref, Ptr> self;_node = _node->_next;return *this;}self operator++(int) {//后置++self tmp(*this);_node = _node->_next;return tmp;}

4.前置–,后置–

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

5.解引用(operator*())

Ref operator*() {//因为可能为const T&类型或者T&类型//为了避免繁琐,使用模板参数里面的Ref//编译器根据不同的类型会生成对应的函数return _node->_val;}

6. ->重载(operator- >())

    //template<class T,class Ref,class Ptr>//相当于:// typedef __list_iterator<T, T&, T*> iterator;// typedef __list_iterator<T, const T&, const T*> const_iterator;
Ptr operator->() {return&_node->_val;}

在这里插入图片描述

7.比较运算符的重载:

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

三、list成员函数

1.构造函数

typedef list_node<T> Node;public:typedef _list_iterator<T, T&, T*> iterator;typedef _list_iterator<T, const T&, const T*>  const_iterator;void empty_init() {_size = 0;_head = new Node;_head->_prev = _head;_head->_next = _head;}list() {//构造函数empty_init();}private:Node*_head;//哨兵位size_t _size;

2.begin(),end()

         iterator begin() {//begin()为哨兵位下一个return _head->_next;}const_iterator begin()const {return _head->_next;}//end()为哨兵位iterator end() {return _head;}const_iterator end()const {return _head;}

3.插入(insert)在pos之前一个位置插入

在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

iterator insert(iterator pos, const T& x) {Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);newnode->_prev = prev;newnode->_next = cur;prev->_next = newnode;cur->_prev = newnode;++_size;//返回指向第一个新插入元素的迭代器。return newnode;}

4.删除(erase)

iterator erase(iterator pos) {assert(pos != end());Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;delete cur;prev->_next = next;next->_prev = prev;--_size;//返回被删除节点的下一个位置return next;}

5.尾插尾删

	void push_front(const T& x) {insert(begin(), x);}void pop_back() {erase(--end());}

6.头插头删

void push_back(const T&x) {insert(end(), x);}
void pop_front() {erase(begin());}

7.析构函数

        void clear() {iterator it = begin();while (it != end()) {it = erase(it);}_size = 0;}~list() {clear();delete _head;_head = nullptr;}

8.赋值运算符重载

void swap(list<T>&lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}list<T>operator=(list<T> lt) {swap(lt);return *this;}

9.拷贝构造函数

     list(const list<T>& lt) {empty_init();_size = lt._size;for (auto &ch : lt) {push_back(ch);}}

10.大小(size)

size_t size() {return _size;}

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

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

相关文章

【腾讯云 Cloud Studio 实战训练营】永不宕机的IDE,Coding Everywhere

【腾讯云 Cloud Studio 实战训练营】永不宕机的IDE&#xff0c;随时随地写代码&#xff01; 写在最前视频讲解&#xff1a;Cloud Studio活动简介何为腾讯云 Cloud Studio?Cloud Studio简介免费试用&#xff0c;上手无忧Cloud Studio 特点及优势云端开发多种预制环境可选metawo…

ansible自动化运维(二)剧本、角色编写实战

&#x1f618;作者简介&#xff1a;一名运维工作人员。 &#x1f44a;宣言&#xff1a;人生就是B&#xff08;birth&#xff09;和D&#xff08;death&#xff09;之间的C&#xff08;choise&#xff09;&#xff0c;做好每一个选择。 &#x1f64f;创作不易&#xff0c;动动小…

计数排序算法

计数排序 计数排序说明&#xff1a; 计数排序&#xff08;Counting Sort&#xff09;是一种非比较性的排序算法&#xff0c;它通过统计元素出现的次数&#xff0c;然后根据元素出现的次数将元素排列在正确的位置上&#xff0c;从而实现排序。计数排序适用于非负整数或者具有确…

动态sql以及常用的标签

什么是动态sql&#xff1a; 指根据不同的条件生成不同的sql 搭建环境&#xff1a; 建表&#xff1a; create table blog( id varchar(50) not null comment 博客id, title varchar(100) not null comment 博客标题, author varchar(30) not null comment 博客作者, create_ti…

yolo系列笔记(v4-v5)

YOLOv4 YOLOv4网络详解_哔哩哔哩_bilibili 网络结构&#xff0c;在Yolov3的Darknet的基础上增加了CSP结构。 CSP的优点&#xff1a; 加强CNN的学习能力 去除计算瓶颈。 减少显存的消耗。 结构为&#xff1a; 、 其实还是类似与残差网络的结构&#xff0c;保留下采样之前…

分析npm run serve之后发生了什么?

首先需要明白的是&#xff0c;当你在终端去运行 npm run ****&#xff0c;会是什么过程。 根据上图的一个流程&#xff0c;就可以衍生出很多问题。 1&#xff0c;为什么不直接运行vue-cli-service serve? 因为直接运行 vue-cli-service serve&#xff0c;会报错&#xff0c…

【已解决】如果将MySQL数据库中的表生成PDM

数据库表PDM关系图 | 原创作者/编辑&#xff1a;凯哥Java | 分类&#xff1a;经验分享 有时候&#xff0c;我们需要MySQL数据库中的表生成对应的PDM文件&#xff0c;这里凯哥就讲讲第一种将MySQL数据库的表生成对应的PDM文件。 环境准备&#xff1a; MySQL数据库连接客户端&…

<el-date-picker>组件选择开始时间,结束时间自动延长30min

背景&#xff1a;选择开始时间&#xff0c;结束时间自动增加30分钟&#xff0c;结束时间也可重新选择&#xff0c;如图&#xff1a; <el-form-item label"预约开始时间" prop"value1"><el-date-pickersize"large"v-model"ruleForm…

[数据库]对数据库事务进行总结

文章目录 1、什么是事务2、事务的特性&#xff08;ACID&#xff09;3、并发事务带来的问题4、四个隔离级别&#xff1a; 1、什么是事务 事务是逻辑上的一组操作&#xff0c;要么都执行&#xff0c;要么都不执行。 事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红…

如何用12306的积分买火车票

积分买的票是不允许退票的&#xff0c;所以最好自己买票的时候用。 积分获取 是根据价格*5&#xff0c;比如我买的是100元的票就可以获得500积分。

【Git系列】Git到远程仓库

&#x1f433;Git到远程仓库 &#x1f9ca;1. github账号注册&#x1f9ca;2. 初始化本地仓库&#x1f9ca;3. 创建GitHub远程仓库&#x1f9ca;4. 给本地仓库起别名&#x1fa9f;4.1 查看远程库的连接地址&#x1fa9f;4.2 起别名 &#x1f9ca;5. git推送操作&#x1f9ca;6.…

揭秘!头条百科词条创建全过程及技巧解析

随着互联网时代的到来&#xff0c;人们获取信息的方式越来越便捷。作为国内领先的信息平台&#xff0c;头条百科成为了很多人查阅知识的首选。然而&#xff0c;如何在头条上创建百科词条&#xff0c;让更多人了解和熟知自己呢&#xff1f;本文伯乐网络传媒将为您揭开这个谜团&a…

基于C语言 --- 自己写一个三子棋小游戏

C语言程序设计笔记---019 初阶三子棋小游戏(开源)1、arr_main.c程序大纲2、arr_game1.h3、arr_game1.c3.1、 自定义初识化函数 InitBoard( ) 和 自定义显示函数 DisPlayBoard( )3.2、 自定义玩家下棋函数 PlayerMove( )3.4、 自定义电脑下棋函数 ComputerMove( )3.5、 输赢判断…

反射简述

什么是反射反射在java中起到什么样的作用获取class对象的三种方式反射的优缺点图 什么是反射 JAVA反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意一个方法和属性&…

自然语言处理学习笔记(一)————概论

目录 1.自然语言处理概念 2.自然语言与编程语言的比较 &#xff08;1&#xff09;词汇量&#xff1a; &#xff08;2&#xff09;结构化&#xff1a; &#xff08;3&#xff09;歧义性&#xff1a; &#xff08;4&#xff09;容错性&#xff1a; &#xff08;5&#xff0…

LabVIEW FPGA开发实时滑动摩擦系统

LabVIEW FPGA开发实时滑动摩擦系统 由于非线性摩擦效应的建模和补偿的固有困难&#xff0c;摩擦系统的运动控制已被广泛研究。最近&#xff0c;人们更加关注滑动动力学和滑动定位&#xff0c;作为传统机器人定位的低成本和更灵活的驱动替代方案。摩擦控制器设计和适当选择基础…

【机器学习】Overfitting and Regularization

Overfitting and Regularization 1. 过拟合添加正则化2. 具有正则化的损失函数2.1 正则化线性回归的损失函数2.2 正则化逻辑回归的损失函数 3. 具有正则化的梯度下降3.1 使用正则化计算梯度&#xff08;线性回归 / 逻辑回归&#xff09;3.2 正则化线性回归的梯度函数3.3 正则化…

解决python-opencv:(-215:Assertion failed) _img.empty() in function ‘cv::imwrite‘在将视频分成帧图片,写入时出现的问题

最近在搞视频检测问题&#xff0c;在用到将视频分帧保存为图片时&#xff0c;图片可以保存&#xff0c;但是会出现(-215:Assertion failed) !_img.empty() in function cv::imwrite问题而不能正常运行&#xff0c;在检查代码、检查路径等措施均无果后&#xff0c;了解了视频分帧…

linux实现运行java分包部署

1.打好包之后 找到bin文件夹下的 startup.sh文件 2.cd 进入bin文件夹下 3.执行 sh startup.sh 运行命令 4.如果出现此错误 是Windows和Linux的.sh脚本文件格式不同&#xff0c;如果在脚本中有空行&#xff0c;脚本是在Windows下进行编辑之后上传到linux上去执行的话&#xff0c…

JVM系统优化实践(23):GC生产环境案例(6)

您好&#xff0c;这里是「码农镖局」CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 在互联网大厂中&#xff0c;对每天亿级流量的日志进行清洗、整理是非常常见的工作。在某个系统中&#xff0c;需要对用户的访问日志做脱敏处理&#xff0c;也就是清洗掉姓名…