当前位置: 首页 > news >正文

从零开始手写STL库:List

从零开始手写STL库–List部分

Github链接:miniSTL


文章目录

  • 从零开始手写STL库–List部分
  • List是什么?
  • List需要包含什么函数
          • 1)基础成员函数
          • 2)核心功能
          • 3)其他功能
  • 基础成员函数的编写
  • 核心功能的编写
  • 其他功能编写
  • 总结


List是什么?

std::list是基于双向链表的的数据结构,与std::vector基于数组不同,list在频繁插入和删除的场景中更适合应用。

List需要包含什么函数

应当具有:

1)基础成员函数

构造函数:初始化List头节点
析构函数:释放内存,当运行结束后要摧毁这个List防止内存泄漏
不同于Vector,List这种以链表为基础的容器一般不需要去拷贝新的List,也就不用手动构建拷贝构造函数和拷贝赋值操作符

2)核心功能

push_back/push_front:在List的末尾/头部加入新元素
pop_back/pop_front:移除List末尾/头部元素
size:获取List长度
clear:清空List
get:获取List中某个元素的值
remove:删除某个节点
find:查找某个值对应的节点
empty:检查List是否为空

3)其他功能

迭代器、重载输出符等等

基础成员函数的编写

List的成员:
List本身是链表,那么每个节点应该包括本节点的数据、指向上/下一个节点的指针,而List是描述这一系列节点构成的双向链表,那么只需要记录头节点、尾节点以及List长度即可

template<typename T>
class myList
{
private:struct Node{T data;Node * next;Node * prev;Node(const T & data_, Node * next_ = nullptr, Node * prev_ = nullptr): data(data_), next(next_), prev(prev_) {} };Node * head;Node * tail;size_t current_size;
public:};

构造函数和析构函数就是

public:myList() : head(nullptr), tail(nullptr), current_size(0) {}~myList() {clear(); }

再次提示,这里的构造函数用current_size(0) 初始化才是合规的,放在中括号内会浪费掉这个初始化进程

析构函数调用一下清空函数即可

核心功能的编写

1、push_back/push_front函数:在List的末尾/头部加入新元素
链表不像动态数组需要考虑分配问题,所以直接加就行了

但是也需要判断List为空的清空,如果为空,head/tail是没法取出next指针的,此时就会报错

所以在push的时候检查一下

(在力扣算法题中避免这种复杂操作的方法是构建一个虚拟头节点,就可以统一处理)

    void push_back(const T & value){Node * temp = new Node(value, nullptr, tail);if(tail) tail->next = temp;else head = temp;tail = temp;current_size ++;}void push_front(const T & value){Node * temp = new Node(value, head, nullptr);if(head) head->prev = temp;else tail = temp;head = temp;current_size ++;}

2、pop_back/pop_front函数:移除List末尾/头部元素
头尾节点的删除较为简单,注意一下空列表的情况特殊处理即可

    void pop_back(){if(current_size > 0){Node * temp = tail->prev;delete tail;tail = temp;if(tail) tail->next = nullptr;else head = nullptr;current_size --;}}void pop_front(){if(current_size > 0){Node * temp = head->next;delete head;head = temp;if(head) head->prev = nullptr;else tail = nullptr;current_size --;}}

这里如果删除之后发现头/尾节点是空了,说明这个List已经空了,但是另一端还没处理,所以要让另一端也为nullptr,否则有可能发生指针越界问题。

3、size函数:获取List长度

    int size(){return current_size;}

4、clear函数:清空List
不同于vector那样直接将size归零,List需要考虑节点占用的内存,所以实际上是需要循环释放的

void clear()    
{        while (head)         {             Node * temp = head;head = head->next;             delete temp;            }         tail = nullptr;         current_size = 0;              
}

5、get函数:获取List中某个元素的值
这里的实现方法不是给定一个get函数,而是重载符号“[]”,这样就能更加方便地访问了

    T &operator[](size_t index){Node * curr = head;for(size_t i = 0; i < index; i ++){if(!curr) throw std::out_of_range("Index out of range!");curr = curr->next;}return curr->data;}const T & operator[](size_t index) const{Node * curr = head;for(size_t i = 0; i < index; i ++){if(!curr) throw std::out_of_range("Index out of range!");curr = curr->next;}return curr->data;}

这里返回值设置为引用是考虑到一下情况

myList testList;
testList[2] = 4;

如果返回的不是引用,那么这样的赋值就会失效,并不能真的修改掉List的节点元素

