【C++链表】

目录

  • 前言
  • 一、搭建链表实现的框架
  • 二、链表的构造函数
  • 三、链表的尾插
  • 四、链表的遍历(重点)
    • 迭代器的遍历
    • const修饰的迭代器
  • 五、代码实现

前言

最近用C++写了一下list的基本功能,感触颇深。本以为会跟之前用C写list一样会很轻松,没想到更难了。要考虑的东西跟多了,而且模板报错真的太恶心了(小小吐槽一下,其实就是自己学的不够扎实,还得练呐)。下面的内容是我自己在写链表时的顺序及注意点。

一、搭建链表实现的框架

在这里插入图片描述

二、链表的构造函数

当把一个框架搭建好后,第一步就是写的构造函数。
在这里插入图片描述

三、链表的尾插

构造函数写完后就要开始往链表里插入数据了,所以第三步我开始写链表的尾插(这里都是比较简单的跟之前C语言没什么两样)。我懒得画图解释了,直接上代码。

void push_back(const T& val)
{
	Node* newnode = new Node(val);
	Node* tail = _head->_prev;

	//链接
	tail->_next = newnode;
	newnode->_prev = tail;

	newnode->_next = _head;
	_head->_prev = newnode;
}

四、链表的遍历(重点)

迭代器的遍历

先看看库实现的链表我们是怎么拿过来用的。
在这里插入图片描述
为了完成跟库里一样,我们还需要设计迭代器。
在这里插入图片描述
重载*、++其实很简单。但是重载!=有个比较坑的地方。
在这里插入图片描述

const修饰的迭代器

首先要清楚我们期望的const修的的迭代器是具有怎么的功能。
我们期望被const修饰过的迭代器指向的内容不要被修改,但是可以通过重载的++修改本身。
那这样行不行?如:

typedef const _list_iterator<T> const_iterator;

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

五、代码实现

其他的功能其实都不难,都很好写。所以不想画图解释了,直接上代码。

#pragma once
#include<iostream>
using namespace std;
namespace Ting
{
	template<class T>
	struct _list_node
	{
		_list_node<T>* _prev;
		_list_node<T>* _next;
		T _val;

		//构造函数
		_list_node(const T& val = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _val(val)
		{}
	};

	template<class T,class Ref,class Ptr>
	struct _list_iterator
	{
		typedef _list_node<T> Node;
		typedef _list_iterator<T,Ref,Ptr> self;
		Node* _node;

		_list_iterator(Node* node)
			:_node(node)
		{}
		bool operator!=(const self& it)//这个const有说法
		{
			return _node != it._node;
		}
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		self operator++(int)
		{
			_list_iterator<T> temp(*this);
			_node = _node->_next;
			return temp;
		}
		Ref operator*()
		{
			return _node->_val;
		}
		Ptr operator->()
		{
			return &(_node->_val);
		}
	};

	template<class T>
	class _list
	{
		typedef _list_node<T> Node;
	public:
		typedef _list_iterator<T,T&,T*> iterator;
		//如何设计const迭代器
		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;
		}

		_list()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}
		
		void push_back(const T& val=T())
		{
			Node* newnode = new Node(val);
			Node* tail = _head->_prev;

			//链接
			tail->_next = newnode;
			newnode->_prev = tail;

			newnode->_next = _head;
			_head->_prev = newnode;
		}

		void push_front(const T& val = T())
		{
			insert(begin(), val);
		}

		void pop_back()
		{
			Node* tail = _head->_prev;
			Node* newtail = tail->_prev;

			_head->_prev = newtail;
			newtail->_next = _head;
			
		}

		void pop_front()
		{
			erase(begin());
		}

		iterator insert(iterator pos, const T& val = T())
		{
			Node* cur = pos._node;
			Node* pre = cur->_prev;
			Node* newnode =new Node(val);

			pre->_next = newnode;
			newnode->_prev = pre;

			newnode->_next = cur;
			cur->_prev = newnode;

			return newnode;
		}

