C++ : list类及其模拟实现

news2024/11/16 12:59:43

目录

一、list的介绍和使用

list的介绍

list的使用

1.list的构造

构造函数

2.list iterator 的使用

3.list capacity

4.list element access

5.list modifiers

6.list的迭代器失效

二、list的模拟实现

要点

list类模拟实现部分接口全部代码展示


一、list的介绍和使用

list的介绍

1.list 是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。

2.list的底层是带头双向可循环链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。

3.list和forward_list非常相似:最主要的不同在于forward_list 是单链表,只能朝前迭代,让其更简单高效。

4.与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。

5.与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间。

list的使用

1.list的构造

构造函数

(1)是指传来一个空指针,构造空的list

(2)指构造n个值为val的list

(3)用[first,last)中的元素构造list

(4)用x链表拷贝构造

2.list iterator 的使用

迭代器可以理解成一个指针,因为它封装了底层的逻辑,像指针一样使用。该指针指向list中的某个节点。begin就是指向第一个节点(非哨兵),end,返回最后一个元素下一个位置(就是哨兵位)。rbegin返回end位置,rend,返回begin位置。

注意:

begin和end是正向迭代器,对迭代器++,迭代器向后移动

rbegin和rend是反向迭代器,对迭代器++,迭代器向前移动

3.list capacity

empty 检查list是否是空链表

size  返回list中有效节点个数

4.list element access

front 返回list中,第一个节点的值的引用

back返回list中,最后一个节点的值的引用

5.list modifiers

模拟实现的话,掌握红框中常用的就好。

push_front 在list首节点前插入 值为val的节点

pop_front 删除list首节点

push_back 在list最后一个元素后插入值为val的节点

pop_back 删除list尾结点

insert 在pos位置插入一个值为val的节点

erase 删除pos位置的节点

swap  交换两个list中的元素

clear 清除list中的有效节点

6.list的迭代器失效

迭代器失效是指迭代器指向的节点无效,也就是该节点被删除了,用户不会再有该节点的访问权限。因为list的底层是带头双向循环链表,所以在list中进行插入时是不会导致list迭代器失效的,只有在删除时才会失效,并且失效的只有被删除节点的迭代器,其他节点的迭代器不会受到影响。

在逐个(调用erase函数时,参数)用后置++,不用前置++。表示删除以后,it又被重新赋值了。

二、list的模拟实现

要点

1.list要实现节点链表还有迭代器三个部分,分别建立三个类模板。这是为了提高类的复用性。封装在自己的命名空间里。

2.单个节点的结构体是公有的开放的,因为要在其他类里经常调用。所以得开放。包含val,前指针和后指针,以及构造函数。

 // 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;
 };

3.写迭代器的类时,迭代器指针也要设置为开放的,为了后面在list类中erase  pos位置和insert pos位置可以访问。迭代器的类模板是这样的。

Ref 和Ptr分别是迭代器返回的引用类型  和 迭代器返回的指针类型。

如果写T& 和T*,会限制迭代器返回的类型,这样想要返回const T& 和const T* 也无法更改。而Ref可以使你在实例化的时候就可以选择返回类型是什么。

//List的迭代器类
template<class T, class Ref, class Ptr>
class ListIterator
{
    typedef ListNode<T>* PNode;
    typedef ListIterator<T, Ref, Ptr> Self;//加了Ref和Ptr后,代码的灵活性提高
public:                                 //体现在返回的时候和实例化的时候,我可以控制迭代器解引 
                                              //用后返回什么类型
    ListIterator(PNode pNode = nullptr)
        :_pNode(pNode)
    {
    }
    ListIterator(const Self& l)
        :_pNode(l._pNode)
    {

    }
    Ref operator*()
    {
        return _pNode->_val;
    }
    Ptr operator->()
    {
        return &_pNode->_val;
    }
    Self& operator++()
    {
        _pNode = _pNode->_pNext;
        return *this;
    }
    Self operator++(int)
    {
        Self ptmp(*this);
        _pNode = _pNode->_pNext;
        return ptmp;
    }
    Self& operator--()
    {
        _pNode = _pNode->_pPre;
        return *this;
    }
    Self& operator--(int)
    {
        Self ptmp(*this);
        _pNode = _pNode->_pPre;
        return ptmp;
    }
    bool operator!=(const Self& l)
    {
        return _pNode != l._pNode;
    }
    bool operator==(const Self& l)
    {
        return _pNode == l._pNode;
    }
public:
    PNode _pNode;
};

