C++——list的特性及使用

list的特性        

STL中的list是指带头双向循环列表,list每个元素的存储相互独立,因为其节点存储位置独立不连续,其插入和删除不需要挪动其他元素效率比起vector更高。但也因为存储空间不连续的问题,不能做到和vector一样的随机访问。

 list的模拟实现

template<class T>
    struct ListNode
    {
        ListNode(const T& val = T())
            :_pPre(nullptr)
            ,_pNext(nullptr)
            ,_val(val)
        {
        }
        ListNode<T>* _pPre;
        ListNode<T>* _pNext;
        T _val;
    };


    //List的迭代器类
    template<class T, class Ref, class Ptr>
    class ListIterator
    {
        typedef ListNode<T>* PNode;
        typedef ListIterator<T, Ref, Ptr> Self;
    public:
        ListIterator(PNode pNode = nullptr)
            :_pNode(pNode)
        {}

        ListIterator(const Self& l)
        {
            _pNode = l.getpNode();
        }

        //T& operator*();
        Ref operator*()
        {
            return _pNode->_val;
        }

        //T* operator->();
        Ptr operator->()
        {
            return &_pNode->_val;
        }

        Self& operator++()
        {
            _pNode = _pNode->_pNext;
            return *this;
        }

        Self operator++(int)
        {
            Self tmp(*this);
            _pNode = _pNode->_pNext;
            return tmp;
        }

        Self& operator--()
        {
            _pNode = _pNode->_pPre;
            return *this;
        }

        Self& operator--(int)
        {
            Self tmp(*this);
            _pNode = _pNode->_pPre;
            return tmp;
        }

        bool operator!=(const Self& l)
        {
            return _pNode != l.getpNode();
        }

        bool operator==(const Self& l)
        {
            return _pNode == l.getpNode();
        }

        PNode getpNode()const
        {
            return _pNode;
        }
    private:
        PNode _pNode;
    };


    //list类
    template<class T>
    class list
    {
        typedef ListNode<T> Node;
        typedef Node* PNode;
    public:
        typedef ListIterator<T, T&, T*> iterator;
        typedef ListIterator<T, const T&, const T&> const_iterator;
    public:
        ///
        // List的构造
        list()
        {
            CreateHead();
        }
        list(int n, const T& value = T())
        {
            _size += n;
            CreateHead();
            PNode cur = _pHead;
            while (n--)
            {
                PNode newnode = new Node(value);
                cur->_pNext = newnode;
                newnode->_pPre = cur;
                newnode->_pNext = _pHead;
                _pHead->_pPre = newnode;
                cur = cur->_pNext;
            }
        }
        template <class Iterator>
        list(Iterator first, Iterator last)
        {
            Iterator cur = first;
            while (cur != last)
            {
                push_back(cur.getpNode()->_val);
                cur++;
            }
        }

        list(const list<T>& l)
        {
            CreateHead();
            for (auto& a : l)
            {
                push_back(a);
            }
        }

        list<T>& operator=(const list<T> l)
        {
            list<T> tmp(l);
            swap(tmp);
        }

        ~list()
        {
            clear();
            delete _pHead;
            _pHead = nullptr;
        }


        ///
        // List Iterator
        iterator begin()
        {
            return _pHead->_pNext;
        }
        iterator end()
        {
            return _pHead;
        }
        const_iterator begin()const
        {
            return _pHead->_pNext;
        }
        const_iterator end()const
        {
            return _pHead;
        }


        ///
        // List Capacity
        size_t size()const
        {
            return _size;
        }
        bool empty()const
        {
            return _size == 0;
        }


        
        // List Access
        T& front()
        {
            return _pHead->_pNext->_val;
        }
        const T& front()const
        {
            return _pHead->_pNext->_val;
        }
        T& back()
        {
            return _pHead->_pPre->_val;
        }
        const T& back()const
        {
            return _pHead->_pPre->_val;
        }


        
        // List Modify
        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)
        {
            PNode newnode = new Node(val);
            PNode cur = pos.getpNode();
            PNode prev = cur->_pPre;

            newnode->_pNext = cur;
            cur->_pPre = newnode;
            prev->_pNext = newnode;
            newnode->_pPre = prev;
            _size++;

            return iterator(newnode);
        }
        // 删除pos位置的节点,返回该节点的下一个位置
        iterator erase(iterator pos)
        {
            PNode cur = pos.getpNode();
            PNode prev = cur->_pPre;
            PNode next = cur->_pNext;

            prev->_pNext = next;
            next->_pPre = prev;
            delete cur;
            _size--;

            return iterator(next);
        }

        void clear()
        {
            iterator it = begin();
            while (it != end())
            {
                it = erase(it);
            }
        }

        void swap(list<T>& l)
        {
            std::swap(_pHead, l.getpHead());
            std::swap(_size, l.size());
        }

        PNode getpHead()const
        {
            return _pHead;
        }
    private:
        void CreateHead()
        {
            _pHead = new Node;
            _pHead->_pNext = _pHead;
            _pHead->_pPre = _pHead;

            _size = 0;
        }
        PNode _pHead;
        size_t _size;
    };

