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

【C++精华铺】12.STL list模拟实现

1.序言

        STL (Standard Template Library)是C++标准库中的一个重要组件,提供了许多通用的数据结构和算法。其中,STL list是一种带头双向链表容器,可以存储任意类型的元素。

list的特点包括:

  1. 双向性:list中的元素可以根据需要在前向和后向方向上进行遍历和访问。

  2. 动态大小:list的大小可以根据需要动态增长和收缩,不像数组需要预先定义大小。

  3. 高效的插入和删除:在list中插入或删除元素的操作非常高效,时间复杂度为常数时间。

  4. 不支持随机访问:由于list的实现是基于链表的,所以不支持随机访问,只能通过遍历来访问指定位置的元素。

list提供了一系列的成员函数来操作元素,包括:

  1. push_back()和push_front():分别在list的尾部和头部插入一个元素。

  2. pop_back()和pop_front():分别删除list的尾部和头部的元素。

  3. insert():在指定位置插入一个或多个元素。

  4. erase():删除指定位置的一个或多个元素。

  5. size():返回list中元素的个数。

  6. empty():判断list是否为空。

        值得注意的是,由于list是双向链表,所以在内存上的开销相对较大,而且无法通过下标直接访问元素。因此,在选择容器时需要根据实际需求进行权衡。

2.list整体结构

template<class T>
struct list_node
{list_node<T>* _next;list_node<T>* _prev;T _Data;list_node(const T& x = T()):_next(nullptr), _prev(nullptr), _Data(x){}
};template<class T,class Ref,class Ptr>
struct __list_iterator
{typedef list_node<T> node;typedef __list_iterator<T, Ref, Ptr> iterator;     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;//······
private:node* _head;};

3.list迭代器

3.1 operator*()

        operator*() 返回的是list某节点存储的数据,并且返回时要能修改数据,所以返回类型是T&(Ref:是个模板参数,兼顾 T& 和 const T &,用哪个传那个 )。

Ref operator*()
{return _node->_Data;
}

3.2 operator->()

        operator->() 用于取list存储的数据对象里面的属性,也是模拟指针的行为,返回数据对象的地址。

Ptr operator->()
{return &_node->_Data;
}

        需要注意的是如果我们使用这个 -> 的运算符重载,假设一迭代器对象 it :it.operator->()->(某属性) 等价于 it->->(某属性) ,这里实际上有俩个 -> ,为了增加代码的可读性,这里进行了特殊处理,优化成了一个 -> :it->(某属性) 。

3.3 operator++() 和 operator++(int)、operator--() 和 operator--(int)

        operator++()(operator--())是前置++(--),返回++(--)后的值,operator++(int)(operator--())是后置++(--),返回++前的值(--)。

iterator& operator++()
{_node = _node->_next;return *this;
}
iterator operator++(int)
{ iterator tmp(*this);_node = _node->_next;return tmp;
}
iterator& operator--()
{_node = _node->_prev;return *this;
}
iterator operator--(int)
{iterator tmp(*this);_node = _node->_prev;return tmp;
}

 3.4 operator==() 和 operator!=()

bool operator==(const iterator& it)
{return _node == it._node;
}
bool operator!=(const iterator& it)
{return _node != it._node;
}

3.5 迭代器完整代码

template<class T>
struct list_node
{
list_node<T>* _next;
list_node<T>* _prev;
T _Data;
list_node(const T& x = T()):_next(nullptr), _prev(nullptr), _Data(x)
{}
};template<class T,class Ref,class Ptr>
struct __list_iterator
{
typedef list_node<T> node;
typedef __list_iterator<T, Ref, Ptr> iterator;
__list_iterator(node* n):_node(n)
{}
Ref operator*()
{return _node->_Data;
}
Ptr operator->()
{return &_node->_Data;
}iterator& operator++()
{_node = _node->_next;return *this;
}
iterator operator++(int)
{ iterator tmp(*this);_node = _node->_next;return tmp;
}
iterator& operator--()
{_node = _node->_prev;return *this;
}
iterator operator--(int)
{iterator tmp(*this);_node = _node->_prev;return tmp;
}bool operator==(const iterator& it)
{return _node == it._node;
}
bool operator!=(const iterator& it)
{return _node != it._node;
}
node* _node; 
};