list类模拟实现部分接口全部代码展示

#pragma once
#include<iostream>
#include <assert.h>
using namespace std;


namespace ting
{
    // 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;//加了Ref和Ptr后,代码的灵活性提高
    public:                                 //体现在返回的时候和实例化的时候,我可以控制迭代器解引用后返回什么类型
        ListIterator(PNode pNode = nullptr)
            :_pNode(pNode)
        {
        }
        ListIterator(const Self& l)
            :_pNode(l._pNode)
        {

        }
        Ref operator*()
        {
            return _pNode->_val;
        }
        Ptr operator->()
        {
            return &_pNode->_val;
        }
        Self& operator++()
        {
            _pNode = _pNode->_pNext;
            return *this;
        }
        Self operator++(int)
        {
            Self ptmp(*this);
            _pNode = _pNode->_pNext;
            return ptmp;
        }
        Self& operator--()
        {
            _pNode = _pNode->_pPre;
            return *this;
        }
        Self& operator--(int)
        {
            Self ptmp(*this);
            _pNode = _pNode->_pPre;
            return ptmp;
        }
        bool operator!=(const Self& l)
        {
            return _pNode != l._pNode;
        }
        bool operator==(const Self& l)
        {
            return _pNode == l._pNode;
        }
    public:
        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())
        {
            CreateHead();
            while (n--)
            {
                push_back(value);
            }
            
        }
        template <class Iterator>
        list(Iterator first, Iterator last)
        {
            CreateHead();
            while (first != last)
            {
                push_back(*first);
                ++first;
            }
        }
        list(const list<T>& l)
        {
            CreateHead();
            list<T> tmp(l.begin(), l.end());
            swap(tmp);
        }
        list<T>& operator=(const list<T> l)
        {
            swap(l);
            return *this;
        }
        ~list()
        {
            clear();
            delete _pHead;
            _pHead = nullptr;

        }

        

        ///
        // List Iterator
        iterator begin()
        {
            return iterator(_pHead->_pNext);//因为_pNext不是迭代器类型,要走迭代器的拷贝构造
        }
        iterator end()
        {
            return iterator(_pHead);
        }
        const_iterator begin() const
        {
            return const_iterator(_pHead->_pNext);
        }
        const_iterator end() const
        {
            return const_iterator(_pHead);
        }


        ///
        // List Capacity
        size_t size()const
        {
            size_t n = 0;
            for (auto it = begin(); it != end(); ++it)
            {
                ++n;
            }
            return n;
        }
        bool empty()const
        {
            return _pHead->_pNext == _pHead;
        }


        
        // 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);
            newnode->_pNext = pos._pNode;
            newnode->_pPre = pos._pNode->_pPre;

            newnode->_pPre->_pNext = newnode;
            pos._pNode->_pPre = newnode;
            return iterator(newnode);
        }

        iterator erase(iterator pos)
        {
            assert(pos != end());
            PNode nextNode = pos._pNode->_pNext;
            pos._pNode->_pPre->_pNext = pos._pNode->_pNext;
            pos._pNode->_pNext->_pPre = pos._pNode->_pPre;
            delete pos._pNode;
            return iterator(nextNode);
        }

        void clear()
        {
            while (!empty())
            {
                pop_back();
            }
        }
        void swap(list<T>& l)
        {
            std::swap(_pHead, l._pHead);
        }
    private:
        void CreateHead()
        {
            _pHead = new Node();
            _pHead->_pPre = _pHead;
            _pHead->_pNext = _pHead;
        }
        PNode _pHead;
    };
};


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

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

