【c++】list模拟实现

list的接口

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace zjw
{template<class T>struct listnode    {listnode* <T>_next;listnode* <T>_prev;T _data;listnode(const T& x = T()):_prev(nulllptr),_next(nullptr),_data(x){}};template<class T>struct _list_iterator{typedef listnode <T>node;typedef _list_iterator<T>self;node* _node;_list_iterator(node* n):_node(n){}self& operator++(){}self& operator--(){}self operator++(int){}self operator--(int){}bool operator!=(const self& s){}bool operator==(const self& s){}T& operator(){}};template <class T>class list{    typedef listnode <T>node;public:typedef _list_iterator<T>  iterator;list(){empty_init();}void empty_init(){}iterator begin(){}iterator end(){}void clear(){}~list{}list(const list<T>& it){}void push_back(const T&x){}void push_front(const T& x){}void pop_back(){}void pop_front(){}void swap(list<T>& tmp){}list<T>& operator=(list<T>it){}iterator insert(iterator pos ,const T&x){}iterator erase(iterator pos){}private :node* _head;};}

迭代器前置++,前置–,后置++,后置–

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;}

迭代器重载等于,以及不等于,以及解引用访问数据

         bool operator!=(const self& s){return s._node != _node;}bool operator==(const self& s){return s._node == _node;}T& operator*(){return _node->_data;}

链表的默认构造,以及尾插,获取链表的头和尾巴,以及测试尾插函数

 list(){empty_init();}void empty_init(){_head = new node();_head->_prev = _head;_head->_next = _head;}iterator begin(){return _head->_next;}iterator end(){return _head;}void push_back(const T&x){node* newnode = new node(x);node* tail = _head->_prev;newnode->_next = _head;newnode->_prev = tail;tail->_next = newnode;_head->_prev = newnode;}

尾插测试,以及迭代器测试

 void test1(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout <<*it << " ";it++;}}

在这里插入图片描述


const迭代器的实现

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/811e5adc5cac4d7d82a43a8790aa1741.png

我们就可以新增两个带const的begin(),end(),权限平移就可以调动。

	 iterator begin() const{return _head->_next;}iterator end() const{return _head;}

如果我们要修改迭代器所指向位置的值呢??
在这里插入图片描述
我们应该如何模拟实现一个常量迭代器呢??
如果按照以下的方式,可以实现吗??
在这里插入图片描述

所以我们应该怎么实现呢??
在这里插入图片描述
迭代器中的解引用函数,我们需要让他的返回值不被修改,所以 这个函数的返回值加const 就好了,所以我们在实现一个类,这个类基本和普通迭代器的类一样,只是在解引用函数上有区分。

	template<class T>struct const_list_iterator{typedef    listnode <T>  node;typedef const_list_iterator<T> self;node* _node;const_list_iterator(node* n):_node(n){}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;}bool operator !=(const self& s){return s._node != _node;}bool operator==(const self& s){return s._node == _node;}const T operator*(){return _node->_data;}};

在这里插入图片描述

在这里插入图片描述
这样子,就实现了const 的迭代器,但是重新搞一个类好麻烦呀,于是有大佬就想出了在提供一个模板参数来解决这个问题
在这里插入图片描述


->运算符重载函数

我们可以想一下什么时候会用到->,当指针it指向的是结构体的话,我们可以访问使用
it->data,来访问数据,也可先对指针解引用*it,*it表示拿到这个结构体,然后使用.来访问(*it).data;

  T*  operator->(){return &_node->_data;}
	 struct AA{int a1;int a2;AA(int _a1=0,int _a2=0):a1(_a1),a2(_a2){}};

测试->

	 void test3(){list<AA>res; res.push_back(AA(1,1));res.push_back(AA(2, 2));res.push_back(AA(3, 3));res.push_back(AA(4, 4));list<AA> ::iterator it = res.begin();while (it != res.end()){cout << it.operator->()->a1<<":" << it.operator->()->a2 << endl;it++;}}

在这里插入图片描述
在这里插入图片描述


这里有一个问题就是->访问也是取数据,但取到的数据能修改吗?这就面临和解引用取数据同样的问题。
我们现在需要做的是const迭代器的不能被将修改,普通的可以修改值
在这里插入图片描述
我发现这里和解引用那里不一样的是,解引用那里是值不可被修改,这里是地址不可被修改
在这里插入图片描述


=运算符重载赋值

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

赋值函数测试

 void test4(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret = res;list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}

