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

介绍

        上一次介绍了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容器的模拟实现跟部分容器可能有些难度,这里注重要注意类型使用和转换,迭代器的模拟以及构造赋值与析构。功能实现的逻辑基本与链式逻辑一样。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Dirichlet Process 3

本节来介绍如何构造G&#xff0c;这里使用Stick-breaking construction算法 如下图H是关于的分布 对于G&#xff0c;这里面有2个变量&#xff0c;一个是&#xff0c;即采样的位置&#xff0c;一个是&#xff0c;即的权重 每次采样一次称为一个item 第一次采样 ,, 第二次采样…

c++的命名空间

命名空间 一.c的关键字二.命名空间2.1 命名空间定义2.1 命名空间的使用2.1.1加命名空间名称及作用域限定符2.1.2使用using将命名空间中某个成员引入 三.标准命名空间std 一.c的关键字 c中一共有63个关键字 关键字11111asmdoifreturntrycontinueautodoubleinlineshorttypedeff…

vue echarts地图

下载地图文件&#xff1a; DataV.GeoAtlas地理小工具系列 范围选择器右侧行政区划范围中输入需要选择的省份或地市&#xff0c;选择自己想要的数据格式&#xff0c;这里选择了geojson格式&#xff0c;点右侧的蓝色按钮复制到浏览器地址栏中&#xff0c;打开的geojson文件内容…

LeetCode 670 最大交换数

周一&#xff0c;非常冷&#xff0c;大风呼呼的&#xff0c;上班路都走不动。 好消息&#xff0c;马上要过年了。大风吹&#xff0c;天气好。 过年过年&#xff0c;回家过年~ 学生时代的迷茫是不应该存在的&#xff0c;最好的时光应该尽情享受&#xff0c;而不应该自己给加层…

三年的功能测试,让我女朋友跑了,太难受了...

简单概括一下 先说一下自己的情况&#xff0c;普通本科&#xff0c;18年通过校招进入深圳某软件公司&#xff0c;干了3年多的功能测试&#xff0c;21年的那会&#xff0c;因为大环境不好&#xff0c;我整个人心惊胆战的&#xff0c;怕自己卷铺盖走人了&#xff0c;我感觉自己不…

测试数据: 在线MP4和图片url地址

收集整理一些开发中用到的测试数据 目录 MP4图片ICON MP4 https://media.w3.org/2010/05/sintel/trailer.mp4 图片 https://img-blog.csdnimg.cn/fcc22710385e4edabccf2451d5f64a99.jpeg ICON https://img-blog.csdnimg.cn/direct/fb1e1f109889467a85eec6af0984611c.png 以…

协同过滤源代码在真实数据集上运行及优化

最近在做推荐算法相关研究&#xff0c; 先拿一个协同过滤代码练手。 网上找代码很容易&#xff0c;但是大多是讲原理的示例代码&#xff0c;在真实数据集上运行问题特别多。 以一个2w节点的开源数据集为例&#xff08;baby.inter&#xff09; https://github.com/enoche/MM…

PSIM仿真DSP28335ADC功能并使用SCI串口模块输出曲线

在使用PSIM 2022 软件仿真DSP28335单片机时&#xff0c;发现里面还有SCI串口打印模块&#xff0c;在仿真软件里面可以看到串口数据&#xff0c;但是将代码下载到单片机上之后&#xff0c;使用串口助手却看不到任何数据&#xff0c;经过一番探索终于发现&#xff0c;串口不是这样…

【linux】串口工具

1. PuTTY - 尽管PuTTY更为人所知作为SSH和Telnet客户端&#xff0c;但它也有串口连接能力。 - 在Debian上可以通过命令 sudo apt-get install putty 来安装PuTTY。 2. Minicom - Minicom是一个字符界面的串行通信程序&#xff0c;经常用于调试串口和模拟器。 - 可以通过…

webserver 之 线程同步 线程池(半同步半反应堆)

目录 &#x1f402;前言 &#x1f351;B / S 模型 &#x1f418;线程同步机制 &#x1f33c;概念 &#xff08;1&#xff09;RAII &#xff08;2&#xff09;信号量 &#xff08;3&#xff09;互斥量 &#xff08;4&#xff09;条件变量 &#x1f33c;功能 &#xf…