4.list接口

4.1构造函数

list()
{_head = new node;_head->_next = _head->_prev = _head;
}~list()
{while (end() != _head){erase(end());}delete _head;_head = nullptr;
}
template<class Iterator>
list(Iterator first, Iterator last)
{_head = new node;_head->_next = _head->_prev = _head;while (first != last){push_back(*first);first++;}
}void swap(list<T>& tmp)
{std::swap(_head, tmp._head);
}list(const list<T>& l)
{_head = new node;_head->_next = _head->_prev = _head;list<T> tmp(l.begin(), l.end());swap(tmp);
}

4.2 push_back() push_front() pop_back() pop_front()

void push_back(const T& x)
{node* tail = _head->_prev;node* newnode = new node(x);newnode->_prev = tail;newnode->_next = tail->_next;tail->_next = newnode;_head->_prev = newnode;
}void push_front(const T& x)
{node* head = _head->_next;node* newnode = new node(x);newnode->_prev = _head;newnode->_next = head;_head->_next = newnode;head->_prev = newnode;}
void pop_back()
{node* tail = _head->_prev;_head->_prev = tail->_prev;tail->_prev->_next = _head;delete tail;
}
void pop_front()
{node* head = _head->_next;_head->_next = head->_next;head->_next->_prev = _head;delete head;
}

 4.3迭代器

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

 4.4 insert() 和 erase()

        注意erase的迭代器失效,需要更新pos

void insert(iterator pos, const T& x)
{node* cur = pos._node;node* newnode = new node(x);newnode->_next = cur;newnode->_prev = cur->_prev;cur->_prev->_next = newnode;cur->_prev = newnode;
}iterator erase(iterator pos)
{assert(pos != end());node* prev = pos._node->_prev;node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;return iterator(next);
}

5. list完整代码