在这里插入图片描述


拷贝构造函数

	 list(const list<T>& it){empty_init();for (auto e : it){push_back(e);}}

这里与赋值不一样的地方是赋值的话,之前的空间不用放着也没用,就在原空间操作了;拷贝构造是重新开的空间,然后将原来数据尾插到新空间
拷贝构造函数测试

 void test5(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret(res);list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}

在这里插入图片描述


insert函数和earse函数

因为之前写的双向链表就是借鉴的这里,如果逻辑不清楚,可以去看一下双向链表那一篇文章
(insert)
在这里插入图片描述

 iterator insert(iterator pos ,const T&x){node* cur = pos._node;node* prev = cur->_prev;node* newnode = new node(x);newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;cur->_prev = newnode;return newnode;}

(earse)
在这里插入图片描述

 iterator erase(iterator pos){assert(pos != end());node* cur = pos._node;node* prev = cur->_prev;node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;return next;}

这里insert函数迭代器不会失效,而earse函数迭代器会失效,最好earse完,给迭代器传下一个位置的地址。


析构函数

 void clear(){ iterator it = begin();while (it != end()){it = earse(it);//释放完一个结点,返回下一个结点地址}}~list(){clear();//完成后只剩头节点delete _head;//释放头节点_head = nullptr;//防止野指针cout<<"析构完成“<<endl;}

析构测试

	 void test8(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}res.~list();}

在这里插入图片描述


push_front函数,pop_back()函数,pop_front()函数

因为实现了insert和earse,所以这三个就简单了。

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

注意这里的end()是最后一个数据的下一个位置,所以要先–
测试头插

 void test6(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.push_front(1000);list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}

在这里插入图片描述
测试头删和尾删

void test7(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.pop_front();res.pop_back();list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}

在这里插入图片描述
测试这三个间接测试了insert和erase


源码展示

list.h

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace zjw
{template<class T>struct listnode{listnode<T>* _next;listnode<T>* _prev;T _data;listnode(const T& x = T()):_prev(nullptr),_next(nullptr),_data(x){}};template<class T ,class res,class ptr>struct _list_iterator{ typedef    listnode <T>  node;typedef _list_iterator<T,res,ptr> self;node* _node;_list_iterator(node* n):_node(n){}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;}bool operator !=(const self& s){return s._node != _node;}bool operator==(const self& s){return s._node == _node;}res  operator*(){return _node->_data;}ptr  operator->(){return &_node->_data;}};template <class T>class list{typedef    listnode <T>  node;public:typedef _list_iterator<T,T&,T*>  iterator;typedef _list_iterator<T,const T&,const T*>  const_iterator;list(){empty_init();}void empty_init(){_head = new node();_head->_prev = _head;_head->_next = _head;}iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator  end() const{return _head;}iterator erase(iterator pos){assert(pos != end());node* cur = pos._node;node* prev = cur->_prev;node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;return next;}void clear(){ iterator it = begin();while (it != end()){it=erase(it);}}~list(){clear();delete _head;_head = nullptr;cout << "析构完成" << endl;}list(const list<T>& it){empty_init();for (auto e : it){push_back(e);}}void push_back(const T&x){node* newnode = new node(x);node* tail = _head->_prev;newnode->_next = _head;newnode->_prev = tail;tail->_next = newnode;_head->_prev = newnode;}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void swap(list<T>& tmp){std::swap(_head, tmp._head);}list<T>& operator=(list<T>it){swap(it);return *this;}iterator insert(iterator pos ,const T&x){node* cur = pos._node;node* prev = cur->_prev;node* newnode = new node(x);newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;cur->_prev = newnode;return newnode;}private :node* _head;};struct AA{int a1;int a2;AA(int _a1 = 0, int _a2 = 0):a1(_a1), a2(_a2){}};void print_list(const list<AA>it){list<AA>::const_iterator res =it.begin();while (res!=it.end()){cout << res.operator->()->a1 << ":" << res->a2 << endl;res++;}}/* void test1(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout <<*it << " ";it++;}}*///void test2()//{// list<int>res;// res.push_back(1);// res.push_back(2);// res.push_back(3);// res.push_back(4);// print_list(res);////////////}/* void test3(){list<AA>res; res.push_back(AA(1,1));res.push_back(AA(2,2));res.push_back(AA(3, 3));res.push_back(AA(4, 4));print_list(res);}*//* void test4(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret = res;list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}*//* void test5(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ret(res);list<int> ::iterator it = ret.begin();while (it != ret.end()){cout << *it << " ";it++;}}*//* void test6(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.push_front(1000);list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}*//* void test7(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}cout << endl;res.pop_front();res.pop_back();list<int> ::iterator num = res.begin();while (num != res.end()){cout << *num << " ";num++;}}*/void test8(){list<int>res;res.push_back(1);res.push_back(2);res.push_back(3);res.push_back(4);list<int> ::iterator it = res.begin();while (it != res.end()){cout << *it << " ";it++;}res.~list();}}

.cpp

#include"list.h"
int main()
{zjw::test8();}

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

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

相关文章

高维中介数据: 联合显着性(JS)检验法

摘要 中介分析在流行病学和临床试验中越来越受到关注。在现有的中介分析方法中&#xff0c;流行的联合显着性&#xff08;JS&#xff09;检验会产生过于保守的 I 类错误率&#xff0c;因此功效较低。但是&#xff0c;如果在使用 JS 测试高维中介假设时&#xff0c;可以准确控制…

人力资源(E-HR)应用架构的设计与实践

当谈到人力资源管理时&#xff0c;电子人力资源&#xff08;E-HR&#xff09;系统已经成为现代企业不可或缺的组成部分。E-HR系统的设计与实践对于提高组织的人力资源管理效率和员工体验至关重要。本文将探讨E-HR应用架构的设计与实践&#xff0c;以及如何借助信息技术优化人力…

docker清理闲置镜像邮件发送

脚本名称 DockerImage_Clear.sh脚本内容 #!/bin/bash # 清除闲置的docker镜像 #docker image prune -a -f # 列出可清理的docker镜像 /usr/local/bin/docker images | grep "<none>" # 列出可清理的docker镜像数量 /usr/local/bin/docker images | grep …

怎么使用Pyecharts库对淘宝数据进行可视化展示

目录 一、准备工作 二、数据预处理 三、使用Pyecharts进行可视化展示 柱状图展示销量和评价数 散点图展示价格与销量关系 词云图展示商品标题关键词 四、总结与建议 在当今的大数据时代&#xff0c;数据可视化已经成为了一个非常重要的技能。Pyecharts是一个基于Python的…

NIO群聊系统的实现

一、前言 通过NIO编写简单版聊天室&#xff0c;客户端通过控制台输入发送消息到其他客户端。注意&#xff1a;并未处理粘包半包问题。 二、逻辑简述 服务器&#xff1a; 1&#xff09;创建服务器NIO通道&#xff0c;绑定端口并启动服务器 2&#xff09;开启非阻塞模式 3&…

C++ //练习 10.24 给定一个string,使用bind和check_size在一个int的vector中查找第一个大于string长度的值。

C Primer&#xff08;第5版&#xff09; 练习 10.24 练习 10.24 给定一个string&#xff0c;使用bind和check_size在一个int的vector中查找第一个大于string长度的值。。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /*****…

Altium Designer 22焊接辅助工具 Interactivehtmlbom 插件使用教程

目录 AD22 由Interactivehtmlbom 插件生成的焊接辅助图&#xff0c;交互方式很多&#xff0c;十分方便的为我们提供便利。 介绍安装教程&#xff1a; 前去这个网站 Interactivehtmlbom 插件&#xff0c;单击下载zip 下载完成后找个地方解压&#xff0c;双击Initablelize.bat文…

河道水库雨水情自动测报系统

随着科学技术的不断进步&#xff0c;以及城市化进程的影响&#xff0c;水库的管理变得更加复杂&#xff0c;要实现城市水库的精细化管理&#xff0c;必须借助先进的信息技术手段为支撑&#xff0c;实现对三防、水资源、供水安全的实时监控&#xff0c;优化管理模式和创新管理手…

餐饮废水处理设备定制厂家

诸城市鑫淼环保小编带大家了解一下餐饮废水处理设备定制厂家 1.餐饮废水问题 餐饮业是重要的经济领域&#xff0c;但其废水排放带来的环境问题不容忽视。餐饮废水含有高浓度的有机物、油脂、残渣等&#xff0c;若未经处理直接排放&#xff0c;会严重污染水源&#xff0c;危害环…

Matlab 机器人工具箱 例程:运动学+动力学+路径规划+可视化

文章目录 1 创建机器人2 机器人显示3 机器人示教4 机器人路径规划&#xff1a;给定关节角路径5 机器人路径规划&#xff1a;给定末端位姿&#xff0c;求关节角路径6 工作空间可视化参考链接 1 创建机器人 clc;clear;close all; deg pi/180;L1 Revolute(d, 0, a, 0, alpha, 0,…

【Python】快速入门Python一天学完基础语法

文章目录 前言1. HelloWorld2. 变量与数据类型2.1 变量2.2 数据类型2.2.1 String 字符串类型2.2.2 基本类型转换2.2.2 元组2.2.3 字典2.2.4 拆包 2.3 运算2.3.1 双除号/双乘号2.3.2 常见运算函数举例2.3.3 布尔运算 3. 控制流程3.1 if-else 语句3.2 while 循环3.3 for 循环 4. …

子线程如何获取Request

子线程获取Request 有时候在进行业务处理时对于一些对于业务不那么重要且对于返回结果无关的情况会开启一个新的线程进行处理&#xff0c;但是在开启新线程进行处理时发现无法从RequestContextHolder中获取到当前的请求&#xff0c;取出来是null 这是因为RequestContextHolder中…

逆变器专题(14)-弱电网下的LCL逆变器控制以及谐振峰问题(1)

相应仿真原件请移步资源下载 LCL滤波器 LCL滤波器因其本身为一个二阶系统&#xff0c;其本身就会引发谐振&#xff0c;导致相应谐振频率处的增益得到放大&#xff0c;进而产生谐波等问题&#xff1b;另一方面&#xff0c;在弱电网下&#xff0c;逆变器会与电网阻抗发生耦合&am…

ARM总结and复习

安装交叉编译工具链 a. 为什么安装 因为arm公司的指令集在不断迭代升级&#xff0c;指令集日益增多,而架构是基于指令集研发的&#xff0c;所以架构不一样&#xff0c;指令集也不一样 eg:arm架构使用的是arm指令集 x86架构使用的是x86指令集 而我们日常开发环境中linux的架构…

重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

大家好我是苏麟 , 今天开始又一个专栏开始了(又一个坑 哈哈) . 重载&#xff08;Overload&#xff09;和重写&#xff08;Override&#xff09;的区别。重载的方法能否根据返回类型进行区分&#xff1f; 方法的重载和重写都是实现多态的方式&#xff0c;区别在于前者实现的是编…

Java进阶-测试方法

来学习一下软件测试相关的方法&#xff0c;了解一下黑盒测试和白盒测试&#xff0c;以及后面要用到的JUnit单元测试。JUnit单元测试也属于白盒测试&#xff0c;这次内容较少且相对简单。 一、软件测试方法 1、黑盒测试 不需要写代码&#xff0c;给输入值&#xff0c;看程序…

分付在哪些商户可以使用消费,微信分付怎么提取出来到余额上面来?

分付是一款信用支付产品&#xff0c;用户可以使用分付进行线上线下的消费支付。下面是使用分付的一些方法&#xff1a; - 开通分付&#xff1a;在微信中搜索并开通分付服务&#xff0c;按照提示完成实名认证和绑定银行卡等操作。 - 线上支付&#xff1a;在支持分付的线上商户…

【Web - 框架 - Vue】随笔 - 通过CDN的方式使用VUE 2.0和Element UI

通过CDN的方式使用VUE 2.0和Element UI - 快速上手 VUE 网址 https://cdn.bootcdn.net/ajax/libs/vue/2.7.16/vue.js源码 https://download.csdn.net/download/HIGK_365/88815507测试 代码 <!DOCTYPE html> <html lang"en"> <head><meta …

『大模型笔记』最大化大语言模型(LLM)的性能(来自OpenAI DevDay 会议)

最大化大语言模型(LLM)的性能(来自OpenAI DevDay 会议) 文章目录 一. 内容介绍1.1. 优化的两个方向(上下文优化和LLM优化)1.2. 提示工程:从哪里开始1.3. 检索增强生成:拓展知识边界1.4. 微调:专属定制二. 参考文献一. 内容介绍 简述如何以可扩展的方式把大语言模型(LLMs)…

剑指offer》15--二进制中1的个数[C++]

1. 题目描述 输入一个整数&#xff0c;输出该数二进制表示中 1 的个数。 2. 解题思路 如果对负数直接右移&#xff0c;会导致最高位一直补1&#xff0c;最终变成0xFFFF死循环。 常规做法&#xff1a; 3. 代码实现 #include<iostream> #include<vector> using…