【C++】list容器功能模拟实现

news2024/10/6 10:30:50

介绍

        上一次介绍了list队容器的迭代器模拟,这次模拟实现list的简单功能,尤其要注意构造函数、析构函数、以及赋值运算符重载的实现。

        list容器需要接纳所有类型的数据,因此,结构设置与迭代器设置同理,需要引入结点,数据。

    //结点结构

    template<class T>
    struct ListNode
    {
        ListNode<T>* _next;
        ListNode<T>* _last;
        T _data;
        ListNode(const T& x = T())
            :_next(nullptr)
            , _last(nullptr)
            , _data(x)
        { }
    };

    //list容器基本元素

    template<class T>
    class list
    {
    public:
        typedef ListNode<T> Node;  
        typedef _list_iterator<T> iterator;

    private:
        Node* _node;  //此结点为哨兵结点,前指头结点,后指尾结点,里面没有数据
    };


一,构造函数

        构造函数只需构造“ 哨兵结点 ”即可,因为这里使用链式结构存储,因此构造函数没有顺序结构那样的逻辑。代码如下:

list()
{
    _node = new Node;
    _node->_last = _node;
    _node->_next = _node;
}

        拷贝构造的实现可直接运用赋值运算符,这里要注意,由于这里的设计设计到动态空间的申请,所以实现时需进行深拷贝。

        这里,我们先实现push_back尾插功能,代码如下:

//尾插功能

void push_back(const T& x = T()) 
{
    Node* node = new Node;
    node->_data = x;
    node->_next = _node;
    node->_last = _node->_last;
    _node->_last->_next = node;
    _node->_last = node;
}

        下面是赋值运算符和拷贝构造的实现,唯一要注意的是在使用赋值运算符前,要先确定“ 哨兵结点 ”,即普通的构造函数。

//赋值运算符重载
list<T>& operator=(list<T>& L)
{
    Node* node = (L._node)->_next;
    while (node != L._node)
    {
        push_back(node->_data);
        node = node->_next;
    }
    return *this;
}

//拷贝构造函数

list(list<T>& L)
{

    //哨兵结点的构造
    _node = new Node;
    _node->_last = _node;
    _node->_next = _node;

    //赋值运算符的使用
    *this = L;
}

        下面进行样例代码测试:

void test1()
{
    list<int> v1;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);
    list<int> v2;
    v2 = v1;
    list<int> v3(v1);
    std::cout << "List v2: ";
    for (auto e : v2)
    {
        std::cout << e << "  ";
    }
    std::cout << std::endl;
    std::cout << "List v3: ";
    for (auto e : v3)
    {
        std::cout << e << "  ";
    }
    std::cout << std::endl;
}

 测试数据结果:


二,析构函数

        析构函数的设计只需诼渐释放所有结点即可,包括“ 哨兵结点 ”。代码如下:

~list()
{
    Node* t = _node->_next;
    while (t != _node)
    {
        Node* next = t->_next;
        delete t;
        t = next;
    }
    delete t;    //最后释放哨兵结点
    t = nullptr;
}


三,list容器接口

        这里实现begin()、end()、push_back(这个接口上面已实现,这里不做演示)、pop_back、push_front、pop_front。代码如下:

iterator begin()  //获取头结点
{
    return _node->_next;
}
iterator end()  //获取尾结点
{
    return _node;
}
void pop_back()  //尾删
{
    assert(_node->_next != _node);
    Node* node = _node->_last->_last;
    delete _node->_last;
    _node->_last = node;
    node->_next = _node;
}
void push_front(const T& x = T())  //头插
{
    Node* node = new Node;
    node->_data = x;
    node->_next = _node->_next;
    node->_last = _node;
    _node->_next->_last = node;
    _node->_next = node;
}
void pop_front()  //头删
{
    assert(_node->_next != _node);
    Node* node = _node->_next->_next;
    delete _node->_next;
    _node->_next = node;
    node->_last = _node;
}

        list容器常用功能有clear()、swap()、erase、insert。接口参数与实现如下:

