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

C++ ─── List的模拟实现

目录

​编辑

一, List的模拟实现

二,代码实现

三、list和vector的区别


一, List的模拟实现

     List 是一个双向循环链表,由于List的节点不连续,不能用节点指针直接作为迭代器,因此我们要对结点指针封装,来实现迭代器的作用。

迭代器有两种实现方式,具体应根据容器底层数据结构实现:

        1. 原生态指针,比如:vector

        2. 将原生态指针进行封装,因迭代器使用形式与指针完全相同,因此在自定义的类中必须实现以下方法:

        1. 指针可以解引用,迭代器的类中必须重载operator*()

        2. 指针可以通过->访问其所指空间成员,迭代器类中必须重载oprator->()

        3. 指针可以++向后移动,迭代器类中必须重载operator++()与operator++(int)

至于operator--()/operator--(int)释放需要重载,根据具体的结构来抉择,双向链表可以向前 移动,所以需要重载,如果是forward_list就不需要重载--

        4. 迭代器需要进行是否相等的比较,因此还需要重载operator==()与operator!=()

二,代码实现

#pragma once
#include<assert.h>
#include<iostream>
#include <initializer_list>
#include<algorithm>
using namespace std;namespace BMH
{template<class T>struct ListNode{typedef ListNode<T> Node;Node* _prev;Node* _next;T _data;ListNode(const T& data = T()):_prev(nullptr), _next(nullptr), _data(data){}};template<class T, class Ref, class Ptr>struct ListIterator{//正向迭代器typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> Self;// Ref 和 Ptr 类型需要重定义下,实现反向迭代器时需要用到public:typedef Ref Ref;typedef Ptr Ptr;Node* _node;ListIterator(Node* node =nullptr):_node(node){}//++itSelf& operator++(){_node = _node->_next;return *this;//++it 返回自己(迭代器)}//--itSelf& operator--(){_node = _node->_prev;return  *this;}//it++Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}//it--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}//// 具有指针类似行为//*it  返回值Ref operator*(){return _node->_data;;}//it->  返回指针Ptr operator->(){return &(_node->_data);}////// 迭代器支持比较bool operator == (const Self& it){return _node == it._node;}bool operator != (const Self& it){return _node != it._node;}};template<class T>class List{public:typedef ListNode<T> Node;typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;/////初始化创建头结点void empty_init(){_head = new Node();_head->_prev = _head;_head->_next = _head;}//构造函数List(){empty_init();}List(int n, const T& value = T()){empty_init();for (int i = 0; i < n; ++i)push_back(value);}//用下面拷贝构造函数来实现构造函数,拷贝构造函数是构造函数的一种。//List<int> lt2(lt1)//List(const List<T>& lt)//{//	empty_init();//	for (const auto& e : lt)//	{//		Push_Back(e);//	}//}//List<int> lt1 ={1,2,3,4}List(initializer_list<T> il)//不用引用的原因:il本身是两个指针,拷贝代价小{empty_init();for (const auto& e : il){Push_Back(e);}}template<class Inputiterator >List(Inputiterator p1, Inputiterator p2){empty_init();while (p1 != p2){Push_Back(*p1);++p1;}}//拷贝构造//lt2(lt1)List(const List<T>& lt){empty_init();for (const auto& e : lt){Push_Back(e);}}//赋值重载//lt1=lt2List<T>& operator=(List<T> lt){swap(_head, lt._head);return *this;}void clear(){iterator it = begin();while (it != end()){it = erase(it);//用erase时会发生迭代器失效}}~List(){clear();delete _head;_head = nullptr;}/////迭代器iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const{return  const_iterator(_head);}///// 容量相关//尾插void Push_Back(const T& x){Node* tail = _head->_prev;Node* newnode = new Node(x);newnode->_prev = tail;tail->_next = newnode;newnode->_next = _head;_head->_prev = newnode;}void Pop_Back(){erase(--end());}void Push_Front(const T& x){insert(begin(),x);}void Pop_Front(){erase(begin());}//之前插入,无迭代器失效iterator insert(iterator pos ,const T& data ){Node* cur = pos._node;//pos是迭代器,找到其中的节点地址即可Node* newnode = new Node(data);Node* prev = cur->_prev;prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur-> _prev= newnode;return iterator(newnode);}//有迭代器失效,返回删除节点下一个的迭代器iterator erase(iterator pos){assert(pos!= (*this).end());//防止将Node* cur = pos._node;Node* next = cur->_next;Node* prev = cur->_prev;prev->_next = next;next->_prev = prev;delete cur;return iterator(next);}private:Node* _head;};

三、list和vector的区别

        1、任意位置插入删除时:list可以随意插入删除,但是vector任意位置的插入删除效率低,需要挪动元素,尤其是插入时有时候需要异地扩容,就需要开辟新空间,拷贝元素,释放旧空间,效率很低

        2、访问元素时:vector支持随机访问,但是list不支持随机访问
        3、迭代器的使用上:vector可以使用原生指针,但是list需要对原生指针进行封装
        4、空间利用上:vector使用的是一个连续的空间,空间利用率高,而list使用的是零碎的空间,空间利用率低

这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助

欢迎各位点赞,收藏和关注哦

如果有疑问或有不同见解,欢迎在评论区留言哦

后续我会一直分享双一流211西北大学软工(C,数据结构,C++,Linux,MySQL)的学习干货以及重要代码的分享

相关文章:

C++ ─── List的模拟实现

目录 ​编辑 一&#xff0c; List的模拟实现 二&#xff0c;代码实现 三、list和vector的区别 一&#xff0c; List的模拟实现 List 是一个双向循环链表,由于List的节点不连续&#xff0c;不能用节点指针直接作为迭代器&#xff0c;因此我们要对结点指针封装&#xff0c;来…...

Spring Boot详解

好的&#xff01;Spring Boot 是一个基于 Spring 框架的项目&#xff0c;它为简化配置、快速启动项目而生。它使得构建独立运行、生产级别的 Spring 应用变得非常简单&#xff0c;让开发者专注于业务逻辑而不再被繁琐的配置所困扰。接下来&#xff0c;我将从以下几个方面为你详…...

Proxfier+burpsuite抓包配置问题

1、burp证书配置 导出证书 后缀为cer 打开浏览器设置 搜索证书--》点安全 管理证书 在圈起来的三个地方添加证书 2、Proxifer配置 配置代理服务器 配置ip和port 配置代理规则 注意画圈部分...

sqli-lab靶场学习(一)——Less1-4

前言 最近一段时间想切入安全领域&#xff0c;因为本身有做数据库运维工作&#xff0c;就打算从sql注入方向切入。而sql注入除了学习日常书本上的概念外&#xff0c;需要有个实践的环境&#xff0c;刚好看到sqli-lab这个靶场&#xff0c;就打算先用这个来学习。 安装部署 网上…...

el-select如何同时获取value和label?

在element ui 中 下拉框默认获取下拉框value的值&#xff0c;但是有时候根据 业务需求&#xff0c;我们需要label值也发送给后端&#xff0c;在这提供一下获取value、和label 的方式 1、在给el-option绑定:value值时使用对象的方式&#xff0c;将value和label同时绑定到:value…...

1.初识ChatGPT:AI聊天机器人的革命(1/10)

引言 在当今的数字化世界中&#xff0c;人工智能&#xff08;AI&#xff09;正以其独特的方式重塑我们的生活和工作。其中&#xff0c;AI聊天机器人作为人机交互的前沿技术&#xff0c;已经成为企业与客户沟通、提供个性化服务的重要工具。这些机器人通过模拟人类的对话方式&a…...

API安全 | 发现API的5个小tips

在安全测试目标时&#xff0c;最有趣的测试部分是它的 API。API 是动态的&#xff0c;它们比应用程序的其他部分更新得更频繁&#xff0c;并且负责许多后端繁重的工作。在现代应用程序中&#xff0c;我们通常会看到 REST API&#xff0c;但也会看到其他形式&#xff0c;例如 Gr…...

数据结构---单向链表

单向链表 //链表的创建 Link_t *create_link() {Link_t *plink malloc(sizeof(Link_t));if(NULL plink){perror("fail plink");return NULL;}plink->phead NULL;plink->clen 0;return plink; } //头插 int push_link_head(Link_t *plink, DataType data…...

基于STM32设计的ECG+PPG人体参数测量系统(华为云IOT)(217)

文章目录 一、前言1.1 项目介绍【1】开发背景【2】项目实现的功能【3】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】整体构架【3】上位机开发思路【4】ESP8266工作模式配置1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】摘要【5】项目背景1.4 开发…...

SpringBoot教程(十五) | SpringBoot集成RabbitMq(死信队列、延迟队列)

SpringBoot教程&#xff08;十五&#xff09; | SpringBoot集成RabbitMq&#xff08;死信队列、延迟队列&#xff09; &#xff08;一&#xff09;死信队列使用场景具体用法前提示例: &#xff08;二&#xff09;延迟队列使用场景方法一&#xff1a;通过死亡队列实现方法二&…...

Dubbo依赖包

Dubbo 是一个高性能的 RPC 框架&#xff0c;用于构建分布式服务治理系统。要使用 Dubbo&#xff0c;项目中需要引入一些关键的依赖包。这些依赖包提供了 Dubbo 的核心功能、服务注册与发现、网络通信、序列化等能力。 一、Dubbo 核心依赖包 Dubbo 的核心依赖包包含了实现 RPC…...

webGIS后端程序员学习路线

webGIS后端程序员学习路线 1. GIS 基础知识 学习要点&#xff1a; 学习资源&#xff1a; 2. 后端编程基础 学习要点&#xff1a; 学习资源&#xff1a; 3. 地理数据库&#xff08;Spatial Database&#xff09; 学习要点&#xff1a; 学习资源&#xff1a; 4. 空间数…...

OpenCV绘图函数(15)图像上绘制矩形函数 rectangle()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 绘制一个简单的、粗的或填充的直立矩形。 这个函数 cv::rectangle 绘制一个矩形轮廓或一个填充的矩形&#xff0c;其两个相对的顶点分别是 pt1 和…...

从零开始,认识游戏设计师(4)体验源于设计师②

认真并仔细地揣摩你的想法 了解自己的感受并不是一件简单的事情&#xff0c;作为设计师&#xff0c;我觉得比了解玩家总体感觉的技能更重要的是你能清楚知道描述自己感受。 试想一下&#xff0c;你是否能准确描述你喜欢什么&#xff0c;你讨厌什么&#xff0c;以及为什么这样…...

周末总结(2024/09/07)

工作 人际关系核心实践&#xff1a; 要学会随时回应别人的善意&#xff0c;执行时间控制在5分钟以内 坚持每天早会打招呼 遇到接不住的话题时拉低自己&#xff0c;抬高别人(无阴阳气息) 朋友圈点赞控制在5min以内&#xff0c;职场社交不要放在5min以外 职场的人际关系在面对利…...

MySQL数据库的SQL注入漏洞解析

说明:本文仅是用于学习分析自己搭建的SQL漏洞内容和原理,请勿用在非法途径上,违者后果自负,与笔者无关;本文开始前请认真详细学习《‌中华人民共和国网络安全法》‌及其相关法规内容【学法时习之丨网络安全在身边一图了解网络安全法_中央网络安全和信息化委员会办公室】 …...

Redis进阶(七):分布式锁

在分布式系统下&#xff0c;涉及到多个节点访问同一个公共资源的情况&#xff0c;此时需要通过 锁 进行互斥控制&#xff1a;避免出现 线程安全问题。 1.分布式锁的基本实现 超卖问题&#xff1a; 解决: 采用redis实现分布式锁 可用采取&#xff1a;在购票的时候&#xff0…...

Python 中考虑 concurrent.futures 实现真正的并行计算

Python 中考虑 concurrent.futures 实现真正的并行计算 思考&#xff0c;如何将代码所要执行的计算任务划分成多个独立的部分并在各自的核心上面平行地运行。 Python 的全局解释器锁&#xff08;global interpreter lock&#xff0c;GIL&#xff09;导致没办法用线程来实现真…...

【C++多线程编程】 线程安全与对象生命周期管理

目录 类的线程安全 实现线程安全 构造函数在多线程中的安全性 析构函数多线程环境的安全 智能指针实现多线程安全 shared_ptr 非完全线程安全 shared_ptr可能导致对象生命周期延长 const引用可以减少传递shared_ptr开销 shared_ptr 智能指针块模块的优点 析构所在线程…...

【系统架构设计师-2024年-上半年】综合知识-答案及详解

更多内容请见: 备考系统架构设计师-核心总结索引 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16~17题】【第18~19题】【第20~21题】【第22题】【第23题】…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

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

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

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...