[C++]:12:模拟实现list

[C++]:12:模拟实现list

  • 一.看一看SGI的stl_list的源码:
    • 1.基础结构+构造函数
      • 1.节点结构:
      • 2.节点构造函数:
      • 3.链表结构:
      • 4.链表的构造函数:
    • 2.析构
      • 1.节点析构:
      • 2.链表的析构:
    • 3.迭代器
  • 二.模拟实现list
    • 1.基础结构+构造函数:
      • 1.节点:
      • 2.链表:
      • 3.实现迭代器+遍历数据:
        • 1.迭代器实现:
        • 2.数据遍历
      • 3.拷贝构造+赋值
    • 2.增
      • 1.insert
      • 2.push_front && push_back
    • 3.删
      • 1.erase
      • 2.pop_front && pop_back
    • 4.查
      • 1.find
    • 5.改:
      • 2.amend
    • 6.析构函数:
      • 1.clear 和 ~list
    • 7.容量相关的函数:
      • 1.size()
      • 2.empty()

一.看一看SGI的stl_list的源码:

1.基础结构+构造函数

1.节点结构:

在这里插入图片描述

1.SGI下的节点通过两个结构体实现。
2.基础的链表节点只包括前驱指针和后继指针。
3.链表节点去继承基础链表节点,新增节点数据。
4.优化掉指针类型带模板参数。

2.节点构造函数:

1.节点本身在这个地方是没有构造函数的。
2.观察下面的链表的结构和链表的构造函数可以观察出一点细节。

3.链表结构:

1._last_base类的构造通过_M_get_node方法进行节点的空间分配。
2.初始化一个基础的链表需要构造一个哨兵位的头节点。
3.开始的时候让哨兵位的头节点自己指向自己构造一个双向带头循环的一个结构。
4.list类继承_list_base类的时候里面多了许多的typedef

在这里插入图片描述
请添加图片描述

4.链表的构造函数:

1.通过上面的代码我们发现我们构造一个节点并没有通过节点的构造函数进行构造。
2.在list类型中提供一个方法去在插入新的节点的时候去调用。

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

2.析构

1.节点析构:

在这里插入图片描述

1.使用了内存池去回收节点的空间。

2.链表的析构:

在这里插入图片描述

3.迭代器

1.类比string或者vector他们的迭代器就是原生指针是比较方便的。
2.重写operator++ 和 operator*
3.对于节点来说结构不同于string和vector的。
4.参考SGI的源码发现对于内置类型是不可以实现运算符的重载。
5.实现一个迭代器的类型!

在这里插入图片描述

在这里插入图片描述

二.模拟实现list

1.基础结构+构造函数:

1.节点:

1.自己模拟实现就不这么复杂。
2.sgi通过内存池获取空间通过_creat_node get_node函数去对新增节点的创建。
3.节点自己把自己的数据在内部调整好的构造函数。
4.insert这样的函数去处理定义节点的问题。

//1.节点结构template<class T>struct ListNode {//1.节点的构造函数:ListNode(T x){date = x;}//1.类+模板-->具体的类型。ListNode<T>* prev=nullptr;ListNode<T>* next=nullptr;T date;};

2.链表:

//3.链表结构template<class T>class list{public://1.构造:双向带头循环链表的基本结构!list():head(new ListNode<T>(T())){head->prev = head;head->next = head;}private:ListNode<T>* head;};
}

3.实现迭代器+遍历数据:

1.内置类型没有办法进行运算符的重载。
2.迭代器本质就是节点的指针。
3.把一个节点指针类型包裹在一个自定义类型中。
4.在list和iterator_ListNode类中都对相应的类型进行了重定义。