相关文章

C++笔试强训day13

目录 1.⽜⽜冲钻五 2.最长无重复子数组 ​编辑 3.重排字符串 1.⽜⽜冲钻五 链接 简单逻辑题&#xff0c;按照题目意思模拟就能过。 详细代码&#xff1a; #include <iostream>using namespace std;int n,k; void solve() {cin >> n >> k;string s;cin…

HNU-人工智能-实验2-简单CSP问题

人工智能-实验2 计科210x 甘晴void 一、实验目的 求解约束满足问题 使用回溯搜索算法求解八皇后问题 二、实验平台 课程实训平台https://www.educoder.net/paths/369 三、实验内容 3.0 题目要求 回溯搜索算法 搜索与回溯是计算机解题中常用的算法&#xff0c;很多问…

C#知识|如何在WinForm窗体中实现分割线绘制?

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 在上位机UI设计中经常会用到分割线&#xff0c;用来分割界面区域。 像在KingSCADA、杰控、昆仑通态、WinCC、组态王、力控、易控等组态软件中非常简单&#xff0c;有现成的划线操作&#xff0c;选中相关工具直接绘制即…

一文看懂卷积神经网络CNN(2)—卷积神经网络

目录 一、卷积 1、卷积的定义 &#xff08;1&#xff09;一维卷积 &#xff08;2&#xff09;二维卷积 2、互相关 3、互相关和卷积的区别 4、卷积的变种 5、卷积的数学性质 &#xff08;1&#xff09;交换性 &#xff08;2&#xff09;导数 二、卷积神经网络 1、卷…

Linux 内核简介

操作系统简介 操作系统概念&#xff1a;操作系统处于硬件和应用程序的中间层&#xff0c;控制和管理整个计算机系统的硬件和软件资源&#xff0c;提供给用户和其他软件方便的接口和环境&#xff0c;它是计算机系统的最基本的系统软件。 操作系统功能: 处理机管理存储器管理设…

基于Springboot的房屋租赁管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的房屋租赁管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

01 JVM -- JVM 体系结构、HotSpot

1. JVM、HotSpot、 OpenJDK 的区别 JVM (Java Virtual Machine) 是一个虚拟机HotSpot 是 JVM 规范的一个实现。HotSpot 虚拟机通过即时编译 (JIT) 技术将 Java 字节码转换为本地机器码&#xff0c;以提高程序的执行效率。OpenJDK 是一个项目名&#xff0c;它在 HotSpot 的基础…

puzzle(1041)植此青绿、拼图迷宫

目录 植此青绿 简单模式 困难模式 拼图迷宫 核心规则 中级模式具体规则 十字的交叉点 十字的端点、L的交叉点 L的端点 直线、矩形 U的端点 中级模式精选关卡 基本策略 高级模式具体规则 Z形状 T形状 高级模式精选关卡 植此青绿 最强大脑同款项目。 给出7个正…

JavaEE企业级开发中常用的JDK7和JDK8的时间类

JDK7时间类 全世界的时间有一个统一的计算标准 在同一条经线上的时间是一样的 格林威治时间 简称GMT 计算核心 地球自转一天是24小时 太阳直射正好是12小时 但是误差太大 现在用原子钟来代替 用铯原子震动的频率来计算时间&#xff0c;作为世界的标准时间UTC 中国标准时间…

开源版本管理系统的搭建二:SVN部署及使用

作者&#xff1a;私语茶馆 1. Visual SVN Server部署 SVN Server部署包括&#xff1a; 创建版本仓库创建用户 这些部署是通过VisualSVN Server Manager实现的&#xff0c;如下图&#xff1a; VisualSVN Server Manager&#xff08;安装后自带&#xff09; 1.1.SVN 初始化配…