python丰富的任务进度显示

pip install txdpy 安装 txdpy from txdpy import progbar 导入 progbar progbar()函数传入一个可遍历对象&#xff0c;返可迭代对象 from txdpy import progbar from random import uniform from time import sleepfor i in progbar(range(4651)):print(f第{i}条任务)…

Ubuntu Desktop 隐藏 / 显示文件和文件夹

Ubuntu Desktop 隐藏 / 显示文件和文件夹 1. GUI hot key2. Show hidden and backup filesReferences 1. GUI hot key Ctrl H: 隐藏 / 显示文件和文件夹 2. Show hidden and backup files Edit -> Preferences -> Views References [1] Yongqiang Cheng, https://yo…

Linux:vim的相关知识

目录 vim 是一个较为常见的编译文件的命令操作。 三种模式的区分的作用如下&#xff1a; 命令模式&#xff1a; 插入模式&#xff1a; 进入插入模式的标志&#xff1a;左下角有INSERT 底行模式&#xff1a; 命令模式的常见命令&#xff1a; 底行模式常见命令&#xff1…

【UE】在控件蓝图中通过时间轴控制材质参数变化

效果 步骤 1. 新建一个控件蓝图和一个材质 2. 打开材质&#xff0c;设置材质域为用户界面&#xff0c;混合模式设置为“半透明” 在材质图表中添加两个参数来控制材质的颜色和不透明度 3. 对材质创建材质实例 4. 打开控件蓝图&#xff0c;在画布面板中添加一个图像控件 将刚…

QT发送request请求

时间记录&#xff1a;2024/1/23 一、使用步骤 &#xff08;1&#xff09;pro文件中添加network模块 &#xff08;2&#xff09;创建QNetworkAccessManager网络管理类对象 &#xff08;3&#xff09;创建QNetworkRequest网络请求对象&#xff0c;使用setUrl方法设置请求url&am…

什么是BMC

BMC全称为Baseboard Management Controller&#xff08;基板管理控制器&#xff09;&#xff0c;是一种独立于服务器操作系统和主处理器的专用微控制器&#xff0c;它内置在服务器、网络设备和其他复杂电子系统的主板上。BMC主要负责监控和管理系统硬件的状态&#xff0c;并提供…

模型之气体的行为

气体的行为 “探索气体动理论&#xff1a;分子运动与温度的统计关系” 气体动理论由丹尼尔•伯努利在1738年提出&#xff0c;后来又由麦克斯韦、玻尔兹曼等人在19世纪后半叶推进。根据这种理论&#xff0c;气体是由运动着的分子组成的&#xff0c;气体的许多性质——如温度和…

“深入理解RabbitMQ交换机的原理与应用“

深入理解RabbitMQ交换机的原理与应用 引言1. RabbitMQ交换机简介介绍1.1 什么是RabbitMQ&#xff1f;1.1.1 消息中间件的作用1.1.2 RabbitMQ的特点和优势 1.2 RabbitMQ的基本概念1.2.1 队列1.2.2 交换机1.2.3 路由键 1.3 交换机的作用和分类1.3.1 直连交换机&#xff08;direct…

【MySQL进阶】锁

文章目录 锁概述全局锁语法特点 表级锁表锁意向锁 行级锁行锁间隙锁&临键锁 面试了解数据库的锁吗&#xff1f;介绍一下间隙锁InnoDB中行级锁是怎么实现的&#xff1f;数据库在什么情况下会发生死锁&#xff1f;说说数据库死锁的解决办法 锁 概述 锁机制&#xff1a;数据库…

C++进阶--哈希的应用之位图和布隆过滤器

哈希的应用之位图和布隆过滤器 一、位图1.1 位图&#xff08;bitset&#xff09;的提出1.2 位图的概念1.3 位图的模拟实现1.3.1 位图的底层结构1.3.2 位图的成员函数1.3.2.1 位图的构造1.3.2.2 位图的插入&#xff1a;set1.3.2.3 位图的删除&#xff1a;reset1.3.2.4 位图的查找…