C++模拟实现list:list、list类的初始化和尾插、list的迭代器的基本实现、list的完整实现、测试、整个list类等的介绍

文章目录

  • 前言
  • 一、list
  • 二、list类的初始化和尾插
  • 三、list的迭代器的基本实现
  • 四、list的完整实现
  • 五、测试
  • 六、整个list类
  • 总结


前言

C++模拟实现list:list、list类的初始化和尾插、list的迭代器的基本实现、list的完整实现、测试、整个list类等的介绍


一、list

list本质上是一个双向带头循环链表。
实现list类,需要节点类(clase list_node)、迭代器(class __list_iterator);
节点类(clase list_node): 定义每个节点的结构;
迭代器(class __list_iterator): 使用节点的指针封装出一个类,可以使用运算符重载的形式更好的访问链表;

二、list类的初始化和尾插

namespace hhb
{// 节点template <class T>struct list_node{list_node(const T& val = T()): _next(nullptr), _prev(nullptr), _val(val){}list_node<T>* _next;list_node<T>* _prev;T _val;};// 链表template<class T> class list{typedef list_node<T> Node;public:list(){_head = new Node;_head->_next = _head;_head->_prev = _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;}private:Node* _head;};
}

在这里插入图片描述

三、list的迭代器的基本实现

  • 使用链表节点的指针封装出一个类,是list链表的访问可以向vector一样使用++等操作访问
  • vector和list的使用,虽然在形式上一样,但是他们的底层是不一样的
  • (*)vector迭代器是对指针的解引用
  • (*)list迭代器是调用operator(解引用操作符)函数重载,本质是不一样的

对于const迭代器,是operator(*)和 operator(->)的运算符重载函数的返回值不一样,因此需要增加两个模板参数

  • 即: (T& 和 T*)
// 迭代器
template <class T, class Ref, class Ptr>
struct __list_iterator
{typedef list_node<T> Node;typedef __list_iterator<T, Ref, Ptr> self;
public:__list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_val;}Ptr operator->(){return &_node->_val;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const self& it) const{return _node != it._node;}bool operator==(const self& it) const{return _node == it._node;}Node* _node;
};
  • operator->运算符重载编译器会进行优化, 如下:
struct A
{
public:A(int a1 = 0, int a2 = 0): _a1(a1), _a2(a2){}int _a1;int _a2;
};
void test_list02()
{hhb::list<A> lt;lt.push_back(A(1, 1));lt.push_back(A(2, 2));lt.push_back(A(3, 3));lt.push_back(A(4, 4));lt.push_back(A(5, 5));hhb::list<A>::iterator it = lt.begin();while (it != lt.end()){//cout << (*it)._a1 << " " << (*it)._a2 << " " << endl;cout << it->_a1 << " " << it->_a2 << " " << endl;// 此处编译器进行了优化, it->返回的是T* 也就是 A*, 如果要访问A的成员// 按道理来讲,应该是 (it->)->_a1 / (it->)->_a2 来进行访问++it;}cout << endl;}

在这里插入图片描述

四、list的完整实现

  • list需要有size()的接口,所以需要对链表节点个数进行计数,增加一个成员变量_size.
  • 实现insert()和erase()接口后,push_back()和push_front()、pop_back()和pop_front()接口都可以复用接口。
  • clear()只清除(不包含哨兵位的头节点)数据,不销毁链表
  • 析构函数调用clear()后,释放_head节点(哨兵位的头节点)
  • 拷贝构造函数在拷贝之前,一定要先自己初始化(创建哨兵位的头节点)
  • 赋值(=)运算符重载使用现代写法,拷贝构造加交换函数加自动调用析构函数。
	// 链表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;iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}void emptyInit(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){emptyInit();}list(const list<T>& lt){emptyInit();for (auto e : lt){push_back(e);}}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;}~list(){clear();delete _head;_head = nullptr;_size = 0;}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;insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pos_front(){erase(begin());}iterator insert(iterator pos, const T& x){Node* newNode = new Node(x);Node* cur = pos._node;Node* prev = cur->_prev;newNode->_next = cur;newNode->_prev = prev;cur->_prev = newNode;prev->_next = newNode;++_size;return newNode;}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;cur = nullptr;--_size;return next;}//size_t size()//{//	int sz = 0;//	iterator it = begin();//	while (it != end())//	{//		sz++;//		++it;//	}//	//	return sz;//}size_t size(){return _size;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}_size = 0;}private:Node* _head;size_t _size;};
}

五、测试

  • 测试push_back, pop_back可以顺便测试insert, erase函数, 所以不单独测试insert和erase函数
void test_list03()
{hhb::list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_front(5);lt.push_front(6);lt.push_front(7);lt.push_front(8);for (auto e : lt){cout << e << " ";}cout << endl;lt.pop_back();lt.pos_front();for (auto e : lt){cout << e << " ";}cout << endl;lt.clear();lt.push_back(10);lt.push_back(20);lt.push_back(30);lt.push_back(40);lt.push_back(50);for (auto e : lt){cout << e << " ";}cout << endl;cout << lt.size() << endl;}

在这里插入图片描述

  • 测试拷贝构造和赋值运算符重载
void test_list04()
{hhb::list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);for (auto e : lt){cout << e << " ";}cout << endl;hhb::list<int> lt1(lt);for (auto e : lt1){cout << e << " ";}cout << endl;hhb::list<int> lt2;lt2.push_back(10);lt2.push_back(20);lt2.push_back(30);lt2.push_back(40);lt1 = lt2;for (auto e : lt1){cout << e << " ";}cout << endl;for (auto e : lt2){cout << e << " ";}cout << endl;}

