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

【c++】STl-list使用list模拟实现

主页:醋溜马桶圈-CSDN博客

专栏:c++_醋溜马桶圈的博客-CSDN博客

gitee:mnxcc (mnxcc) - Gitee.com

目录

1. list的介绍及使用

1.1 list的介绍

1.2 list的使用  

1.2.1 list的构造

1.2.2 list iterator的使用

1.2.3 list capacity

1.2.4 list element access

1.2.5 list modifiers

1.2.6 list的迭代器失效

2. list的深度剖析及模拟实现

2.1 模拟实现list

2.2 list的反向迭代器 

3. list与vector的对比

3.1 list与vector的对比

3.2 对比list排序和vector排序


1. list的介绍及使用

1.1 list的介绍

list - C++ Reference (cplusplus.com)

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代
  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素
  3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高
  4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好
  5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

1.2 list的使用  

list中的接口比较多,此处类似,只需要掌握如何正确的使用,然后再去深入研究背后的原理,已达到可扩展的能力。以下为list中一些常见的重要接口

1.2.1 list的构造

1.2.2 list iterator的使用

此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点

【注意】

  1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
  2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

1.2.3 list capacity

1.2.4 list element access

1.2.5 list modifiers

	list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(4);lt.push_back(4);lt.push_back(4);

1.2.6 list的迭代器失效

前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响

2. list的深度剖析及模拟实现

2.1 模拟实现list

#pragma once
#include <assert.h>
#include <iostream>
using namespace std;namespace dc
{template<class T>struct ListNode{ListNode<T>* _next;ListNode<T>* _prev;T _data;ListNode(const T& x=T()):_next(nullptr),_prev(nullptr),_data(x){}};//typedef ListIterator<T, T&, T*> iterator;//typedef ListIterator<T, const T&, const T*> const_iterator;template<class T,class Ref,class Ptr>struct ListIterator{typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;Node* _node;ListIterator(Node* node):_node(node){}//*it//T& operator*()Ref operator*(){return _node->_data;}//it->//T* operator->()Ptr operator->(){return &_node->_data;}//++itSelf& operator++(){_node = _node->_next;return *this;}//it++Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}//--itSelf& operator--(){_node = _node->_prev;return *this;}//it--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& it){return _node != it._node;}		bool operator==(const Self& it){return _node == it._node;}};//template<class T>//struct ListConstIterator//{//	typedef ListNode<T> Node;//	typedef ListConstIterator<T> Self;//	Node* _node;//	ListConstIterator(Node* node)//		:_node(node)//	{}//	//*it//	const T& operator*()//	{//		return _node->_data;//	}//	//it->//	const T* operator->()//	{//		return &_node->_data;//	}//	//++it//	Self& operator++()//	{//		_node = _node->_next;//		return *this;//	}//	//it++//	Self operator++(int)//	{//		Self tmp(*this);//		_node = _node->_next;//		return tmp;//	}//	//--it//	Self& operator--()//	{//		_node = _node->_prev;//		return *this;//	}//	//it--//	Self operator--(int)//	{//		Self tmp(*this);//		_node = _node->_prev;//		return tmp;//	}//	bool operator!=(const Self& it)//	{//		return _node != it._node;//	}//	bool operator==(const Self& it)//	{//		return _node == it._node;//	}//};template<class T>class list{typedef ListNode<T> Node;public://typedef ListIterator<T> iterator;//typedef ListConstIterator<T> const_iterator;typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;iterator begin(){//return _head->_next;return _head->_next;}iterator end(){return _head;}const_iterator begin() const{//return _head->_next;return _head->_next;}const_iterator end() const{return _head;}//初始化头结点void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}//lt2(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}//需要析构,一般就需要自己写深拷贝//不需要析构,默认浅拷贝就可以void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}//lt1=lt3list<T>& operator=(list<T> lt){swap(lt);return *this;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}~list(){clear();delete _head;_head = nullptr;}//void push_back(const T& x)//{//	Node* newnode = new Node(x);//	Node* tail = _head->_prev;//	tail->_next = newnode;//	newnode->_prev = tail;//	_head->_prev = newnode;//	newnode->_next = _head;//}void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void insert(iterator pos, const T& val){Node* cur = pos._node;Node* newnode = new Node(val);Node* prev = cur->_prev;prev->_next = newnode;newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;_size++;}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;_size--;return iterator(next);}size_t size() const{return _size;}bool empty(){return _size == 0;}private:Node* _head;size_t _size;};
}

2.2 list的反向迭代器 

