【C++精华铺】12.STL list模拟实现
1.序言
STL (Standard Template Library)是C++标准库中的一个重要组件,提供了许多通用的数据结构和算法。其中,STL list是一种带头双向链表容器,可以存储任意类型的元素。
list的特点包括:
双向性:list中的元素可以根据需要在前向和后向方向上进行遍历和访问。
动态大小:list的大小可以根据需要动态增长和收缩,不像数组需要预先定义大小。
高效的插入和删除:在list中插入或删除元素的操作非常高效,时间复杂度为常数时间。
不支持随机访问:由于list的实现是基于链表的,所以不支持随机访问,只能通过遍历来访问指定位置的元素。
list提供了一系列的成员函数来操作元素,包括:
push_back()和push_front():分别在list的尾部和头部插入一个元素。
pop_back()和pop_front():分别删除list的尾部和头部的元素。
insert():在指定位置插入一个或多个元素。
erase():删除指定位置的一个或多个元素。
size():返回list中元素的个数。
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标准库中的一个重要组件,提供了许多通用的数据结构和算法。其中,STL list是一种带头双向链表容器,可以存储任意类型的元素。 list的特点包括: 双向性:list中的元素可以根据需…...
ChatGPT Mac App 发布!
2024 年 6 月,OpenAI 的大语言模型 ChatGPT 的 Mac 客户端与 ChatGPT-4o 一起发布了。ChatGPT Mac 户端可以让用户直接在 Mac 电脑上使用 ChatGPT 进行对话。它提供了一个简单易用的用户界面,用户可以在其中输入文本或语音指令,并接收模型生成…...
ACE之ACE_Time_Value
简介 ACE_Time_Value在ACE中表示时间,集成不同平台的时间 结构 #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 # 作用:表达式可以求值,也可以给变量赋值。 # Python算术运算符: # - * / % //(整除:向下取整) ** print(10 4) # 14 print(10 - 4) # 6 print(10 * 4) # 40 …...
代码优化方法记录
每次代码 review 之后,对 review 的情况进行总结记录,产出实际经验,方便组内学习、分享。 1、提取公共内容 公共内容要提取,避免重复编写; 2、css 色值使用变量 css 中的色值、字体,都换成组件库中的变…...
qt 图形、图像、3D相关知识
1.qt 支持3d吗 Qt确实支持3D图形渲染。Qt 3D模块是Qt的一个组成部分,它允许开发者在Qt应用程序中集成3D内容。Qt 3D模块提供了一组类和函数,用于创建和渲染3D场景、处理3D对象、应用光照和纹理等。 Qt 3D模块包括以下几个主要组件: Qt 3D …...
【逆向基础】十、工具分享之DIE(Detect It Easy)
一、简介 DIE(Detect It Easy)是一款可以轻松检测PE文件的程序;其主要作用是查壳,并将pe文件的内容解析出来,包括PE文件中包含的导入函数、导出函数的名称及地址,入口函数地址等,是技术人员分析…...
Netcat:——网络瑞士军刀
Netcat: 网络瑞士军刀 概述 Netcat(通常称为 nc)是一个功能强大的网络工具,广泛用于网络测试和调试。它能够读取和写入网络数据,支持TCP、UDP协议,可以用于端口扫描、端口监听、文件传输等多种用途。 主要用途 获取…...
C++ //练习 14.50 在初始化ex1和ex2的过程中,可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因。
C Primer(第5版) 练习 14.50 练习 14.50 在初始化ex1和ex2的过程中,可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因。 struct LongDouble{LongDouble(double 0.0);operator double();operator float(); }; Long…...
【开源 Mac 工具推荐之 1】gibMacOS:方便快捷的 macOS 完整包下载 Shell 工具
简介 gibMacOS 是由 GitHub 开发者 corpnewt 编写的一款 Shell 工具。它采用 Python 编程语言,可以让用户打开后在纯文本页面中轻松选择并下载来源于 Apple 官方的 macOS 完整安装包。 Repo 地址:https://github.com/corpnewt/gibMacOS (其…...
pdf文件如何快速英文转中文?
要将 PDF 文件中的英文内容转换为中文,你可以使用以下几种方法: 1、在线翻译工具: 使用网上的免费在线翻译工具,如Google翻译、百度翻译或有道翻译,将整个 PDF 文档粘贴到工具中进行翻译。 2、专业翻译软件…...
程序的控制结构——if-else语句(双分支结构)【互三互三】
目录 🍁 引言 🍁if-else语句(双分支结构) 👉格式1: 👉功能: 👉程序设计风格提示: 👉例题 👉格式2: 👉…...
[C++]初识C++(命名空间,命名空间使用,函数重载,缺省参数等)
💖💖💖欢迎来到我的博客,我是anmory💖💖💖 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…...
每天一个数据分析题(四百十六)- 线性回归模型
根据模型假设,线性回归模型中误差项的方差为 A. 常数 B. 函数 C. 随机变量 D. 以上都不是 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专项练习题库 内容涵盖Python,SQL,统计学&#…...
JupyterNotebook中导出当前环境,并存储为requirements.txt
使用Anaconda管理Python环境时,可以轻松地导出环境配置,以便在其他机器或环境中重新创建相同的环境。可以通过生成一个environment.yml文件实现的,该文件包含了环境中安装的所有包及其版本。但是,常常在一些课程中JupyterNotebo…...
Java对象复制系列二: 手把手带你写一个Apache BeanUtils
👆🏻👆🏻👆🏻关注博主,让你的代码变得更加优雅。 前言 Apache BeanUtils 是Java中用来复制2个对象属性的一个类型。 上一篇文章我们讲到了 Apache BeanUtils 性能相对比较差,今天…...
一个极简的 Vue 示例
https://andi.cn/page/621516.html...
修复 Ubuntu 24.04 Dock 丢失应用程序图标
找出应用程序窗口的类名 首先,您需要启动应用程序窗口。然后,按 Alt F2 启动“运行 Command”对话框。当对话框打开时,输入 lg 并按 Enter 键。 在该窗口中,单击Windows按钮,然后找出目标应用程序窗口的类名称。 在/…...
idea MarketPlace插件找不到
一、背景 好久没用idea了,打开项目后没有lombok,安装lombok插件时发现idea MarketPlace插件市场找不到,需要重新配置代理源,在外网访问时通过代理服务进行连接 二、操作 ### File-->setting 快捷键 Ctrl Alt S 远端源地…...
淘宝智能客服Prompt实战:从零构建高效对话系统的关键技术与避坑指南
在电商客服场景中,传统基于规则或简单意图匹配的对话系统长期面临挑战。随着大语言模型(LLM)技术的成熟,基于Prompt工程的智能客服方案为行业带来了新的可能性。本文将深入探讨在淘宝智能客服场景下,如何从零构建一套高…...
5大维度解析MOOTDX:金融数据采集的Python工具革新方案
5大维度解析MOOTDX:金融数据采集的Python工具革新方案 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 金融数据采集是量化投资与金融研究的基础环节,但传统方案往往面临成本…...
MacBook Pro Ubuntu系统WiFi与Touch Bar问题完全解决方案
MacBook Pro Ubuntu系统WiFi与Touch Bar问题完全解决方案 【免费下载链接】T2-Ubuntu 项目地址: https://gitcode.com/gh_mirrors/t2u/T2-Ubuntu 如何精准识别硬件兼容性问题? 在MacBook Pro上安装Ubuntu后,用户常遇到两类硬件功能异常…...
Qwen3-ASR-0.6B在Linux环境下的高效部署方案
Qwen3-ASR-0.6B在Linux环境下的高效部署方案 1. 引言 语音识别技术正在快速改变我们与设备交互的方式,而Qwen3-ASR-0.6B作为一款轻量级但功能强大的语音识别模型,为开发者提供了在Linux服务器上部署高效语音识别服务的新选择。这个模型虽然只有6亿参数…...
Java时间处理全指南:从老旧的Date到现代的java.time包迁移教程
Java时间处理全指南:从Date到java.time的现代化迁移实战 如果你是一位Java后端开发者,大概率在某个深夜与java.util.Date进行过激烈搏斗。这个诞生于JDK 1.0的古老API,以其反直觉的月份从0开始计数、非线程安全的SimpleDateFormat、含糊不清的…...
GLM-OCR模型版本管理与升级指南
GLM-OCR模型版本管理与升级指南 每次看到GLM-OCR模型出了新版本,你是不是既兴奋又有点头疼?兴奋的是新功能、新优化,头疼的是怎么把它安全、平滑地用到线上服务里,万一出问题怎么办? 在星图GPU平台上,模型…...
在线强化学习 vs 离线强化学习:哪种更适合你的AI项目?5个关键因素帮你选择
在线强化学习与离线强化学习的深度决策指南:5个核心维度解析 在AI项目落地的初期阶段,技术选型往往决定着整个项目的成败。强化学习作为机器学习领域的重要分支,其在线(Online)与离线(Offline)两…...
Alpamayo-R1-10B惊艳案例:暴雨天气图像+‘缓行通过积水区’指令的因果链输出
Alpamayo-R1-10B惊艳案例:暴雨天气图像‘缓行通过积水区’指令的因果链输出 1. 项目简介:一个能“看懂”路况并“思考”的自动驾驶大脑 想象一下,你正开车经过一个暴雨后的十字路口,前方路面有明显的积水。你会怎么做࿱…...
基于VSG控制的MMC并网逆变器仿真模型(Simulink仿真实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
【训练营】01 立创EDA与ESP32-C3入门实战:从零构建互联网时钟
【训练营】01 立创EDA与ESP32-C3入门实战:从零构建互联网时钟 大家好,我是老张,一个在嵌入式行业摸爬滚打了十来年的工程师。最近有不少刚入门的朋友问我,想学嵌入式开发,但面对一堆陌生的工具和开发板,感觉…...