迭代器失效问题

与vector不同,list插入时迭代器不会失效,因为节点相互独立的原因,所以list的插入不会改变其节点存储位置,如此一来迭代器的指向也不会有影响。

 

不过删除时仍会出现迭代器失效,迭代器指向的节点被删除时该迭代器失效(指向的节点失效,迭代器自然也就失效了),其余不受影响。

 

 list与vector的区别

vectorlist
插入与删除插入与删除都可能需要挪动部分元素,时间复杂度为O(n),插入还往往伴随着扩容,又因为其需要连续的存储空间还可能出现开辟新空间,拷贝数据,释放旧空间的操作,整体效率低下。插入与删除的时间复杂度均为O(1),存储空间的独立使其不需要扩容,需要新节点时才进行申请,并且不需要挪动数据。
随机访问存储空间连续,支持随机访问,查找的时间复杂度为O(1)不支持随机访问,查找的时间复杂度为O(n)
迭代器使用原生指针使用被封装的原生指针
空间利用率因其内存连续,不易造成内存碎片,空间利用率高,但缓存利用率高因其节点是动态开辟而来,且相互独立。容易造成内存碎片,空间利用率低,但缓存利用率低

总结:如果需要高效存储、需要随机访问且不关心插入删除效率则使用vector。反之需要大量插入删除查找,不关心随机访问则使用list。

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

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

相关文章

鸿蒙编译子系统详解(二)main.py

1.5.4源码解析 1.5.4.1 build/hb/main.py脚本 这个脚本是编译的主程序脚本&#xff0c;流程如下&#xff1a; 首先是初始化各种module类&#xff0c;然后运行对应模块。 hb分为build,set,env,clean,tool,help几个模块&#xff0c;模块源码位于build/hb/modules/目录下&#xff…

学生管理系统初级

根据题目要求生成大纲 总结: 1.在书写时&#xff0c;考虑到了书写时id可是是abc... 类型是String&#xff0c;但在根据id获取集合中元素时 list.get() &#xff0c;get&#xff08;&#xff09;里面是int类型。 2.在书写还有一点功能并不完全&#xff0c; 2.1查找时是打印所有…

【NodeMCU实时天气时钟温湿度项目 1】连接点亮SPI-TFT屏幕和UI布局设计

前言 从今天开始&#xff0c;我们详解介绍制作实时天气时钟项目的方法步骤&#xff0c;主要分以下几个专题分别进行&#xff1a;&#xff08;1&#xff09;连接点亮SPI-TFT屏幕和UI布局设计&#xff1b;&#xff08;2&#xff09;NodeMCU的WIFI模式设置及连接&#xff1b;&…

车牌号识别系统:PyQT5+QT Designe+crnn/PaddleOCR+YOLO+OpenCV矫正算法。

PyQT5&QT Designecrnn/PaddleOCRYOLO传统OpenCV矫正算法。可视化的车牌识别系统项目。 车牌号识别系统 项目绪论1.项目展示2.视频展示3.整体思路 一、PyQT5 和 QT Designer1.简介2.安装3.使用 二、YOLO检测算法三、OpenCV矫正算法四、crnn/PaddleOCR字符识别算法五、QT界面…

FreeRTOS任务详解

一、任务的创建与删除 1.任务的基本概念 RTOS系统的核心就是任务管理,FreeRTOS 也不例外,而且大多数学习 RTOS 系统的工程 师或者学生主要就是为了使用 RTOS 的多任务处理功能,初步上手 RTOS 系统首先必须掌握的 也是任务的创建、删除、挂起和恢复等操作,由此可见任务管理…

限量背包问题

问题描述 限量背包问题&#xff1a;从m个物品中挑选出最多v个物品放入容量为n的背包。 问题分析 限量背包问题&#xff0c;可以用来解决许多问题&#xff0c;例如要求从n个物品中挑选出最多v个物品放入容量为m的背包使得背包最后的价值最大&#xff0c;或者总共有多少种放法…

我独自升级:崛起怎么下载 我独自升级游戏下载教程分享

定于5月8日全球揭幕的《我独自升级崛起》——一款扣人心弦的动作RPG巨制&#xff0c;灵感采撷于同名动画及网络漫画的热潮&#xff0c;誓将引领满怀热忱的玩家步入一场交织着深邃探索和宏大规模的奇妙冒险。该游戏立足于一个独树一帜的网络武侠宇宙&#xff0c;细腻刻画了一个凡…

VSCode通过SSH连接虚拟机Ubuntu失败

