C++系列之list的模拟实现

💗 💗 博客:小怡同学
💗 💗 个人简介:编程小萌新
💗 💗 如果博客对大家有用的话,请点赞关注再收藏 🌞
list的节点类
template
struct list_Node
{
public:
list_Node* _prev;
list_Node* _next;
T _val;
list_Node(const T& val = T())
{
_prev = _next = nullptr;
_val = val;
}
};`
list的迭代器类
//这里写入多个参数的目的是区分const迭代器
//传入不同的模板就会有不同的类
template<class T,class Ref ,class Ptr>
struct list_iterator
{public:typedef list_Node<T> Node;typedef list_iterator<T,Ref,Ptr> self;list_iterator(Node* node = nullptr){_node = node;}list_iterator(const self& i){_node(i._node);}//const对象不改变原数据T& operator*(){return _node->_val;}T* operator->(){return &_node->val;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(_node);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self& operator--(int){self tmp(_node);_node = _node->_prev;return tmp;}bool operator!=(const self& l){return _node != l._node;}bool operator==(const self& l){return _node == l._node;}Node* _node;};
构造函数
list(int n, const T& value = T())
{_head = new Node();_head->_prev = _head;_head->_next = _head;while (n--){push_back(value);}
}
template <class Intiterator>
list(Intiterator first, Intiterator last)
{//这三行代码的作用是制造一个头结点_head = new Node();_head->_prev = _head;_head->_next = _head;while (first != last){push_back(*first);first++;}
}
list(const list<T>& l)
{_head = new Node();_head->_prev = _head;_head->_next = _head;//这里制造一个list对象,构建与l对象一样的元素,在与*this进行调换。list<T> tmp (l.begin(),l.end());swap(tmp);
}
析构函数
~list()
{clear();//复用clear()函数,如果元素是自定义类型,则一一析构,delete _head;_head = nullptr;
}
赋值运算符=
list<T>& operator=(const list<T> l)
{swap(l);return *this;
}
迭代器的使用
iterator begin()
{return iterator(_head->_next);
}
iterator end()
{return itertor(_head);
}
//const对象迭代器的使用返回的是const指针(实际上迭代器是一个模板,只是类型不同)
const_iterator begin()const
{return const_iterator(_head->_next);
}
const_iterator end()const
{return itertor(_head);
}
list的元素大小和判空
size_t size()const//const与非const对象都可调用
{return _size;
}
bool empty()const
{return _size == 0;
}
访问list的头节点与尾节点
T& front()
{return _head->_next->_val;
}
const T& front()const
{return _head->_next->_val;
}
T& back()
{return _head->_prev->_val;
}
const T& back()const
{return _head->_prev->_val;
}
尾插,尾删,头插,尾删,插入,删除,交换,清空
//这里使用了函数的调用
void push_back(const T& val)
{insert(end(), val);
}
void pop_back()
{ erase(--end());
}
void push_front(const T& val)
{ insert(begin(), val);
}
void pop_front()
{ erase(begin());
}
// 在pos位置前插入值为val的节点
//这里不会发生迭代器的失效,迭代器没有被改变,返回时返回pos之前的迭代器
iterator insert(iterator pos, const T& val)
{Node* newnode = new Node(val);Node* node_pos = pos.Node;Node* prev = node_pos->_prev;Node* next = node_pos->_next;prev->_next = next;next->_prev = prev;return newnode;
}
// 删除pos位置的节点,返回该节点的下一个位置
//这里发生迭代器的失效。指向pos指针变成野指针,返回时需要更新到该节点的下一个位置
iterator erase(iterator pos)
{Node* node_pos = pos.Node;Node* node_next = pos.Node->_next;node_pos->_prev->_next = node_pos->_next;node_next->_prev = node_pos->_prev;delete node_pos;return iterator(node_next);
}
//清除链表,只保留头节点
void clear()
{iterator it = begin();while (it != end()){erase(it);}_head->_prev = _head;_head->_next = _head;
}
//交换链表
void swap(const list<T>& L)
{Node* tmp = L._head;L._head = tmp;tmp = _head;
}
#include <assert.h>
#include <iostream>
using namespace std;
namespace zjy
{template<class T>struct list_Node{public:list_Node* _prev;list_Node* _next;T _val;list_Node(const T& val = T()){_prev = _next = nullptr;_val = val;}};template<class T,class Ref ,class Ptr>struct list_iterator{public:typedef list_Node<T> Node;typedef list_iterator<T,Ref,Ptr> self;list_iterator(Node* node = nullptr){_node = node;}list_iterator(const self& i){_node(i._node);}T& operator*(){return _node->_val;}T* operator->(){return &_node->val;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(_node);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self& operator--(int){self tmp(_node);_node = _node->_prev;return tmp;}bool operator!=(const self& l){return _node != l._node;}bool operator==(const self& l){return _node == l._node;}Node* _node;};template<class T>class list{public:typedef list_Node<T> Node;typedef list_iterator<T,T&,T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;list(){_head = new Node();_head->_prev = _head;_head->_next = _head;}/*list(int n, const T& value = T()){_head = new Node();_head->_prev = _head;_head->_next = _head;while (n--){Node* newnode = new Node(value);Node* tail = _head->_prev;tail -> _next = newnode;newnode->_prev = _head;newnode->_next = _head;_head->_prev = newnode;tail = newnode;}}*/list(int n, const T& value = T()){_head = new Node();_head->_prev = _head;_head->_next = _head;while (n--){push_back(value);}}/*template <class Intiterator>list(Intiterator first, Intiterator last){_head = new Node();_head->_prev = _head;_head->_next = _head;Node* begin= first._node;Node* end = last._node;Node* tail = _head->_prev;while (begin != last){tail->_next = begin;begin->_prev = tail;begin->_next = _head;_head->_prev = begin;tail = begin;begin++;}}*/template <class Intiterator>list(Intiterator first, Intiterator last){_head = new Node();_head->_prev = _head;_head->_next = _head;while (first != last){push_back(*first);first++;}}void swap(const list<T>& L){Node* tmp = L._head;L._head = tmp;tmp = _head;}list(const list<T>& l){_head = new Node();_head->_prev = _head;_head->_next = _head;list<T> tmp (l.begin(),l.end());swap(tmp);}list<T>& operator=(const list<T> l){swap(l);return *this;}~list(){clear();delete _head;_head = nullptr;}iterator begin(){return iterator(_head->_next);}iterator end(){return itertor(_head);}const_iterator begin()const{return const_iterator(_head->_next);}const_iterator end()const{return const_itertor(_head);}size_t size()const{return _size;}bool empty()const{return _size == 0;}T& front(){return _head->_next->_val;}const T& front()const{return _head->_next->_val;}T& back(){return _head->_prev->_val;}const T& back()const{return _head->_prev->_val;}void push_back(const T& val) {insert(end(), val); }void pop_back() { erase(--end()); }void push_front(const T& val) { insert(begin(), val); }void pop_front() { erase(begin()); }// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){Node* newnode = new Node(val);Node* node_pos = pos.Node;Node* prev = node_pos->_prev;Node* next = node_pos->_next;prev->_next = next;next->_prev = prev;return newnode;}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){Node* node_pos = pos.Node;Node* node_next = pos.Node->_next;node_pos->_prev->_next = node_pos->_next;node_next->_prev = node_pos->_prev;delete node_pos;return iterator(node_next);}void clear(){iterator it = begin();while (it != end()){erase(it);}_head->_prev = _head;_head->_next = _head;}void test(){Node* tmp = _head->_next;while (tmp != _head){cout << tmp->_val << endl;tmp = tmp->_next;}}private:Node* _head;size_t _size;};
}

相关文章:
C++系列之list的模拟实现
💗 💗 博客:小怡同学 💗 💗 个人简介:编程小萌新 💗 💗 如果博客对大家有用的话,请点赞关注再收藏 🌞 list的节点类 template struct list_Node { public: list_Node* _prev; list_…...
什么情况下你会使用AI工具(chatgpt、bard)?
在当今数字化和智能化的时代,AI工具已成为许多领域的常见工具。在本文中,我将探讨什么情况下会使用AI工具。前言 – 人工智能教程 ChatGPT是一款由OpenAI开发的大型语言模型,可以生成文本、翻译语言、编写不同类型的创意内容,并以…...
【go】两数求和
文章目录 题目代码解法2 代码仓库 题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案…...
软考高项-成本管理
工具和技术 三点估算 通过考虑估算中的不确定性与风险,使用3种估算值来界定活动成本的近似区间,可以提高活动成本估算的准确性; 储备分析 为应对成本的不确定性,成本估算中可以包括应急储备。应急储备的管理方法: 将…...
24年FRM备考知识点以及一级公式表
FRM一级公示表以及备考知识点 链接:https://pan.baidu.com/s/17RpFF9OyfRk7FGtEQrxf3A?pwd1234 提取码:1234 FRM二级公示表以及备考知识点 链接:https://pan.baidu.com/s/175D05wV1p94dIfBZThutCQ?pwd1234 提取码:1234...
Spring Cloud学习:二【详细】
目录 Nacos的配置 Nacos的单机启动 服务注册 Nacos服务分级存储模型 优先访问同集群的服务 根据权重负载均衡 环境隔离Namespace Nacos调用流程 Nacos与Eureka注册对比 Nacos与Eureka的共同点 Nacos与Eureka的区别 Nacos配置管理 统一配置 配置自动刷新 多环境配…...
Unity的live2dgalgame多语言可配置剧情框架
这段代码用于读取表格 using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using OfficeOpenXml; using System.IO; using UnityEngine.Networking; using UnityEngine.UI; using Random UnityEngine.Random;public class Plots…...
再畅通工程(最小生成树)
题目描述:还是畅通工程 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)&…...
前后端分离不可忽视的陷阱,深入剖析挑战,分享解决方案,助你顺利实施分离开发。
不管你设计的系统架构是怎么样,最后都是你的组织内的沟通结构胜出。这个观点一直在组织内不断地被证明,但也不断地被忽略。 前后端分离的利与弊 近几年,随着微服务架构风格的引入、前后端生态的快速发展、多端产品化的出现,前后…...
(四)库存超卖案例实战——优化redis分布式锁
前言 在上一节内容中,我们已经实现了使用redis分布式锁解决商品“超卖”的问题,本节内容是对redis分布式锁的优化。在上一节的redis分布式锁中,我们的锁有俩个可以优化的问题。第一,锁需要实现可重入,同一个线程不用重…...
【ROS入门】雷达、摄像头及kinect信息仿真以及显示
文章结构 雷达信息仿真以及显示Gazebo仿真雷达配置雷达传感器信息xacro文件集成启动仿真环境 Rviz显示雷达数据 摄像头信息仿真以及显示Gazebo仿真摄像头新建xacro文件,配置摄像头传感器信息xacro文件集成启动仿真环境 Rviz显示摄像头数据 kinect信息仿真以及显示Ga…...
实用篇-认识微服务
一、服务架构演变 1. 单体架构 单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署 单体架构的优点: 架构简单部署成本低 单体架构的缺点: 耦合度高 2. 分布式架构 分布式架构: 根据业务功能对系…...
【产品运营】产品需求应该如何管理
产品项目在进行时经常会有一些需求需要实现,需求是产品更新迭代的动力,需求也是从用户诉求转化而来;在做需求管理时,我们需要判断一个需求的优先级等方面,对产品进行优化; 目录: 一、 为什么要…...
Linux 系统调用IO口,利用光标偏移实现文件复制
用系统调用IO函数实现从一个文件读取最后2KB数据并复制到另一个文件中,源文件以只读方式打开,目标文件以只写的方式打开,若目标文件不存在,可以创建并设置初始值为0664,写出相应代码,要对出错情况有一定的处…...
【原创】指针变量作为函数参数要点注意
指针变量作为函数参数要点注意(已写至笔记) 1传参指针不加*(main中函数) 2收参指针要加*(被main调用的函数) 3传参指针名可与收参指针名不同,不影响 4【问】如何看主函数中指针所指内容是否改变…...
SpringMVC Day 04 : 数据绑定
前言 SpringMVC是一个非常流行的Java Web框架,它提供了很多方便的功能和工具来帮助我们构建高效、灵活的Web应用程序。其中,数据绑定就是SpringMVC中非常重要的一部分,它可以帮助我们方便地将请求参数绑定到Java对象上,从而简化了…...
2.3.1 协程设计原理与汇编实现
1.为什么要有协程? 同步的编程方式,异步的性能。同步编程时,我们需要等待io就绪。但是在协程这里,我们使用一种机制,当io需要等待时,就切到下一个io,之后当之前的io就绪时,再切换回来…...
J2EE项目部署与发布(Windows版本)->会议OA单体项目Windows部署,spa前后端分离项目Windows部署
会议OA单体项目Windows部署spa前后端分离项目Windows部署 1.会议OA单体项目Windows部署(以实施的角度) 将项目放入webapp,项目能够访问: 首先拿到war包和数据库脚本,并检查是否有什么问题。 如何查看项目报错信息(当你…...
Lua脚本语言
1. 概念 Lua(发音为"loo-ah",葡萄牙语中的"lua"意为月亮)是一种轻量级的、高效的、可嵌入的脚本编程语言。官网Lua最初由巴西计算机科学家Roberto Ierusalimschy、Waldemar Celes和Luiz Henrique de Figueiredo于1993年开…...
cat()函数和print()函数的区别
目录 区别一: 区别二: cat、print函数都是输出函数。 区别一: cat()函数不能赋值; print()函数可以赋值。 x<-cat("hello world") //赋值 hello world x //cat函数无返回值 NULLy<-print("hello …...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