6、remove函数:删除某个节点
那么这里需要查找到该节点,再进行删除,而且需要注意它是头尾节点时的情况

    void remove(const T & val){Node * temp = head;while (temp && temp->data != val){temp = temp->next;}if(!temp) return;if(temp != head && temp != tail){temp->prev->next = temp->next;temp->next->prev = temp->prev;}else if(temp == head && temp == tail){head = nullptr;tail = nullptr;}else if(temp == head){head = temp->next;head->prev = nullptr;}else{tail = temp->prev;tail->next = nullptr;}current_size --;delete temp;temp = nullptr;}

7、find函数:查找某个值对应的节点
循环遍历对比就行

    Node * getNode(const T & val){Node * node = head;while (node && node->data != val){node = node->next;}return node;}T *find(const T &val){Node * node = getNode(val);if(!node) return nullptr;return & node->data;}

8、empty函数:检查List是否为空

    bool empty(){return current_size == 0;}

其他功能编写

迭代器

    Node * begin() { return head; }Node * end() { return nullptr; }const Node * begin() const { return head; }const Node * end() const { return nullptr; }

重载<<符号

template <typename T>
std::ostream &operator<<(std::ostream &os, myList<T> &pt)
{for (auto current = pt.begin(); current; current = current->next){os << " " << current->data;}os << std::endl;return os;
}

总结

List的编写中,难点在于考虑链表为空的情况,很多个函数都需要去考虑,并且处理头尾节点,实际上是个细致的工作,并不在于思路上有多难。

在经常增删的情况下,用List会比Vector更为合适,代价是内存用得比较多,空间换时间。

相关文章:

从零开始手写STL库:List

从零开始手写STL库–List部分 Github链接&#xff1a;miniSTL 文章目录 从零开始手写STL库–List部分List是什么&#xff1f;List需要包含什么函数1&#xff09;基础成员函数2&#xff09;核心功能3)其他功能 基础成员函数的编写核心功能的编写其他功能编写总结 List是什么&am…...

蒙特卡洛采样

目录 蒙特卡洛采样的计算逻辑计算步骤:1. 定义问题2. 确定采样范围3. 生成随机样本点4. 计算函数值5. 估计期望值或积分值6. 计算误差具体示例:1. 定义问题2. 确定采样范围3. 生成随机样本点4. 计算函数值5. 估计积分值6. 计算误差总结蒙特卡洛采样是一种通过随机生成样本点来…...

Apache虚拟主机VirtualHost配置项详解

在Apache中,VirtualHost容器用于定义一个虚拟主机的配置,它允许在单一的物理服务器上托管多个不同的网站,每个网站可以有自己的域名、文档根目录、错误日志等。VirtualHost内的配置项非常灵活,可以包含从基本的网站信息到高级的URL重写和安全设置。 以下是一些常见的Virtu…...

OpenAI从GPT-4V到GPT-4O,再到GPT-4OMini简介

OpenAI从GPT-4V到GPT-4O&#xff0c;再到GPT-4OMini简介 一、引言 在人工智能领域&#xff0c;OpenAI的GPT系列模型一直是自然语言处理的标杆。随着技术的不断进步&#xff0c;OpenAI推出了多个版本的GPT模型&#xff0c;包括视觉增强的GPT-4V&#xff08;GPT-4 with Vision&…...

从人工巡检到智能防控:智慧油气田安全生产的新视角

一、背景需求 随着科技的飞速发展&#xff0c;视频监控技术已成为各行各业保障安全生产、提升管理效率的重要手段。特别是在油气田这一特殊领域&#xff0c;由于其工作环境复杂、安全风险高&#xff0c;传统的监控方式已难以满足实际需求。因此&#xff0c;基于视频监控AI智能…...

【黑马java基础】Lamda, 方法引用,集合{Collection(List, Set), Map},Stream流

文章目录 JDK8新特性&#xff1a;Lambda表达式认识Lambda表达式Lambda表达式的省略规则 JDK8新特性&#xff1a;方法引用静态方法的引用实例方法的引用特定类型方法的引用构造器的应用 集合➡️Collection单列集合体系Collection的常用方法Collection的遍历方法迭代器增强for循…...

Stable Diffusion 使用详解(1)---- 提示词及相关参数

目录 背景 提示词 内容提示词 人物及主体特征 场景 环境光照 画幅视角 注意事项及示例 标准化提示词 画质等级 风格与真实性 具体要求 背景处理 光线与色彩 负向提示词 小结 常用工具 另外几个相关参数 迭代步数 宽度与高度 提示词引导系数 图片数量 背景…...

数据结构和算法(刷题) - 无序数组排序后的最大相邻差

无序数组排序后的最大相邻差 问题&#xff1a;一个无序的整型数组&#xff0c;求出该数组排序后的任意两个相邻元素的最大差值&#xff1f;要求时间和空间复杂度尽可能低。 三种方法&#xff1a; 排序后计算比较 简介&#xff1a;用任意一种时间复杂度为 O ( n log ⁡ n ) O…...