		iterator erase(iterator pos)
		{
			Node* cur = pos._node;
			Node* pre = cur->_prev;
			Node* next = cur->_next;

			pre->_next = next;
			next->_prev = pre;
			delete cur;

			return next;
		}

		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it=erase(it);
			}
		}

		//拷贝构造
		_list(_list<T>& lt)
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;

			iterator it = lt.begin();
			while (it != lt.end())
			{
				push_back(*it);
				++it;
			}
		}

		void swap(_list<T>& lt)
		{
			std::swap(_head, lt._head);
		}

		_list<T>& operator=(_list<T> lt)
		{
			swap(lt);
			return *this;
		}

		~_list()
		{
			clear();
		}
	private:
		Node* _head;
	};
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录| 图论04 查并集 ●查并集理论知识 ●1971.寻找图中是否存在路径 ●684.冗余连接 ●685.冗余连接II

#查并集理论知识 并查集用处&#xff1a;解决连通性问题 将两个元素添加到一个集合中。判断两个元素在不在同一个集合 思路&#xff1a;将三个元素A&#xff0c;B&#xff0c;C &#xff08;分别是数字&#xff09;放在同一个集合&#xff0c;其实就是将三个元素连通在一起&a…

k8s常见的资源对象使用

目录 一、kubernetes内置资源对象 1.1、kubernetes内置资源对象介绍 1.2、kubernetes资源对象操作命令 二、job与cronjob计划任务 2.1、job计划任务 2.2、cronjob计划任务 三、RC/RS副本控制器 3.1、RC副本控制器 3.2、RS副本控制器 3.3、RS更新pod 四、Deployment副…

IBM:2023 年数据泄露的平均成本将达到 445 万美元

IBM 发布年度《数据泄露成本报告》&#xff0c;显示 2023 年全球数据泄露平均成本达到 445 万美元&#xff0c;比过去 3 年增加了 15%。创下该报告的历史新高。 报告显示&#xff0c;企业在计划如何应对日益增长的数据泄露频率和成本方面存在分歧。研究发现&#xff0c;虽然 95…

自定义MVC

目录 一.什么是MVC 1.1.三层架构和MVC的区别 二.自定义MVC工作原理图 三.自定义mvc实现 3.1 创建web工程 3.2 中央处理器 3.3 Action接口定义 3.4 实现子控制器 3.5 完善中央控制器 3.5.1 请求分发功能 3.5.2 使用配置文件配置action 3.5.3 请求参数处理 1. 定义接…

QT DAY1