1.迭代器实现:
template<class T>struct itreator_ListNode {//2.提供迭代器的方法:typedef itreator_ListNode<T> self;typedef ListNode<T> Node;Node* _node;itreator_ListNode(Node* x):_node(x){}//1.运算符重载:bool operator!=(self x){return this->_node != x._node;}bool operator==(self x){return this->_node == x._node;}//2.运算符重载++ --self& operator++(){this->_node = this->_node->next;return *this;}self operator++(int){self ret = *this;this->_node = this->_node->next;return ret;}self& operator--(){this->_node = this->_node->prev;return *this;}self operator--(int){self ret = *this;this->_node = this->_node->prev;return ret;}T operator*(){return this->_node->date;}};
	template<class T>class list{public://1.构造:双向带头循环链表的基本结构!list():head(new ListNode<T>(T())){head->prev = head;head->next = head;}//2.提供迭代器的方法:typedef itreator_ListNode<T> iterator;typedef ListNode<T> Node;//2-1:迭代器应该满足左闭右开//List_Node<T>* 类型到iterator类型是通过单参数的构造函数支持的!iterator begin() { return head->next; }iterator end() {return head;}void push_back(T x){//1.产生一个节点:ListNode<T>* newnode = new ListNode<T>(x);//2.进行节点的连接:ListNode<T>* prev = head->prev;prev->next = newnode;newnode->prev = prev;head->prev = newnode;newnode->next = head;}private:Node* head;};
2.数据遍历

在这里插入图片描述

3.拷贝构造+赋值

//1.拷贝构造:list(list& copy):head(new ListNode<T>(T())){head->prev = head;head->next = head;//循环copy调用push_backfor (auto num : copy){push_back(num);}}
//赋值相关+交换函数void swap(list& tmp){Node* head = this->head;this->head = tmp.head;tmp.head = head;}list operator=(list tmp){swap(tmp);return *this;}

2.增

1.insert

在这里插入图片描述

1.模拟实现第一个insert函数提供迭代器和插入的节点数据:

//为什么不可以iterator&类型返回//Node* 类型到iterator类型通过单参数的构造函数支持的:发生隐式类型转换!//Node* 类型到iterator&类型没有被支持的!iterator insert(iterator pos , T x = T()){//1.产生一个节点:Node* newnode = new ListNode<T>(x);//2.连接!Node* next = pos._node->next;pos._node->next = newnode;newnode->prev = pos._node;newnode->next = next;next->prev = newnode;return newnode;}

2.push_front && push_back

	void push_back(T x = T()){insert(head->prev, x);}void push_front(T x = T()){insert(head, x);}

3.删

1.erase

在这里插入图片描述

//2.删除考虑返回一下下一个位置的迭代器:iterator erase(iterator pos){Node* prev = pos._node->prev;Node* next = pos._node->next;prev->next = next;next->prev = prev;//1.使用默认生成的析构函数delete pos._node;return next;}

2.pop_front && pop_back

void pop_back(){erase(head->prev);}void pop_front(){erase(head->next);}

4.查

1.find

iterator find(T x){iterator cur = begin();while (cur != end()){if (cur._node->date == x)return cur;cur = cur._node->next;//单参数构造函数支持的隐式类型转换!}return nullptr;}

5.改:

2.amend

//修改数据:void amend(iterator pos,T x){pos._node->date = x;}

6.析构函数:

在这里插入图片描述

1.clear 和 ~list

1.清除所有的节点数据会保留头节点。
2.使用clear后的状态应该满足只有一个哨兵位的头节点并且前驱指向自己后继指向自己。

//4.遍历链表清理节点:void clear(){Node* cur = head->next;while (cur != head){Node* next = cur->next;delete cur;cur = next;}head->next = head;head->prev = head;}//析构:~list(){clear();delete head;}

7.容量相关的函数:

1.size()

//容量相关:size_t size(){assert(head != nullptr);int count = 0;if (empty())return 0;else{iterator cur = begin();while (cur != end()){count++;cur = cur._node->next;//单参数构造函数支持的隐式类型转换!}return count;}}

2.empty()

bool empty(){assert(head != nullptr);if (head->next == head)return true;return false;}

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

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

相关文章

py的函数多返回值

前言:之前我们学过了py中函数&#xff0c;这一章我们来学习它的进阶版 目录 一.函数的多返回值 1.1关于函数的多返回值 1.2举例 二.函数多种传参方式 2.1关于多种传参方式 2.2关键字参数 2.2缺省参数 2.3不定长参数 2.4小结 三.匿名函数 3.1关于函数如何作为参数进行…

android 自定义八边形进度条

自定义八边形动画效果图如下 绘制步骤&#xff1a; 1.先绘制橙色底部八边形实心 2.黑色画笔绘制第二层&#xff0c;让最外层显示一条线条宽度即可 3.再用黄色画笔绘制黄色部分 4.使用渐变画笔根据当前进度绘制覆盖黄色部分 5.使用黑色画笔根据当前进度绘制刻度条 6.黑色画笔绘制…

使用Sqoop的并行处理:扩展数据传输

使用Sqoop的并行处理是在大数据环境中高效传输数据的关键。它可以显著减少数据传输的时间&#xff0c;并充分利用集群资源。本文将深入探讨Sqoop的并行处理能力&#xff0c;提供详细的示例代码&#xff0c;以帮助大家更全面地了解和应用这一技术。 Sqoop的并行处理 在开始介绍…

Java网络编程:概述--快速入门

I. 介绍 1.1 什么是网络编程 - 网络编程是指通过计算机网络实现程序之间的通信。在Java中&#xff0c;网络编程通常涉及到数据的传输、通信协议的使用以及与网络相关的各种操作。 1.2. 为什么学习Java网络编程 - Java网络编程是Java开发者重要的技能之一&#xff0c;因为它允许…

mybatis----小细节

1、起别名 在MyBatis中&#xff0c;<typeAliases>元素用于定义类型别名&#xff0c;它可以将Java类名映射为一个更简短的别名&#xff0c;这样在映射文件中可以直接使用别名而不需要完整的类名。 下面是一个示例&#xff1a; 在mybatis核心配置文件中配置typeAliases标…

SSH隧道技术

SSH隧道 简介 SSH隧道是一种通过SSH协议在两个网络节点之间建立安全通信的技术。它可以用于多种用途&#xff0c;包括加密和保护敏感数据传输、绕过防火墙限制、远程访问内部服务等。 应用&#xff1a; 端口转发&#xff1a;SSH隧道可以将本地端口转发到远程主机上&#xf…

合并K个升序链表(LeetCode 23)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路方法一&#xff1a;顺序合并方法二&#xff1a;分治合并方法三&#xff1a;使用优先队列合并 参考文献 1.问题描述 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff…

Python——基本语法(二)

一、while 循环 语法&#xff1a; while 条件表达式:条件表达示为真&#xff0c;就执⾏这⾥的代码&#xff0c;必须缩进 4 个空格多⾏代码保持缩进⼀致 条件表达式可以是: True # 布尔值的 True 1 < 10 # 凡是在 if 语句中使⽤的判断表达示&#xff0c;这⾥都可以使…

【Java实战项目】基于ssm的流浪动物领养系统网站

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

【音视频原理】图像相关概念 ② ( 帧率 | 常见帧率标准 | 码率 | 码率单位 )

文章目录 一、帧率1、帧率简介2、常见帧率标准3、帧率 刷新率 二、码率1、码率简介2、码率单位 一、帧率 1、帧率简介 帧率 Frame Rate , 帧 指的是 是 画面帧 , 帧率 是 画面帧 的 速率 ; 帧率 的 单位是 FPS , Frames Per Second , 是 每秒钟 的 画面帧 个数 ; 帧率 是 动画…

漫漫数学之旅006

文章目录 经典格言数学习题古今评注名人小传 - 格洛里亚斯泰纳姆经典格言 数学上有才华的人没有在历史或英语上有才华的人那么多。——格洛里亚斯泰纳姆(Gloria Steinem) 数学习题 求阴影部分的面积。 古今评注 查尔斯巴贝奇,这位19世纪的英国数学家、发明家和机械工程…

相机内外参标定综合

相机内外参标定 内外参标定常用的工具相机成像原理内外参标定数学原理1&#xff09;求解内参矩阵与外参矩阵的积2&#xff09;求解内参矩阵3&#xff09;求解外参矩阵 内外参标定常用的工具 如图所示&#xff0c;棋盘格是很常见使用的标定工具 左下角写着棋盘格的参数&#xf…

Qt绘画的使用

1. 绘图 绘图组件&#xff1a; 1、绘画对象 2、绘画位置 3、绘画工具 4、绘画时机 绘画时机&#xff1a; 当整个窗口或窗口的一部分需要重新绘制时&#xff0c;会调用绘制事件处理函数 void QWidget::paintEvent(QPaintEvent *event) 绘画对象&#xff1a; QPainter类&#xff…

群晖Drive搭建云同步服务器结合内网穿透实现Obsidian笔记文件远程多端同步

文章目录 一、简介软件特色演示&#xff1a; 二、使用免费群晖虚拟机搭建群晖Synology Drive服务&#xff0c;实现局域网同步1 安装并设置Synology Drive套件2 局域网内同步文件测试 三、内网穿透群晖Synology Drive&#xff0c;实现异地多端同步Windows 安装 Cpolar步骤&#…

使用内网穿透解决电信无公网IP难题,神卓互联

事情经过 事情是这样的&#xff0c;由于客户的单位通了电信宽带&#xff0c;然后采购了我们的ERP系统安装在单位的服务器上&#xff0c;在单位的时候可以通过输入服务器的局域网Ip地址访问&#xff0c;也就是192.168.2.1xx这样的地址&#xff0c;访问确实没有问题&#xff0c;…

【漏洞复现】Sentinel Dashboard默认弱口令漏洞

Nx01 产品简介 Sentinel Dashboard是一个轻量级的开源控制台&#xff0c;提供机器发现以及健康情况管理、监控、规则管理和推送的功能。它还提供了详细的被保护资源的实际访问统计情况&#xff0c;以及为不同服务配置的限流规则。 Nx02 漏洞描述 Sentinel Dashboard存在默认弱…

墙地砖外形检测的技术方案-外部轮廓检测算法

Ramer算法 利用Canny算子得到墙地砖轮廓后&#xff0c;必须进一步将轮廓线精确分段成墙地砖的四条边&#xff0c;从而可得到墙地砖轮廓尺寸、边直度和直角度指标。采用如下算法实现&#xff1a; 第1&#xff0c;选择较高阈值&#xff0c;利用ramer算法将轮廓线用多边形&#…

软件测试|Python 用户输入和字符串格式化

简介 在 Python 中&#xff0c;用户输入和字符串格式化是编程中常见的任务之一。用户输入使我们能够与用户交互&#xff0c;而字符串格式化帮助我们创建美观的输出。本文将介绍如何在 Python 中执行这些任务&#xff0c;并提供详细示例。 用户输入 在 Python 中&#xff0c;…

[论文阅读]DeepFusion

DeepFusion Lidar-Camera Deep Fusion for Multi-Modal 3D Object Detection 用于多模态 3D 物体检测的激光雷达相机深度融合 论文网址&#xff1a;DeepFusion 论文代码&#xff1a;DeepFusion 摘要 激光雷达和摄像头是关键传感器&#xff0c;可为自动驾驶中的 3D 检测提供补…

多输入多输出 | Matlab实现PSO-CNN粒子群优化卷积神经网络多输入多输出预测

多输入多输出 | Matlab实现PSO-CNN粒子群优化卷积神经网络多输入多输出预测 目录 多输入多输出 | Matlab实现PSO-CNN粒子群优化卷积神经网络多输入多输出预测预测效果基本介绍模型背景程序设计参考资料 预测效果 基本介绍 Matlab实现PSO-CNN粒子群优化卷积神经网络多输入多输出…