void clear()
{
    Node* t = _node->_next;
    while (t != _node)
    {
        Node* next = t->_next;
        delete t;
        t = next;
    }
    t = nullptr;
}
void swap(list<T>& L)
{
    std::swap(_node, L._node);
}
iterator insert(iterator pos, const T& x = T())
{
    Node* node = new Node;
    node->_data = x;
    node->_next = pos.node;
    node->_last = (pos.node)->_last;
    node->_next->_last = node;
    node->_last->_next = node;
    return node;
}
iterator erase(iterator pos)
{
    assert(pos.node != _node);
    Node* next = (pos.node)->_next;
    Node* last = (pos.node)->_last;
    delete pos.node;
    next->_last = last;
    last->_next = next;
    return next;
}

        下面进行样例代码测试:

void test2()
{
    list<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    list<int>::iterator it = ++v.begin();
    v.insert(it, 9);
    v.erase(v.begin());
    for (auto e : v)
    {
        std::cout << e << "  ";
    }
    std::cout << std::endl;
}

测试数据结果如下:

        其它细节逻辑可自行测试,这里不再一一演示。

        总:list容器的模拟实现跟部分容器可能有些难度,这里注重要注意类型使用和转换,迭代器的模拟以及构造赋值与析构。功能实现的逻辑基本与链式逻辑一样。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1406364.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

邮件服务支持Exchange协议,资产历史账号支持设置保留数量,JumpServer堡垒机v3.10.2 LTS版本发布

2024年1月22日&#xff0c;JumpServer开源堡垒机正式发布v3.10.2 LTS版本。JumpServer开源项目组将对v3.10 LTS版本提供长期的支持和维护&#xff0c;并定期迭代发布小版本。欢迎广大社区用户升级至v3.10 LTS版本&#xff0c;以获得更佳的使用体验。 在v3.10.2 LTS版本中&…

LeetCode203 移除链表元素

203. 移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#…

简单高效 Learn LaTeX 008 - LaTex Font Color 字体与颜色 (32 mins)

在LaTeX中进行字体和颜色的设置&#xff1a; https://www.ixigua.com/7298100920137548288?id7304094068840071730&logTag3418d8469157c468c60b

开始学习vue2(Vue方法)

一、过滤器 过滤器&#xff08;Filters&#xff09;是 vue 为开发者提供的功能&#xff0c;常用于文本的格式 化。过滤器可以用在两个地方&#xff1a;插值表达式 和 v-bind 属性绑定。 过滤器应该被添加在 JavaScript 表达式的尾部&#xff0c;由“管道符 ”进行 调用&#…

春招冲刺第二天——SQL学习

春招冲刺第二天 前言 MySQL学习&#xff1a;哔哩哔哩参考视频&#xff1a; 【中字】SQL进阶教程 | 史上最易懂SQL教程&#xff01;10小时零基础成长SQL大师 第一章 Mysql安装 视频前三节有教程&#xff0c;或自行查阅&#xff0c;不做赘述 课程资料和数据库数据的网盘&…

苹果眼镜(Vision Pro)的开发者指南(6)-实战应用场景开发 - 游戏、协作、空间音频、WebXR

第一部分:【构建游戏和媒体体验】 了解如何使用visionOS在游戏和媒体体验中创建真正身临其境的时刻。游戏和媒体可以利用全方位的沉浸感来讲述令人难以置信的故事,并以一种新的方式与人们联系。将向你展示可供你入门的visionOS游戏和叙事开发途径。了解如何使用RealityKit有…

windows .vscode的json文件配置 CMake 构建项目 调试窗口中文设置等