流畅的Python阅读笔记

五一快乐的时光总是飞快了&#xff0c;不知多久没有拿起键盘写文章了&#xff0c;最近公司有Python的需求&#xff0c;想着复习下Python吧&#xff0c;然后就买了本Python的书籍 书名&#xff1a; 《流畅的Python》 下面是整理的一个阅读笔记&#xff0c;大家自行查阅&#xf…

ROS专栏—基于STM32F103的INA219电源数据采集

一、专栏介绍 这篇博客为ROS小车专栏的第一篇&#xff0c;自己想要做一个ROS小车&#xff0c;同时通过CSDN平台记录我的制作过程&#xff0c;为后来者提供一些参考吧&#xff0c;恩我也是从零开始摸索&#xff0c;可能会有很多错误和问题&#xff0c;希望大家多多包涵。 二、…

Python 全栈系列241 GFGo Lite迭代

说明 随着整个算网开发逐渐深入&#xff0c;各个组件、微服务的数量、深度在不断增加。由于算网是个人项目&#xff0c;我一直按照MVP(Minimum Viable Product )的原则在推进。由于最初的时候对架构、算法和业务的理解并没有那么深刻&#xff0c;所以MVP的内容还是在不断变化&…

数据结构十:哈希表

本次将从概念上理解什么是哈希表&#xff0c;理论知识较多&#xff0c;满满干货&#xff0c;这也是面试笔试的一个重点区域。 目录 一、什么是哈希表 1.0 为什么会有哈希表&#xff1f; 1.1 哈希表的基本概念 1.2 基本思想 1.3 举例理解 1.4 存在的问题 1.5 总结 二、…

基于TL431基准电压源的可调恒压恒流源的Multisim电路仿真设计

1、线性电源的工作原理 在我们日常应用里&#xff0c;直流电是从市电或电网中的交流电获取的。例如15V直流电压源、24V直流电压源等等。交流电变为直流电的过程大概分为一下几步&#xff1a; 首先&#xff0c;交流电通过变压器降低其电压幅值。接着&#xff0c;经过整流电路进…

01_SpringBoot简单搭建入门程序

目录 1、先创建一个java项目2、导入依赖3、将Java项目修改为SpringBoot项目4、编写一个测试的Controller5、测试(创建一个*.http的文件)方式1&#xff1a;方式2&#xff1a;可以直接在浏览器访问该地址方式3&#xff1a;使用postman也可以 1、先创建一个java项目 我的项目结构…

智能化工单助力业务运作:亿发解析工单系统的功能与适用场景

在现代企业管理中&#xff0c;工单系统扮演着至关重要的角色。面对市面上众多的工单系统&#xff0c;我们可以根据不同的依据进行分类&#xff0c;以更好地满足企业的需求。 1、按部署方式分类&#xff1a; 按照部署方式可以分为本地化部署工单系统和云端SaaS服务工单系统。 …

步态识别论文(6)GaitDAN: Cross-view Gait Recognition via Adversarial Domain Adaptation

摘要: 视角变化导致步态外观存在显着差异。因此&#xff0c;识别跨视图场景中的步态是非常具有挑战性的。最近的方法要么在进行识别之前将步态从原始视图转换为目标视图&#xff0c;要么通过蛮力学习或解耦学习提取与相机视图无关的步态特征。然而&#xff0c;这些方法有许多约…

【java9】java9新特性之Optional类改进

其实Optional类在Java8中就引入了&#xff0c;用于避免null检查和NullPointerException指针问题。 在Java9中&#xff0c;Optional类得到了进一步的改进&#xff0c;增加了一些新的方法&#xff0c;使其更加灵活和易用。 以下是一些Java9中对Optional类的改进&#xff1a; s…

ssm106学生公寓管理系统的设计与实现+jsp

学生公寓管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本学生公寓管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…