通过前面例子知道,反向迭代器的++就是正向迭代器的--,反向迭代器的--就是正向迭代器的++,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可

template<class Iterator>
class ReverseListIterator
{// 注意:此处typename的作用是明确告诉编译器,Ref是Iterator类中的类型,而不是静态成员变量// 否则编译器编译时就不知道Ref是Iterator中的类型还是静态成员变量// 因为静态成员变量也是按照 类名::静态成员变量名 的方式访问的
public:typedef typename Iterator::Ref Ref;typedef typename Iterator::Ptr Ptr;typedef ReverseListIterator<Iterator> Self;
public://// 构造ReverseListIterator(Iterator it) : _it(it) {}//// 具有指针类似行为Ref operator*() {Iterator temp(_it);--temp;return *temp;}Ptr operator->() { return &(operator*()); }//// 迭代器支持移动Self& operator++() {--_it;return *this;}Self operator++(int) {Self temp(*this);--_it;return temp;}Self& operator--() {++_it;return *this;}Self operator--(int){Self temp(*this);++_it;return temp;}//// 迭代器支持比较bool operator!=(const Self& l)const { return _it != l._it; }bool operator==(const Self& l)const { return _it != l._it; }Iterator _it;
};

3. listvector的对比

3.1 listvector的对比

vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及应用场景不 同,其主要不同如下

3.2 对比list排序和vector排序

void test2()
{srand(time(0));const int N = 1000000;list<int> lt1;list<int> lt2;vector<int> v;for (int i = 0; i < N; i++){auto e = rand()+i;lt1.push_back(e);v.push_back(e);}int begin1 = clock();//排序sort(v.begin(), v.end());int end1 = clock();int begin2 = clock();lt1.sort();int end2 = clock();printf("vector sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);
}

相关文章:

【c++】STl-list使用list模拟实现

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;c_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1. list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 …...

号卡极团分销管理系统 index.php SQL注入漏洞复现

0x01 产品简介 号卡极团分销管理系统,同步对接多平台,同步订单信息,支持敢探号一键上架,首页多套UI+商品下单页多套模板,订单查询支持实时物流信息、支持代理商自定义域名、泛域名绑定,内置敢探号、172平台、号氪云平台第三方接口以及号卡网同系统对接! 0x02 漏洞概述…...

内核驱动更新

1.声明我们是开源的 .c 文件末尾加上 2.在Kconfig里面修改设备&#xff0c;bool&#xff08;双态&#xff09;-----》tristate&#xff08;三态&#xff09; 3.进入menuconfig修改为M 4.编译内核 make modules 也许你会看到一个 .ko 文件 5.复制到根目录文件下 在板子…...

故障诊断 | 一文解决,PLS偏最小二乘法的故障诊断(Matlab)

效果一览 文章概述 故障诊断 | 一文解决,PLS偏最小二乘法的故障诊断(Matlab) 模型描述 偏最小二乘法(Partial Least Squares, PLS)是一种统计建模方法,用于建立变量之间的线性关系模型。它是对多元线性回归方法的扩展,特别适用于处理高维数据和具有多重共线性的数据集。…...

我为什么选择成为程序员?

前言&#xff1a; 我选择成为程序员不是兴趣所在&#xff0c;也不是为了职业发展&#xff0c;全是生活所迫&#xff01; 第一章&#xff1a;那年&#xff0c;我双手插兜&#xff0c;对外面的世界一无所知 时间回到2009年&#xff0c;时间过得真快啊&#xff0c;一下就是15年前…...

Open CASCADE学习|统计形状拓扑数量

边界表示法&#xff08;Boundary Representation&#xff0c;简称B-Rep&#xff09;是几何造型中最成熟、无二义的表示法。它主要用于描述物体的几何信息和拓扑信息。在边界表示法中&#xff0c;一个实体&#xff08;Solid&#xff09;由一组封闭的面&#xff08;Face&#xff…...

LeetCode 热题 100 题解(二):双指针部分(2)| 滑动窗口部分(1)

题目四&#xff1a;接雨水&#xff08;No. 43&#xff09; 题目链接&#xff1a;https://leetcode.cn/problems/trapping-rain-water/description/?envTypestudy-plan-v2&envIdtop-100-liked 难度&#xff1a;困难 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&am…...

常用的深度学习自动标注软件

0. 简介 自动标注软件是一个非常节省人力资源的操作&#xff0c;而随着深度学习的发展&#xff0c;这些自动化标定软件也越来越多。本文章将会着重介绍其中比较经典的自动标注软件 1. AutoLabelImg AutoLabelImg 除了labelimg的初始功能外&#xff0c;额外包含十多种辅助标注…...