一、CMake 和 mingw64的安装和环境配置 二、tasks.json和launch.json文件配置 tasks.json {"version": "2.0.0","options": {"cwd": "${workspaceFolder}/build"},"tasks": [{"type": "shell&q…

V∗: Guided Visual Search as a Core Mechanism in Multimodal LLMs

摘要 当我们环顾四周并执行复杂任务时&#xff0c;我们如何看待和选择性地处理我们所看到的是至关重要的。然而&#xff0c;这种视觉搜索机制的缺乏&#xff0c;在目前的多模态LLM&#xff08;MLLM&#xff09;阻碍了他们的能力&#xff0c;专注于重要的视觉细节&#xff0c;特…

顶顶通呼叫中心中间件利用自动外呼进入机器人的压力测试配置流程

文章目录 前言呼入进入机器人配置流程创建线路创建线路组呼入配置创建自动外呼任务1. 实现“一端放音&#xff0c;另一端进入机器人”操作创建拨号方案—“模拟放音”呼叫路由—“internal”启用拨号方案—“模拟放音”队列外呼配置 2. 实现“两端都进入机器人”操作队列外呼配…

网络安全--防御保护02

第二天重要的一个点是区域这个概念 防火墙的主要职责在于控制和防护---安全策略---防火墙可以根据安全策略来抓取流量之后做出对应的动作 防火墙的分类&#xff1a; 单一主机防火墙&#xff1a;专门有设备作为防火墙 路由集成&#xff1a;核心设备&#xff0c;可流量转发 分…

云原生离线工作流编排利器 -- 分布式工作流 Argo 集群

作者&#xff1a;庄宇 在现代的软件开发和数据处理领域&#xff0c;批处理作业&#xff08;Batch&#xff09;扮演着重要的角色。它们通常用于数据处理&#xff0c;仿真计算&#xff0c;科学计算等领域&#xff0c;往往需要大规模的计算资源。随着云计算的兴起&#xff0c;阿里…

【趣味CSS3.0】粘性定位属性Position:sticky是不是真的没用了?

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起学习和进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&a…

Windows下安装达梦8开发版数据库

达梦数据库属于国产主流数据库之一&#xff0c;本文记录WIndows下安装最新的达梦8数据库的过程。   达梦官网&#xff08;参考文献1&#xff09;下载开发版&#xff08;X86平台&#xff09;版安装包&#xff0c;如下图所示&#xff1a; 解压安装包后&#xff0c;其中包含ISO文…

打 jar 包运行 在windows 平台控制台和日志 乱码解决

--拒絕鷄巴囉嗦&#xff0c;直接解決問題 我们在Windows下运行jar包时&#xff0c;常常会出现乱码&#xff0c;主要分为dos窗口输出的日志中出现乱码和程序返回数据出现乱码。 dos窗口输出的日志中出现乱码 执行如下命令&#xff0c;将控制台输出编码改为UTF8&#xff1a; ch…

BL0942 内置时钟免校准计量芯片 用于智能家居领域 上海贝岭 低成本 使用指南

BL0939是上海贝岭股份有限公司开发的一款用于智能家居领域进行电能测量的专用芯片&#xff0c;支持两路测量&#xff0c;可同时进行计量和漏电故障检测&#xff0c;漏电检测电流可设&#xff0c;响应时间快&#xff0c;具有体积小&#xff0c;外围电路简单&#xff0c;成本低廉…

springboot集成tess4j

spring整合tess4j用于OCR识别图片&#xff0c;在windows环境识别正常&#xff0c;在liunx没有反应&#xff0c;本文用于解决部署linux问题。 整合springboot 1、引入pom文件 <dependency><groupId>net.sourceforge.tess4j</groupId><artifactId>tess…

HTML标题

我的HTML标题学习小记 HTML的标题功能真的非常实用&#xff01;它们就像是文章的大纲&#xff0c;帮助网页内容呈现出清晰的结构&#xff0c;也就是小题大作一番。 HTML标题的奥秘 在HTML中&#xff0c;我们使用<h1>至<h6>这些标签来定义标题。其中&#xff0c;…

​ElasticSearch

目录 简介 基本概念 倒排索引 FST 简介 ES是一个基于lucene构建的&#xff0c;分布式的&#xff0c;RESTful的开源全文搜索引擎。支持对各种类型的数据的索引&#xff1b;搜索速度快&#xff0c;可以提供实时的搜索服务&#xff1b;便于水平扩展&#xff0c;每秒可以处理 …

GitHub无法完成推送 的设置选项

GitHub无法完成推送 的设置选项 系统设置 VS中控制台设置【指令】 控制台调出方法 以下为VS控制台指令 git config --global --unset http.proxy git config --global --unset https.proxygit config --global http.proxy 127.0.0.1:7890 git config --global https.proxy …

http503错误是什么原因

HTTP503错误在站长圈很经常遇到&#xff0c;很多网站站长经常遇到的HTTP503错误经常会不知道怎么去解决它。今天我们就来针对HTTP503错误问题展开说说。HTTP503错误是指服务器暂时无法处理客户端的请求&#xff0c;常常出现在服务器超负荷或维护期间。在这种情况下&#xff0c;…