#pragma once
#include<iostream>
#include<assert.h>
using namespace std; 
namespace zy
{template<class T>struct list_node{list_node<T>* _next;list_node<T>* _prev;T _Data;list_node(const T& x = T()):_next(nullptr), _prev(nullptr), _Data(x){}};template<class T,class Ref,class Ptr>struct __list_iterator{typedef list_node<T> node;typedef __list_iterator<T, Ref, Ptr> iterator;__list_iterator(node* n):_node(n){}Ref operator*(){return _node->_Data;}Ptr operator->(){return &_node->_Data;}iterator& operator++(){_node = _node->_next;return *this;}iterator operator++(int){ iterator tmp(*this);_node = _node->_next;return tmp;}iterator& operator--(){_node = _node->_prev;return *this;}iterator operator--(int){iterator tmp(*this);_node = _node->_prev;return tmp;}bool operator==(const iterator& it){return _node == it._node;}bool operator!=(const iterator& it){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;list(){_head = new node;_head->_next = _head->_prev = _head;}~list(){while (end() != _head){erase(end());}delete _head;_head = nullptr;}template<class Iterator>list(Iterator first, Iterator last){_head = new node;_head->_next = _head->_prev = _head;while (first != last){push_back(*first);first++;}}void swap(list<T>& tmp){std::swap(_head, tmp._head);}list(const list<T>& l){_head = new node;_head->_next = _head->_prev = _head;list<T> tmp(l.begin(), l.end());swap(tmp);}list<T>& operator=(list<T> lt){swap(lt);return *this;}void push_back(const T& x){node* tail = _head->_prev;node* newnode = new node(x);newnode->_prev = tail;newnode->_next = tail->_next;tail->_next = newnode;_head->_prev = newnode;}void push_front(const T& x){node* head = _head->_next;node* newnode = new node(x);newnode->_prev = _head;newnode->_next = head;_head->_next = newnode;head->_prev = newnode;}void pop_back(){node* tail = _head->_prev;_head->_prev = tail->_prev;tail->_prev->_next = _head;delete tail;}void pop_front(){node* head = _head->_next;_head->_next = head->_next;head->_next->_prev = _head;delete head;}iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator begin() const{return iterator(_head->_next);}const_iterator end() const{return iterator(_head);}void insert(iterator pos, const T& x){node* cur = pos._node;node* newnode = new node(x);newnode->_next = cur;newnode->_prev = cur->_prev;cur->_prev->_next = newnode;cur->_prev = newnode;}iterator erase(iterator pos){assert(pos != end());node* prev = pos._node->_prev;node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;return iterator(next);}private:node* _head;};
}

相关文章:

【C++精华铺】12.STL list模拟实现

1.序言 STL (Standard Template Library)是C标准库中的一个重要组件&#xff0c;提供了许多通用的数据结构和算法。其中&#xff0c;STL list是一种带头双向链表容器&#xff0c;可以存储任意类型的元素。 list的特点包括&#xff1a; 双向性&#xff1a;list中的元素可以根据需…...

ChatGPT Mac App 发布!

2024 年 6 月&#xff0c;OpenAI 的大语言模型 ChatGPT 的 Mac 客户端与 ChatGPT-4o 一起发布了。ChatGPT Mac 户端可以让用户直接在 Mac 电脑上使用 ChatGPT 进行对话。它提供了一个简单易用的用户界面&#xff0c;用户可以在其中输入文本或语音指令&#xff0c;并接收模型生成…...

ACE之ACE_Time_Value

简介 ACE_Time_Value在ACE中表示时间&#xff0c;集成不同平台的时间 结构 #mermaid-svg-dGoKn1R7GicabUif {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-dGoKn1R7GicabUif .error-icon{fill:#552222;}#mermaid-…...

[论文笔记] 自对齐指令反翻译:SELF-ALIGNMENT WITH INSTRUCTION BACKTRANSLATION

https://arxiv.org/pdf/2308.06259 这篇论文介绍了一种名为“指令反向翻译”(instruction backtranslation)的方法,用于通过自动标记人类书写的文本和相应的指令来构建高质量的指令跟随语言模型。这里是一个通俗易懂的解释: 一、背景 通常,训练一个高质量的指令跟随语言…...

算术运算符. 二

# 表达式 # 操作数和运算符组成 比如 11 # 作用&#xff1a;表达式可以求值&#xff0c;也可以给变量赋值。 # Python算术运算符&#xff1a; # - * / % //&#xff08;整除:向下取整&#xff09; ** print(10 4) # 14 print(10 - 4) # 6 print(10 * 4) # 40 …...

代码优化方法记录

每次代码 review 之后&#xff0c;对 review 的情况进行总结记录&#xff0c;产出实际经验&#xff0c;方便组内学习、分享。 1、提取公共内容 公共内容要提取&#xff0c;避免重复编写&#xff1b; 2、css 色值使用变量 css 中的色值、字体&#xff0c;都换成组件库中的变…...

qt 图形、图像、3D相关知识

1.qt 支持3d吗 Qt确实支持3D图形渲染。Qt 3D模块是Qt的一个组成部分&#xff0c;它允许开发者在Qt应用程序中集成3D内容。Qt 3D模块提供了一组类和函数&#xff0c;用于创建和渲染3D场景、处理3D对象、应用光照和纹理等。 Qt 3D模块包括以下几个主要组件&#xff1a; Qt 3D …...

【逆向基础】十、工具分享之DIE(Detect It Easy)

一、简介 DIE&#xff08;Detect It Easy&#xff09;是一款可以轻松检测PE文件的程序&#xff1b;其主要作用是查壳&#xff0c;并将pe文件的内容解析出来&#xff0c;包括PE文件中包含的导入函数、导出函数的名称及地址&#xff0c;入口函数地址等&#xff0c;是技术人员分析…...

Netcat:——网络瑞士军刀

Netcat: 网络瑞士军刀 概述 Netcat&#xff08;通常称为 nc&#xff09;是一个功能强大的网络工具&#xff0c;广泛用于网络测试和调试。它能够读取和写入网络数据&#xff0c;支持TCP、UDP协议&#xff0c;可以用于端口扫描、端口监听、文件传输等多种用途。 主要用途 获取…...

C++ //练习 14.50 在初始化ex1和ex2的过程中,可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因。

C Primer&#xff08;第5版&#xff09; 练习 14.50 练习 14.50 在初始化ex1和ex2的过程中&#xff0c;可能用到哪些类类型的转换序列呢&#xff1f;说明初始化是否正确并解释原因。 struct LongDouble{LongDouble(double 0.0);operator double();operator float(); }; Long…...

【开源 Mac 工具推荐之 1】gibMacOS:方便快捷的 macOS 完整包下载 Shell 工具

简介 gibMacOS 是由 GitHub 开发者 corpnewt 编写的一款 Shell 工具。它采用 Python 编程语言&#xff0c;可以让用户打开后在纯文本页面中轻松选择并下载来源于 Apple 官方的 macOS 完整安装包。 Repo 地址&#xff1a;https://github.com/corpnewt/gibMacOS &#xff08;其…...

pdf文件如何快速英文转中文?

要将 PDF 文件中的英文内容转换为中文&#xff0c;你可以使用以下几种方法&#xff1a; 1、在线翻译工具&#xff1a; 使用网上的免费在线翻译工具&#xff0c;如Google翻译、百度翻译或有道翻译&#xff0c;将整个 PDF 文档粘贴到工具中进行翻译。 2、专业翻译软件&#xf…...

程序的控制结构——if-else语句(双分支结构)【互三互三】

目录 &#x1f341; 引言 &#x1f341;if-else语句&#xff08;双分支结构&#xff09; &#x1f449;格式1&#xff1a; &#x1f449;功能&#xff1a; &#x1f449;程序设计风格提示&#xff1a; &#x1f449;例题 &#x1f449;格式2&#xff1a; &#x1f449;…...

[C++]初识C++(命名空间,命名空间使用,函数重载,缺省参数等)

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…...

每天一个数据分析题(四百十六)- 线性回归模型

根据模型假设&#xff0c;线性回归模型中误差项的方差为 A. 常数 B. 函数 C. 随机变量 D. 以上都不是 数据分析认证考试介绍&#xff1a;点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专项练习题库 内容涵盖Python&#xff0c;SQL&#xff0c;统计学&#…...

JupyterNotebook中导出当前环境,并存储为requirements.txt

​使用Anaconda管理Python环境时&#xff0c;可以轻松地导出环境配置&#xff0c;以便在其他机器或环境中重新创建相同的环境。可以通过生成一个environment.yml文件实现的&#xff0c;该文件包含了环境中安装的所有包及其版本。但是&#xff0c;常常在一些课程中JupyterNotebo…...

Java对象复制系列二: 手把手带你写一个Apache BeanUtils

&#x1f446;&#x1f3fb;&#x1f446;&#x1f3fb;&#x1f446;&#x1f3fb;关注博主&#xff0c;让你的代码变得更加优雅。 前言 Apache BeanUtils 是Java中用来复制2个对象属性的一个类型。 上一篇文章我们讲到了 Apache BeanUtils 性能相对比较差&#xff0c;今天…...

一个极简的 Vue 示例

https://andi.cn/page/621516.html...

修复 Ubuntu 24.04 Dock 丢失应用程序图标

找出应用程序窗口的类名 首先&#xff0c;您需要启动应用程序窗口。然后&#xff0c;按 Alt F2 启动“运行 Command”对话框。当对话框打开时&#xff0c;输入 lg 并按 Enter 键。 在该窗口中&#xff0c;单击Windows按钮&#xff0c;然后找出目标应用程序窗口的类名称。 在/…...

idea MarketPlace插件找不到

一、背景 好久没用idea了&#xff0c;打开项目后没有lombok&#xff0c;安装lombok插件时发现idea MarketPlace插件市场找不到&#xff0c;需要重新配置代理源&#xff0c;在外网访问时通过代理服务进行连接 二、操作 ### File-->setting 快捷键 Ctrl Alt S 远端源地…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...