1.思维导体 2.作业 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {qDebug()<<this->size();qDebug()<<this->rect().size();qDebug()<<this->geometry().size();qDebug()<<this->frameGeometry().siz…

安防视频管理平台GB设备接入EasyCVR, 如何获取RTMP与RTSP视频流

安防视频监控平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力&#xff0c;比…

六边形架构和分层架构的区别?

六边形架构和分层架构是什么&#xff1f; 六边形架构&#xff08;Hexagonal Architecture&#xff09;和分层架构&#xff08;Layered Architecture&#xff09;是两种常见的软件架构模式。六边形架构强调将核心业务逻辑与外部依赖解耦&#xff0c;通过接口与外部世界进行通信。…

桥接模式-处理多维度变化

程序员小名去摆摊卖奶茶了&#xff0c;口味有香、甜。 型号有大、中、小。假如小名先在家里把这些奶茶装好&#xff0c;那么最少要装2x3 6杯奶茶&#xff0c;如果此时新增一个口味&#xff1a;酸&#xff0c;那么就需要多装3杯奶茶了。而且这样做&#xff0c;等客户买走一种&a…

【【51单片机直流电机调速】】

学会电机调速&#xff0c;掌握中国速度 PWM的生成方法 先用户设定一个比较值&#xff0c;然后计数器定时自增。 当计数器<比较值&#xff0c;输出0 当计数器>比较值&#xff0c;输出1 main.c #include <REGX52.H> #include"delay.h" #include"…

【弹力设计篇】聊聊熔断设计

为什么需要熔断 熔断这个词一听从生活中就是保险丝超过一定的温度后自动断开&#xff0c;以此来保护家用电器&#xff0c;属于电路中自我保护装置。如果没有熔断&#xff0c;那么家用电器一定会损坏的。 进一步再来分析一下&#xff0c;在分布式系统中&#xff0c;各个系统之间…

酷雷曼无人机技能培训考试圆满举办

2023年7月18日、19日&#xff0c;以“向云端起航&#xff0c;让技术落地”为主题的酷雷曼无人机技能提升培训会在酷雷曼北京运营中心隆重举行&#xff0c;来自全国各地的众多合作商参加了本次培训&#xff0c;通过系统、全面的学习成功取得了专业无人机飞行员执照&#xff0c;为…

django跨域设置

1.安装 (venv) ***\data_analyse_web>pip install django-cors-headers 2.添加应用 :在settings.py中添加应用,放到任意位置都行 INSTALLED_APPS {# ...corsheaders,# ... } 3. 设置中间层&#xff0c;在settings.py中添加中间层&#xff0c;放到最前面 MIDDLEWARE [c…

mac m1 触控栏TouchBar功能栏异常

电脑可能在高温下运行时间过长&#xff0c;导致TouchBar之前正常显示的调整屏幕亮度与调整声音等功能的按钮均丢失&#xff0c;然后看了一眼键盘设置&#xff0c;设置也是正常的&#xff0c;已勾选显示功能栏 下面请看 如何在MacBook Pro&#xff08;macOS Monterey&#xff0…

PHP百度小程序rtc-room组件token获取经历

【前言】 目前就职盘古网络集团&#xff0c;一名PHPer程序员。我们的主营业务是百度产品相关&#xff0c;所以最近有了一个百度小程序项目&#xff0c;涉及其音视频组件做直播。 开发文档 百度智能小程序文档 鉴权token 百度智能小程序文档 嗯&#xff0c;很好的功能。结果测…

【Redis学习】01Redis基础

Redis&#xff08;B站黑马&#xff09;学习笔记 01Redis基础 文章目录 Redis&#xff08;B站黑马&#xff09;学习笔记前言01Redis基础初始Redis认识NoSQL认识Redis安装RedisLinux版安装官网压缩包下载使用yum下载&#xff08;个人不推荐&#xff0c;找不到安装目录&#xff0…

golang+layui提升界面美化度--[推荐]

一、背景 golanglayui提升界面美化度--[推荐]&#xff1b; golang后端写的页面很难看&#xff0c;如何好看点呢&#xff0c;那就是layui https://layui.dev/ 也是一个简单上手容易使用的框架&#xff0c;类似jquery&#xff0c;对于后端开发来说满足使用需求 二、使用注意点…

Python 逻辑回归:理论与实践

文章目录 1. 介绍1.1 什么是逻辑回归&#xff1f;1.2 逻辑回归的应用领域 2. 逻辑回归的原理2.1 Sigmoid 函数2.2 决策边界2.3 损失函数 3. 逻辑回归的实现3.1 数据准备3.2 创建逻辑回归模型3.3 模型训练3.4 模型预测3.5 模型评估 4. 可视化决策边界4.1 绘制散点图4.2 绘制决策…

TortoiseGit安装

1、TortoiseGit简介 TortoiseGit是基于TortoiseSVN的Git版本的Windows Shell界面。它是开源的&#xff0c;可以完全免费使用。 TortoiseGit 支持你执行常规任务&#xff0c;例如commit、显示日志、区分两个版本、创建分支和标签、创建补丁等。 2、TortoiseGit下载 (1)Tortois…

RocketMQ第一课-快速实战以及集群架构搭建

一、RocketMQ产品特点 1、RocketMQ介绍 ​ RocketMQ是阿里巴巴开源的一个消息中间件&#xff0c;在阿里内部历经了双十一等很多高并发场景的考验&#xff0c;能够处理亿万级别的消息。2016年开源后捐赠给Apache&#xff0c;现在是Apache的一个顶级项目。 ​ 早期阿里使用Act…

【如何训练一个中译英翻译器】LSTM机器翻译seq2seq字符编码(一)

系列文章 【如何训练一个中译英翻译器】LSTM机器翻译seq2seq字符编码&#xff08;一&#xff09; 【如何训练一个中译英翻译器】LSTM机器翻译模型训练与保存&#xff08;二&#xff09; 【如何训练一个中译英翻译器】LSTM机器翻译模型部署&#xff08;三&#xff09; 训练一个…