在这里插入图片描述

六、整个list类

// list.h
#pragma once#include <assert.h>
namespace hhb
{// 节点template <class T>struct list_node{list_node(const T& val = T()): _next(nullptr), _prev(nullptr), _val(val){}list_node<T>* _next;list_node<T>* _prev;T _val;};// 迭代器template <class T, class Ref, class Ptr>struct __list_iterator{typedef list_node<T> Node;typedef __list_iterator<T, Ref, Ptr> self;public:__list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_val;}Ptr operator->(){return &_node->_val;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const self& it) const{return _node != it._node;}bool operator==(const self& it) const{return _node == it._node;}Node* _node;};// 链表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;iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}void emptyInit(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){emptyInit();}list(const list<T>& lt){emptyInit();for (auto e : lt){push_back(e);}}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;}~list(){clear();delete _head;_head = nullptr;_size = 0;}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;insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pos_front(){erase(begin());}iterator insert(iterator pos, const T& x){Node* newNode = new Node(x);Node* cur = pos._node;Node* prev = cur->_prev;newNode->_next = cur;newNode->_prev = prev;cur->_prev = newNode;prev->_next = newNode;++_size;return newNode;}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;cur = nullptr;--_size;return next;}//size_t size()//{//	int sz = 0;//	iterator it = begin();//	while (it != end())//	{//		sz++;//		++it;//	}//	//	return sz;//}size_t size(){return _size;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}_size = 0;}private:Node* _head;size_t _size;};
}
  • 整个测试