HOW - React 处理不紧急的更新和渲染

目录 useDeferredValueuseTransitionuseIdleCallback 在 React 中&#xff0c;有一些钩子函数可以帮助你处理不紧急的更新或渲染&#xff0c;从而优化性能和用户体验。 以下是一些常用的相关钩子及其应用场景&#xff1a; useDeferredValue 用途&#xff1a;用于处理高优先级…...

基于A律压缩的PCM脉冲编码调制通信系统simulink建模与仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1A律压缩的原理 4.2 PCM编码过程 4.3 量化噪声与信噪比 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#…...

【入门教程一】基于DE2-115的My First FPGA 工程

1.1. 概述 这是一个简单的练习&#xff0c; 可以帮助初学者开始了解如何使用Intel Quartus 软件进行 FPGA 开发。 在本章节中&#xff0c;您将学习如何编译 Verilog 代码&#xff0c;进行引脚分配&#xff0c;创建时序约束&#xff0c;然后对 FPGA 进行编程&#xff0c;驱动开…...

mysql中的索引和分区

目录 1.编写目的 2.索引 2.1 创建方法 2.2 最佳适用 2.3 索引相关语句 3.分区 3.1 创建方法 3.2 最佳适用 Welcome to Code Blocks blog 本篇文章主要介绍了 [Mysql中的分区和索引] ❤博主广交技术好友&#xff0c;喜欢文章的可以关注一下❤ 1.编写目的 在MySQL中&…...

项目实战--C#实现图书馆信息管理系统

本项目是要开发一个图书馆管理系统&#xff0c;通过这个系统处理常见的图书馆业务。这个系统主要功能是&#xff1a;&#xff08;1&#xff09;有客户端&#xff08;借阅者使用&#xff09;和管理端&#xff08;图书馆管理员和系统管理员使用&#xff09;。&#xff08;2&#…...

信号【Linux】

文章目录 信号处理方式&#xff08;信号递达&#xff09;前后台进程 终端按键产生信号kill系统调用接口向进程发信号阻塞信号sigset_tsigprocmasksigpending内核态与用户态&#xff1a;内核空间与用户空间内核如何实现信号的捕捉 1、信号就算没有产生&#xff0c;进程也必须识别…...

Kafka Producer之ACKS应答机制

文章目录 1. 应答机制2. 等级03. 等级14. 等级all5. 设置等级6. ISR 1. 应答机制 异步发送的效率高&#xff0c;但是不安全&#xff0c;同步发送安全&#xff0c;但是效率低。 无论哪一种&#xff0c;有一个关键的步骤叫做回调&#xff0c;也就是ACKS应答机制。 其中ACKS也分…...

【深入理解SpringCloud微服务】深入理解Eureka核心原理

深入理解Eureka核心原理 Eureka整体设计Eureka服务端启动Eureka三级缓存Eureka客户端启动 Eureka整体设计 Eureka是一个经典的注册中心&#xff0c;通过http接收客户端的服务发现和服务注册请求&#xff0c;使用内存注册表保存客户端注册上来的实例信息。 Eureka服务端接收的…...

算法——滑动窗口(day7)

904.水果成篮 904. 水果成篮 - 力扣&#xff08;LeetCode&#xff09; 题目解析&#xff1a; 根据题意我们可以看出给了我们两个篮子说明我们在开始采摘到结束的过程中只能有两种水果的种类&#xff0c;又要求让我们返回收集水果的最大数目&#xff0c;这不难让我们联想到题目…...

Django学习第一天(如何创建和运行app)

前置知识&#xff1a; URL组成部分详解&#xff1a; 一个url由以下几部分组成&#xff1a; scheme&#xff1a;//host:port/path/?query-stringxxx#anchor scheme:代表的是访问的协议&#xff0c;一般为http或者ftp等 host&#xff1a;主机名&#xff0c;域名&#xff0c;…...

VScode连接虚拟机运行Python文件的方法

声明&#xff1a;本文使用Linux发行版本为rocky_9.4 目录 1. 在rocky_9.4最小安装的系统中&#xff0c;默认是没有tar工具的&#xff0c;因此&#xff0c;要先下载tar工具 2. 在安装好的vscode中下载ssh远程插件工具 3. 然后连接虚拟机 4. 查看python是否已经安装 5. 下载…...

通义千问AI模型对接飞书机器人-模型配置(2-1)

一 背景 根据业务或者使用场景搭建自定义的智能ai模型机器人&#xff0c;可以较少我们人工回答的沟通成本&#xff0c;而且可以更加便捷的了解业务需求给出大家设定的业务范围的回答&#xff0c;目前基于阿里云的通义千问模型研究。 二 模型研究 参考阿里云帮助文档&#xf…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...