选择程序员是为什么?

本章节是关于为什么会选择一名程序员的经验分享 首先&#xff0c;我为什么会选择这个方向&#xff0c;可能是因为钱多&#xff0c;学东西不就是为了赚钱嘛&#xff1f;这是一点&#xff0c;不过最让我接收这个行业的是好奇世界的新大陆&#xff0c;可以简单的说就是&#xff0c…...

线程池参数如何设置

线程池参数设置 hello丫&#xff0c;各位小伙伴们&#xff0c;好久不见了&#xff01; 下面&#xff0c;我们先来复习一下线程池的参数 1、线程池参数有哪些&#xff1f; corePoolSize&#xff08;核心线程数&#xff09;&#xff1a;线程池中的常驻核心线程数。即使这些线程…...

qt环境搭建-镜像源安装Qt Creator(5.15.2)以及配置环境变量

前言&#xff1a; 版本&#xff1a;5.15.2 镜像源&#xff1a;ustc与清华 纯小白&#xff0c;找了半天的镜像源安装qtcreator&#xff0c;搞了半天结果安装的是最新的&#xff0c;太新的对小白很不友好&#xff0c;bug比较多&#xff0c;支持的系统也不全&#xff0c;口碑不…...

SQL Server详细安装使用教程

1.安装环境 现阶段基本不用SQL Server数据库了&#xff0c;看到有这样的分析话题&#xff0c;就把多年前的存货发一下&#xff0c;大家也可以讨论看看&#xff0c;思路上希望还有价值。 SQL Server 2008 R2有32位版本和64位版本&#xff0c;32位版本可以安装在Windows XP及以上…...

深度解读C++17中的std::string_view:解锁字符串处理的新境界

深入研究C17中的std::string_view&#xff1a;解锁字符串处理的新境界 一、简介二、std::string_view的基础知识2.1、构造函数2.2、成员函数 三、std::string_view为什么性能高&#xff1f;四、std::string_view的使用陷阱五、std::string_view源码解析六、总结 一、简介 C中有…...

汇编基础-----常见命令基本使用

汇编基础-----常见命令基本使用 MOV&#xff1a;将数据从一个位置复制到另一个位置。 MOV destination, source例如&#xff1a; MOV RAX, RBX ; 将RBX寄存器中的值复制到RAX寄存器中ADD/SUB&#xff1a;将两个操作数相加或相减。 ADD destination, source SUB destinatio…...

科研学习|可视化——相关性结果的可视化

一、相关性分析介绍 相关性分析是指研究两种或者两种以上的变量之间相关关系的统计分析方法&#xff0c;一般分析步骤为&#xff1a; 1&#xff09;判断变量间是否存在关联&#xff1b;2&#xff09;分析关联关系&#xff08;线性/非线性&#xff09;、关联方向&#xff08;正相…...

MapReduce过程解析

一、Map过程解析 Read阶段&#xff1a;MapTask通过用户编写的RecordReader&#xff0c;从输入的InputSplit中解析出一个个key/value。Map阶段&#xff1a;将解析出的key/value交给用户编写的Map()函数处理&#xff0c;并产生一系列的key/value。Collect阶段&#xff1a;在用户编…...

速看!这8道嵌入式面试题你都会吗?

大家好&#xff0c;我是知微&#xff01; 正逢求职季&#xff0c;分享一些嵌入式面试当中经常会遇到的题目&#xff0c;希望这些干货对小伙伴们面试有用哦&#xff01; 1、介绍一下static关键字的作用 在C语言中&#xff0c;static 关键字有几种不同的作用&#xff0c;根据其…...

基于SSM的电影网站(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的电影网站&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMv…...

SOCKS代理是如何提高网络性能和兼容性的?

SOCKS代理作为一种网络协议中间件&#xff0c;不仅在提升网络隐私和安全性方面发挥着重要作用&#xff0c;也在提高网络性能和兼容性方面有着不容忽视的影响&#x1f680;。本文将深入探讨SOCKS代理如何通过减少网络延迟&#x1f680;、优化数据传输&#x1f504;、提高跨平台兼…...

好菜每回味道不同--建造者模式

1.1 炒菜没放盐 中餐&#xff0c;老板需要每次炒菜&#xff0c;每次炒出来的味道都有可能不同。麦当劳、肯德基这些不过百年的洋快餐却能在有千年饮食文化的中国发展的那么好呢&#xff1f;是因为你不管何时何地在哪里吃味道都一样&#xff0c;而鱼香肉丝在我们中餐却可以吃出上…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...