问题说明 最近使用VSCode通过SSH连接Ubuntu&#xff0c;通过VSCode访问Ubuntu进行项目开发&#xff0c;发现连接失败 在VSCode中进行SSH配置 这些都没有问题&#xff0c;但在进行连接时候出现了问题&#xff0c;如下&#xff1a; 出现了下面这个弹窗 解决方法 发现当…

软件测试职责

软件测试职责主要包括以下几个方面&#xff1a; 1. 需求分析&#xff1a;理解软件需求规格说明书&#xff0c;确保测试活动覆盖所有的功能需求和非功能需求&#xff08;如性能、安全性、兼容性等&#xff09;。 2. 测试计划制定&#xff1a;根据项目需求&#xff0c;设计测试…

NodeJS 如何在npm运行时设置Windows控制台的标题?

通过代码设置 const server app.listen(port, () > {console.log(主机名称&#xff1a;, global.hostname)console.log(主机IP地址&#xff1a;, global.host)console.log(后台服务端口号&#xff1a;, port)console.log(恭喜你&#xff0c;启动成功!)process.title node …

图像处理

图像处理 导入图片 导入io模块&#xff0c;读取文件所在位置&#xff0c;将生成的图像数据赋给变量img&#xff0c;显示图像 from skimage import ioimgio.imread(D:\工坊\图像处理\十个勤天2.png)io.imshow(img) 运行结果&#xff1a; 将图片进行灰度处理 from skimage i…

Autodesk AutoCAD 2025 for Mac:强大的二维三维绘图工具

Autodesk AutoCAD 2025 for Mac是一款专为Mac用户打造的计算机辅助设计软件&#xff0c;它在继承了AutoCAD系列软件的优秀传统的基础上&#xff0c;针对Mac系统进行了全面优化&#xff0c;为用户提供了更出色的绘图和设计体验。 这款软件不仅支持用户创建和编辑复杂的二维几何图…

Nvidia发布Llama3-ChatQA-1.5: 提升对话问答和表格推理能力,平均性能超越GPT-4

前言 近日&#xff0c;Nvidia推出了一款名为Llama3-ChatQA-1.5的对话问答模型。该模型在对话式问答和检索增强型生成等能力方面表现出色&#xff0c;在综合评测指标上甚至超越了当前业界顶尖的GPT-4模型。 技术特点 Llama3-ChatQA-1.5是基于Llama-3基础模型训练而成的。相比之…

01-基本概念

1. 到底什么是数据结构&#xff1f; 数据结构是指在计算机中组织和存储数据的方式&#xff0c;它涉及到数据元素之间的关系以及对这些关系进行操作的方法。数据结构可以看作是一种将数据组织起来以便有效使用的方式&#xff0c;它关注数据的组织、存储和操作&#xff0c;以及如…

关于冯诺依曼体系结构 和 操作系统(Operator System)的概念讲解(冯诺依曼体系结构,操作系统的作用等)

目录 一、冯诺依曼体系结构 二、操作系统 1. 概念 2. 设计操作系统的目的 3.系统调用和库函数概念 4.总结 三、完结撒❀ 一、冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体系。 截…

标贝数据采集标注在自动驾驶场景中落地应用实例

AI数据服务作为人工智能和机器学习的基础&#xff0c;在自动驾驶领域中有着重要地位。与其他人工智能应用场景相比&#xff0c;自动驾驶的落地场景相对复杂&#xff0c;想要让汽车本身的算法做到处理更多、更复杂的场景&#xff0c;就需要运用大量场景化高质量AI数据做支撑。标…

第八节课《大模型微调数据构造》

大模型微调数据构造&#xff08;补充课程&#xff09;_哔哩哔哩_bilibili Tutorial/FineTune at main Focusshang/Tutorial GitHub 一、大模型训练数据介绍 预训练&#xff1a; 网络、论文数据&#xff0c;无标签数据transform算法base model典型&#xff1a;GPT监督微调 对…

【C语言】整数,浮点数数据在内存中的存储

Tiny Spark get dazzling some day. 目录 1. 整数在内存中的存储1.1 原码、反码、补码1.1 大小端存储1.2.1 字节序分类1.2.2 判断字节序 2. 浮点数在内存中的存储2.1 浮点数的存储形式2.2 浮点数的 “ 存 ”2.2.1 S2.2.2 E2.2.3 F 2.3 浮点数的 “ 取 ”2.3.1 S2.3.2 E、F 3. 浮…

ISIS的基本概念

1.ISIS概述 IS-IS是一种链路状态路由协议&#xff0c;IS-IS与OSPF在许多方面非常相似&#xff0c; 例如运行IS-IS协议的直连设备之间通过发送Hello报文发现彼此&#xff0c;然后建立邻接关系&#xff0c;并交互链路状态信息。 CLNS由以下三个部分组成&#xff1a; CLNP&#xf…

新的项目springboot

buybuyshenglombok <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency> 添加依赖 lombok package com.example.demo.pojo;import lombok.AllArgsConstructor; import lombok.Data; import …