【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;要么都不执行。 事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红…

九耶|阁瑞钛伦特:以下是一个地铁跑酷html代码

以下是一个简单的地铁跑酷的 HTML 代码示例&#xff1a; <!DOCTYPE html> <html> <head><title>地铁跑酷</title><style>#gameContainer {width: 400px;height: 600px;background-color: #000;position: relative;margin: 0 auto;overflo…

mount: wrong fs type, bad option, bad superblock报错 ubuntu

问题描述 mount: wrong fs type, bad option, bad superblock Ubuntu无法挂载磁盘。 原因 很大概率是你的硬盘是NTFS。 解决 sudo apt install ntfs-3g即可。

如何用12306的积分买火车票

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

AJAX并发请求控制

AJAX、axios、fetch的区别 AJAX Gmail开发人员发现IE里面有个XMLHTTPRequest对象来请求数据时&#xff0c;可以实现无刷新数据请求&#xff0c;所以使用这个特性&#xff0c;进行网络数据请求&#xff0c;这就是AJAX的由来。 AJAX不是一个单词&#xff0c;他的全称是Asynchro…

Java设计模式-享元模式

享元模式 1.享元模式含义 享元模式&#xff0c;运用共享技术有效地支持大量细粒度的对象。 其实享元模式很好理解&#xff0c;就是共享元数据的意思。比如一个小狗类对象&#xff0c;里面的属性有头&#xff0c;耳朵&#xff0c;眼睛&#xff0c;毛色这几个属性&#xff0c;…

【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.…

k8s集群中安装kibana 7.x 踩坑

1. FATAL ValidationError: child "server" fails because [child "port" fails because ["port" must be a number]] 解决办法&#xff1a; 在环境变量中指定端口&#xff1a; - name: SERVER_PORTvalue: 5601 2. Kibana FATAL Error: [elast…

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

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

英语疑问句

文章目录 一般疑问句特殊疑问句 一般疑问句 英语肯定句怎么改成一般疑问句&#xff1f; 1.假如句子中有"情态动词、助动词、be动词"则直接提前。2.假如句子&#xff0c;只有实义动词&#xff0c;就要借助"do,does,did"放在句子前面,并将实义动词改为"…

VUE3-03

1.Composition API(其他部分) 1.1 shallowReactive与shallowRef shallowReactive : 只处理了对象内最外层属性的响应式(也就是浅响应式)shallowRef: 只处理了value的响应式, 不进行对象的reactive处理 应用场景&#xff1a; 如果有一个对象数据, 结构比较深, 但变化时只是…

基于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、 输赢判断…