#define  _CRT_SECURE_NO_WARNINGS#include <iostream>
#include <list>
using namespace std;
#include "list.h"void print1(const hhb::list<int>& lt)
{hhb::list<int>::const_iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;
}void test_list01()
{hhb::list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);hhb::list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;for (auto e : lt){cout << e << " ";}cout << endl;print1(lt);
}struct A
{
public:A(int a1 = 0, int a2 = 0): _a1(a1), _a2(a2){}int _a1;int _a2;
};void test_list02()
{hhb::list<A> lt;lt.push_back(A(1, 1));lt.push_back(A(2, 2));lt.push_back(A(3, 3));lt.push_back(A(4, 4));lt.push_back(A(5, 5));hhb::list<A>::iterator it = lt.begin();while (it != lt.end()){//cout << (*it)._a1 << " " << (*it)._a2 << " " << endl;cout << it->_a1 << " " << it->_a2 << " " << endl;// 此处编译器进行了优化, it->返回的是T* 也就是 A*, 如果要访问A的成员// 按道理来讲,应该是 (it->)->_a1 / (it->)->_a2 来进行访问++it;}cout << endl;}void test_list03()
{hhb::list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_front(5);lt.push_front(6);lt.push_front(7);lt.push_front(8);for (auto e : lt){cout << e << " ";}cout << endl;lt.pop_back();lt.pos_front();for (auto e : lt){cout << e << " ";}cout << endl;lt.clear();lt.push_back(10);lt.push_back(20);lt.push_back(30);lt.push_back(40);lt.push_back(50);for (auto e : lt){cout << e << " ";}cout << endl;cout << lt.size() << endl;}void test_list04()
{hhb::list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);for (auto e : lt){cout << e << " ";}cout << endl;hhb::list<int> lt1(lt);for (auto e : lt1){cout << e << " ";}cout << endl;hhb::list<int> lt2;lt2.push_back(10);lt2.push_back(20);lt2.push_back(30);lt2.push_back(40);lt1 = lt2;for (auto e : lt1){cout << e << " ";}cout << endl;for (auto e : lt2){cout << e << " ";}cout << endl;}int main()
{//test_list01();test_list02();//test_list03();//test_list04();return 0;
}

总结

C++模拟实现list:list、list类的初始化和尾插、list的迭代器的基本实现、list的完整实现、测试、整个list类等的介绍

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

电脑怎么录屏?超实用免费电脑录屏软件推荐与教程

在数字化时代&#xff0c;电脑录屏已成为我们工作、学习和娱乐中不可或缺的一部分。无论是录制教学视频、游戏直播、会议记录还是软件操作演示&#xff0c;一款好用的录屏软件都能大大提升我们的效率。今天&#xff0c;我们就来介绍五款超实用的电脑录屏软件&#xff0c;并附上…

【prefect】python任务调度工具 Prefect | 可视化任务工具 | Python自动化的终极武器 | 高效数据管道管理

一、产品介绍 1、官方 Github https://github.com/PrefectHQ/prefect 2、官方文档 https://docs.prefect.io/3.0/get-started/index 3、Pgsql说明 正确的python链接pgsql如下&#xff1a; import psycopg2 from sqlalchemy import create_enginedef connect_with_psycopg2(…

Node.js官网无法正常访问时安装NodeJS的方法

目录 一、使用 nvm 进行安装二、通过阿里云开源镜像站进行安装 一、使用 nvm 进行安装 此时如果直接使用 nvm install 命令进行安装会报错&#xff1a; nvm install 16.14.0Could not retrieve https://nodejs.org/dist/latest/SHASUMS256.txt. Get “https://nodejs.org/dis…

对称加密算法使用示例

Demo包括以下对称加密算法组合 备注&#xff1a;XTS仅支持AES128和AES256&#xff0c;不支持AES192 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives import cmac from cryptography.hazmat.primitives.…

MFC-基础架构

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天讲解MFC的基础架构 概述 介绍&#xff1a;MFC&#xff08;Microsoft Foundation Classes&#xff09;是微软公司提供的一个类库&#xff0c;用于在 Windows 操作系统下进行 C 应用程序开发MFC把Windows SDK API函…

解决:The play() request was interrupted by a call to pause().报错

前言&#xff1a; 最近在公司中实现进入页面之后点击单词直接播放音频的时候&#xff0c;发现音频并不会播放声音&#xff0c;并且控制台报错&#xff1a; 研究之后找到了解决方案&#xff0c;与小伙伴们进行分享 原因&#xff1a; 首先看这句话的意思&#xff1a; 在调用 …

红黑树构建模拟实现

目录 一.红黑树概述 二.红黑树的性质 ​编辑 三.构建红黑树模拟实现 插入新节点情况分析 情况一、cur为红色&#xff0c;parent为红色&#xff0c;grandfather为黑色&#xff0c;uncle存在且为红 情况二、cur为红色&#xff0c;parent为红色&#xff0c;grandfather为黑色…

VS运行程序时报错--无法定位程序输入点

发现问题&#xff1a; VS 在运行程序时&#xff0c;报错&#xff1a; 找到原因&#xff1a; 因为我在替换动态库的时候&#xff0c;只替换了lib库&#xff0c;没有替换运行目录下的dll库&#xff0c;运行时候的dll与程序中的lib库不对应。 替换库后就能解决这个问题。

PyTorch使用------自动微分模块

目录 &#x1f354; 梯度基本计算 1.1 单标量梯度的计算 1.2 单向量梯度的计算 1.3 多标量梯度计算 1.4 多向量梯度计算 1.5 运行结果&#x1f4af; &#x1f354; 控制梯度计算 2.1 控制不计算梯度 2.2 注意: 累计梯度 2.3 梯度下降优化最优解 2.4 运行结果&#x1…

dgl库安装

此篇文章继续上一篇pytorch已经安装成功的情况 &#xff08;python3.9&#xff0c;pytorch2.2.2&#xff0c;cuda11.8&#xff09; 上一篇pytorch安装教学链接 选择与之匹配的版本 输入下方代码进行测试 import dgl.data dataset dgl.data.CoraGraphDataset() print(‘Numb…

契约锁与您相约2024新疆数字经济创新大会暨新疆数字丝路博览会

9月20日&#xff0c;由新疆数字经济联合会主办&#xff0c;多家行业协会及企业共同承办的“2024(第一届)新疆数字经济创新发展大会暨新疆数字丝路博览会”在新疆国际会展中心盛大开幕&#xff0c;活动期间&#xff0c;契约锁作为电子签章行业领先的服务商携数字可信系列产品亮相…

小程序服务零工市场

零工市场小程序有着信息发布、岗位匹配、线上接单、零工人员保障险参保、技能培训、费用结算、完工确认、服务评价、纠纷调解等功能&#xff0c;为求职者和雇主搭建一座高效、便捷、精准的对接桥梁。 用工单位通过小程序的“雇主找人”&#xff0c;发布招聘信息&#xff0c;找到…

本地生活商城开发搭建 同城O2O线上线下推广

同城本地化商城目前如火如荼&#xff0c;不少朋友咨询本地生活同城平台怎么开发&#xff0c;今天商淘云与大家分享同城O2O线上商城的设计和开发。 本地生活商城一般会涉及到区域以及频道类&#xff0c;一般下单需要支持用户定位、商家定位&#xff0c;这样利于用户可以快速找到…

一文解读OLAP的工具和应用软件

OLAP&#xff08;OnlineAnalyticalProcessing&#xff09;是一种用于快速分析大规模、多维度数据的方法。OLAP工具和应用软件则是帮助人们进行OLAP分析的重要工具。本文将介绍几种常见的OLAP工具和应用软件&#xff0c;并探讨它们在数据分析中的作用。 一 OLAP工具的分类 在选…

巴菲特的长期投资策略:新投资者实现财务自由的启示

在投资界&#xff0c;沃伦巴菲特的名字几乎无人不晓。作为伯克希尔哈撒韦公司的董事长和首席执行官&#xff0c;巴菲特以其卓越的投资智慧和长期价值增长策略&#xff0c;成为了全球投资者的偶像。巴菲特的成功不仅仅是因为他的财富&#xff0c;更在于他对投资的深刻理解和对财…

Centos 7 搭建Samba

笔记&#xff1a; 环境&#xff1a;VMware Centos 7&#xff08;网络请选择桥接模式&#xff0c;不要用NAT&#xff09; 遇到一个问题就是yum 安装404&#xff0c;解决办法在下面&#xff08;没有遇到可以无视这句话&#xff09; # 安装Samba软件 yum -y install samba# 创建…

使用MinIO+PicGo在服务器搭建图床

创建minio目录 用于存放Minio可执行文件 mkdir /usr/local/minio下载minio # 进入到/usr/local/minio cd /usr/local/minio # 执行下载 wget https://dl.min.io/server/minio/release/linux-amd64/minio # 授权下载文件为可执行文件 chmod x minio创建存储目录 # 新建data存…

最短路: Djikstra

最短路: Djikstra 适用于边权非负 如果存在负边权, 则当前距离dist最小的点, 不一定就是实际离源点最近的点,可能有负边导致其它路径离当前点更近 如下图所示, 如果存在负边, y点距离S点最近, 所以选中y点进行松弛, 贪心思想 当边权非负,离起点S最近的点,不能被更新, 如果在…

相亲交友系统 现代爱情的导航仪

在这个数字化的时代&#xff0c;人们的生活方式发生了翻天覆地的变化&#xff0c;其中最显著的变化之一便是交友方式的转变。编辑h17711347205随着社会节奏的加快&#xff0c;越来越多的人选择通过相亲交友系统来寻找人生伴侣。相亲交友系统不仅简化了传统的交友流程&#xff0…

【版本更新】TDuckX表单1.9版来了

hi&#xff0c;朋友们大家好&#xff0c;填鸭表单TDuckX迎来了9月的版本更新&#xff1b;接下来让我们看看本次更新的详细内容吧。 1.新增360评估(Bate版本) 360度评估反馈&#xff08;360Feedback&#xff09;&#xff0c;又称“360度考核法”或“全方位考核法”&#xff0c…