C++系列之list的模拟实现

在这里插入图片描述

💗 💗 博客:小怡同学
💗 💗 个人简介:编程小萌新
💗 💗 如果博客对大家有用的话,请点赞关注再收藏 🌞

list的节点类

template
struct list_Node
{
public:
list_Node* _prev;
list_Node* _next;
T _val;
list_Node(const T& val = T())
{
_prev = _next = nullptr;
_val = val;
}
};`

list的迭代器类

//这里写入多个参数的目的是区分const迭代器
//传入不同的模板就会有不同的类
template<class T,class Ref ,class Ptr>
struct list_iterator
{public:typedef list_Node<T> Node;typedef list_iterator<T,Ref,Ptr> self;list_iterator(Node* node = nullptr){_node = node;}list_iterator(const self& i){_node(i._node);}//const对象不改变原数据T& operator*(){return _node->_val;}T* operator->(){return &_node->val;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(_node);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self& operator--(int){self tmp(_node);_node = _node->_prev;return tmp;}bool operator!=(const self& l){return _node != l._node;}bool operator==(const self& l){return _node == l._node;}Node* _node;};

构造函数

list(int n, const T& value = T())
{_head = new Node();_head->_prev = _head;_head->_next = _head;while (n--){push_back(value);}
}
template <class Intiterator>
list(Intiterator first, Intiterator last)
{//这三行代码的作用是制造一个头结点_head = new Node();_head->_prev = _head;_head->_next = _head;while (first != last){push_back(*first);first++;}
}
list(const list<T>& l)
{_head = new Node();_head->_prev = _head;_head->_next = _head;//这里制造一个list对象,构建与l对象一样的元素,在与*this进行调换。list<T> tmp (l.begin(),l.end());swap(tmp);
}	

析构函数

~list()
{clear();//复用clear()函数,如果元素是自定义类型,则一一析构,delete _head;_head = nullptr;
}

赋值运算符=

list<T>& operator=(const list<T> l)
{swap(l);return *this;
}

迭代器的使用


iterator begin()
{return iterator(_head->_next);
}
iterator end()
{return itertor(_head);
}
//const对象迭代器的使用返回的是const指针(实际上迭代器是一个模板,只是类型不同)
const_iterator begin()const
{return const_iterator(_head->_next);
}
const_iterator end()const
{return itertor(_head);
}		

list的元素大小和判空

size_t size()const//const与非const对象都可调用
{return _size;
}
bool empty()const
{return _size == 0;
}

访问list的头节点与尾节点

T& front()
{return _head->_next->_val;
}
const T& front()const
{return _head->_next->_val;
}
T& back()
{return _head->_prev->_val;
}
const T& back()const
{return _head->_prev->_val;
}

尾插,尾删,头插,尾删,插入,删除,交换,清空

//这里使用了函数的调用
void push_back(const T& val)
{insert(end(), val); 
}
void pop_back() 
{ erase(--end()); 
}
void push_front(const T& val) 
{ insert(begin(), val); 
}
void pop_front() 
{ erase(begin());
}
// 在pos位置前插入值为val的节点
//这里不会发生迭代器的失效,迭代器没有被改变,返回时返回pos之前的迭代器
iterator insert(iterator pos, const T& val)
{Node* newnode = new Node(val);Node* node_pos = pos.Node;Node* prev = node_pos->_prev;Node* next = node_pos->_next;prev->_next = next;next->_prev = prev;return newnode;
}
// 删除pos位置的节点,返回该节点的下一个位置
//这里发生迭代器的失效。指向pos指针变成野指针,返回时需要更新到该节点的下一个位置
iterator erase(iterator pos)
{Node* node_pos = pos.Node;Node* node_next = pos.Node->_next;node_pos->_prev->_next = node_pos->_next;node_next->_prev = node_pos->_prev;delete node_pos;return iterator(node_next);
}
//清除链表,只保留头节点
void clear()
{iterator it = begin();while (it != end()){erase(it);}_head->_prev = _head;_head->_next = _head;
}
//交换链表
void swap(const list<T>& L)
{Node* tmp = L._head;L._head = tmp;tmp = _head;
}
#include  <assert.h>
#include <iostream>
using namespace std;
namespace zjy
{template<class T>struct list_Node{public:list_Node* _prev;list_Node* _next;T _val;list_Node(const T& val = T()){_prev = _next = nullptr;_val = val;}};template<class T,class Ref ,class Ptr>struct list_iterator{public:typedef list_Node<T> Node;typedef list_iterator<T,Ref,Ptr> self;list_iterator(Node* node = nullptr){_node = node;}list_iterator(const self& i){_node(i._node);}T& operator*(){return _node->_val;}T* operator->(){return &_node->val;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(_node);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self& operator--(int){self tmp(_node);_node = _node->_prev;return tmp;}bool operator!=(const self& l){return _node != l._node;}bool operator==(const self& l){return _node == l._node;}Node* _node;};template<class T>class list{public:typedef list_Node<T> Node;typedef list_iterator<T,T&,T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;list(){_head = new Node();_head->_prev = _head;_head->_next = _head;}/*list(int n, const T& value = T()){_head = new Node();_head->_prev = _head;_head->_next = _head;while (n--){Node* newnode = new Node(value);Node* tail = _head->_prev;tail -> _next = newnode;newnode->_prev = _head;newnode->_next = _head;_head->_prev = newnode;tail = newnode;}}*/list(int n, const T& value = T()){_head = new Node();_head->_prev = _head;_head->_next = _head;while (n--){push_back(value);}}/*template <class Intiterator>list(Intiterator first, Intiterator last){_head = new Node();_head->_prev = _head;_head->_next = _head;Node* begin= first._node;Node* end = last._node;Node* tail = _head->_prev;while (begin != last){tail->_next = begin;begin->_prev = tail;begin->_next = _head;_head->_prev = begin;tail = begin;begin++;}}*/template <class Intiterator>list(Intiterator first, Intiterator last){_head = new Node();_head->_prev = _head;_head->_next = _head;while (first != last){push_back(*first);first++;}}void  swap(const list<T>& L){Node* tmp = L._head;L._head = tmp;tmp = _head;}list(const list<T>& l){_head = new Node();_head->_prev = _head;_head->_next = _head;list<T> tmp (l.begin(),l.end());swap(tmp);}list<T>& operator=(const list<T> l){swap(l);return *this;}~list(){clear();delete _head;_head = nullptr;}iterator begin(){return iterator(_head->_next);}iterator end(){return itertor(_head);}const_iterator begin()const{return const_iterator(_head->_next);}const_iterator end()const{return const_itertor(_head);}size_t size()const{return _size;}bool empty()const{return _size == 0;}T& front(){return _head->_next->_val;}const T& front()const{return _head->_next->_val;}T& back(){return _head->_prev->_val;}const T& back()const{return _head->_prev->_val;}void push_back(const T& val) {insert(end(), val); }void pop_back() { erase(--end()); }void push_front(const T& val) { insert(begin(), val); }void pop_front() { erase(begin()); }// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){Node* newnode = new Node(val);Node* node_pos = pos.Node;Node* prev = node_pos->_prev;Node* next = node_pos->_next;prev->_next = next;next->_prev = prev;return newnode;}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){Node* node_pos = pos.Node;Node* node_next = pos.Node->_next;node_pos->_prev->_next = node_pos->_next;node_next->_prev = node_pos->_prev;delete node_pos;return iterator(node_next);}void clear(){iterator it = begin();while (it != end()){erase(it);}_head->_prev = _head;_head->_next = _head;}void test(){Node* tmp = _head->_next;while (tmp != _head){cout << tmp->_val << endl;tmp = tmp->_next;}}private:Node* _head;size_t _size;};
}

在这里插入图片描述

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

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

相关文章

关于本地项目上传到gitee的详细流程

如何上传本地项目到Gitee的流程&#xff1a; 1.Gitee创建项目 2. 进入所在文件夹&#xff0c;右键点击Git Bash Here 3.配置用户名和邮箱 在gitee的官网找到命令&#xff0c;注意这里的用户名和邮箱一定要和你本地的Git相匹配&#xff0c;否则会出现问题。 解决方法如下&…

linux上java -jar方式运行项目及输出文件nohup.out的清理, linux上定时器的用法

linux上java -jar方式运行项目及输出文件nohup.out的清理&#xff0c; linux上定时器的用法 linux上java -jar方式运行定期自动清理nohup.out文件的内容**验证**定时器crontab使用时注意事项 linux上java -jar方式运行 参考&#xff1a;https://blog.csdn.net/qq_42169450/arti…

2023 MathorCup(妈妈杯) 数学建模挑战赛B题完整解题思路+模型+代码

2023妈妈杯数学建模B题完整版思路、模型代码已出&#xff01;&#xff01;&#xff01; 云顶数模最新完整版解题思路、模型代码&#xff0c;供大家参考~~ B题目 解题思路 详细模型解析&#xff1a;

开启CETOS 裸奔了一年的服务器开启firewall防火墙

记录一下关于firewall&#xff0c;博主非运维专家或服务器专家。 背景 客户有一台裸奔运行了一年多的系统有公网但发现没有开防火墙&#xff0c;iptables和firewall均是关闭状态&#xff0c;通过扫描发现很多漏洞。根据客户要求对端口进行重新梳理且关闭不必要或有潜在风险的…

ubuntu安装nps客户端

Ubuntu安装nps客户端 1.什么是nps内网穿透&#xff1f;2.设备情况3.下载客户端3.链接服务端3.1、无配置文件模式3.2、注册到系统服务(启动启动、监控进程) 1.什么是nps内网穿透&#xff1f; nps是一款轻量级、高性能、功能强大的内网穿透代理服务器。目前支持tcp、udp流量转发…

云端代码编辑器Atheos

什么是 Atheos &#xff1f; Atheos是一个基于 Web 的 IDE 框架&#xff0c;占用空间小且要求最低&#xff0c;构建于 Codiad 之上&#xff0c;不过 Atheos 已从原始 Codiad 项目完全重写&#xff0c;以利用更现代的工具、更简洁的代码和更广泛的功能。 注意事项 群晖内核版本太…

浅谈中国汽车充电桩行业市场状况及充电桩选型的介绍

安科瑞虞佳豪 车桩比降低是完善新能源汽车行业配套的一大重要趋势&#xff0c;目前各国政府都在努力推进政策&#xff0c;通过税收减免、建设补贴等措施提升充电桩建设速度&#xff0c;以满足新能源汽车需求。 近年来&#xff0c;在需求和技术的驱动下&#xff0c;充电桩的平…

Mac怎么删除文件和软件?苹果电脑删除第三方软件方法

Mac删除程序这个话题为什么一直重复说或者太多人讨论呢&#xff1f;因为如果操作不当&#xff0c;可能会导致某些不好的影响。因为Mac电脑如果有太多无用的应用程序&#xff0c;很有可能会拖垮Mac系统的运行速度。或者如果因为删除不干净&#xff0c;导致残留文件积累在Mac电脑…

Jmeter的接口自动化测试

在去年实施了一年的三端&#xff08;PC、无线M站、无线APP【Android、IOS】&#xff09;后&#xff0c;今年7月份开始&#xff0c;我们开始进行接口自动化的实施&#xff0c;目前已完成了整个框架的搭建以及接口的持续测试集成。今天做个简单的分享。 在开始自动化投入前&#…

第14期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

vscode 保存 “index.tsx“失败: 权限不足。选择 “以超级用户身份重试“ 以超级用户身份重试。

vscode 保存 "index.tsx"失败: 权限不足。选择 “以超级用户身份重试” 以超级用户身份重试。 操作&#xff1a;mac在文件夹中创建文件&#xff0c;sudo 创建umiJs项目 解决&#xff1a;修改文件夹权限 右键文件夹

STM32F103单片机内部RTC实时时钟驱动程序

一、STM32f103系列RTC功能 RTC实时时钟功能是嵌入式软件开发中比较常用的功能&#xff0c;一般MCU的RTC功能都带有年月日时间寄存器&#xff0c;比如STM32F4xx系列&#xff0c;RTC描述如下&#xff1a; 可见F4系列的RTC功能比较强大&#xff0c;设置好初始时间后&#xff0c;读…

NodeJS爬取墨刀上的设计图片

背景 设计人员分享了一个墨刀的原型图&#xff0c;但是给的是只读权限&#xff0c;无法下载其中的素材&#xff1b;开发时想下载里面的一张动图&#xff0c;通过浏览器的F12工具在页面结构找到了图片地址。 但是浏览器直接访问后发现没权限&#xff1a; Nginx 的 403 页面。。…

批量编辑 Outlook 联系人

现状 Outlook 自带的联系人编辑功能无法快速、批量编辑联系人字段使用 Excel 等外部编辑器&#xff0c;可批量编辑联系人 导出联系人到文件 在【联系人】界面&#xff0c;点击【文件】在【文件】界面&#xff0c;点击【打开和导出】–>【导入/导出】在弹出的向导窗口中点…

语法复习之C语言与指针

内存是如何存储数据的&#xff1f; 在C语言中定义一个变量后&#xff0c;系统就会为其分配内存空间。这个内存空间包括了地址和长度。将变量赋值后&#xff0c;该值就被写入到了指定的内存空间中。内存空间的大小一般以字节作为基本单位。   普通变量存放的是数据&#xff0c…

学习paddle-detection(paddlex的使用)

首先下载paddlex&#xff08;网页&#xff09;的本地软件&#xff0c;下载链接如下&#xff1a; paddlex 下载完成后进行安装 打开后选择开发者模式&#xff0c;开发者模式主要是和VScode进行集成 本章节主要介绍在开发者模式下可以查看和编辑的文件及其作用&#xff0c;关于…

【优选算法系列】第一节.双指针(283. 移动零和1089. 复写零)

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;优选算法系列 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff01…

LabVIEW开发基于图像处理的车牌检测系统

LabVIEW开发基于图像处理的车牌检测系统 自动车牌识别的一般步骤是图像采集、去除噪声的预处理、车牌定位、字符分割和字符识别。结果主要取决于所采集图像的质量。在不同照明条件下获得的图像具有不同的结果。在要使用的预处理技术中&#xff0c;必须将彩色图像转换为灰度&am…

LaTeX:在标题section中添加脚注footnote

命令讲解 先导包&#xff1a; \usepackage{footmisc} 设原标题为&#xff1a; \section{标题内容} 更改为&#xff1a; \section[标题内容]{标题内容\protect\footnote{脚注内容}} 语法讲解&#xff1a; \section[]{} []内为短标题&#xff0c;作为目录和页眉中的标题。…

在Golang中理解错误处理

处理Golang中临时错误和最终错误的策略和示例 作为一名精通Golang的开发人员&#xff0c;您了解有效的错误处理是编写健壮可靠软件的关键因素。在复杂系统中&#xff0c;错误可能采取各种形式&#xff0c;包括临时故障和最终失败。在本文中&#xff0c;我们将探讨处理Golang中…