首页 > 其他分享 >STL-list模拟实现

STL-list模拟实现

时间:2024-02-27 22:34:20浏览次数:26  
标签:node const 迭代 iterator STL list next 模拟

#pragma once
#include"16my_Itetator.h" //测试用
#include<iostream> //测试用
using std::cout;
using std::endl;
using std::cin;
namespace test
{
    //struct默认权限是public,一般也不会加权限,class才会(需要封装时使用class)
    //结点使用struct的好处是开放结点,可以直接访问.不用重载流插入(stl也没重载),
    
    template<class T>
    struct list_node
    {
        //一个完整的结点,包含前,后,和自己
        list_node<T>* _next;
        list_node<T>* _prev;
        T _data;//

        //使用全缺省匿名对象(只要是模板,都得传对象,自定义类型接收的必须是实体对象)构造
        //list中使用是分配器分配空间,所以没写构造函数
        list_node(const T& x = T())//此处为方便不使用分配器,直接初始化个匿名对象
            : _next(nullptr)
            , _prev(nullptr)
            , _data(x)
        {}

        //移动构造
        list_node(T&& x = T())//此处为方便不使用分配器,直接初始化个匿名对象
            : _next(nullptr)
            , _prev(nullptr)
            , _data(std::forward<T>(x))
        {}

        //拷贝原理 
        
        /**
         * 
         *  list<int> lt(1) 初始化过程:
         *     先走拷贝构造,
         *     走init建一个头结点
         *     然后insert, insert中会建一个新结点, 值为1, 完成插入
         * 
         *     list<list<int>> lt1 初始化过程
         *     走默认构造, 空初始化一个list<T>头结点的过程(newnode之前), 再走默认构造, 建一个list<int>结点的匿名对象, 走的是拷贝构造(匿名对象传给x),
         *  将匿名对象拷贝进去.析构匿名对象, list<list<int>>默认构造完成
         * 
         *     list<list<int>> lt2(lt1) 初始化过程
         *     走拷贝构造, empty(就是头结点过程), ... 和lt1初始化过程一样
         *     建一个临时变量(接收迭代器构造的list)走迭代器构造, empty(建一个lt1的头结点), push_back
         *     交换头和临时头的内容, 完成拷贝构造
         * 
         *     在第一层迭代器构造中, 将lt1插进的过程有两层拷贝构造
         *     第一层拷贝构造 -- x == lt1
         *     push过程newnode(x == lt)->第二层拷贝构造:--通过初始化列表走的 解决问题
         * 
         *     综合发现 : 多重结点类只需要完成第一层深拷贝, 即可完成多层深拷贝
         *     因为每次都会new新结点, 且初始化列表赋值过程不是值拷贝, 而是会调用类类型的构造函数
         */



    };

    //这里声明的是list专用的迭代器 -- 实例化后能用于访问list
    //迭代器用于访问结点
    template<class T, class Ref, class Ptr>//Ref会接收参数 -- Ref会接收T&和const T&等,一个模板解决
    struct __list_iterator
    {
        //成员类型
        typedef list_node<T> node;
        typedef __list_iterator<T,Ref,Ptr> self; //只管接收


        //成员变量
        node* _node; //成员变量只需要1个结点指针,通过这个结点指针的各种操作来模拟指针

        //通过结点的指针来构造迭代器,模仿指针
        __list_iterator(node* n)
            :_node(n)
        {}
        //不用写拷贝构造,直接值拷贝就行了,需要的就是值拷贝,指向同一个结点

        //list迭代器不用写析构函数,因为迭代器接收的是list结点,由list负责即可


        //指针操作运算符重载,模拟指针

        //解引用重载能够模拟指针返回的是结点的data,和string,vector迭代器一样
        //
        /**
         * 模拟指针的方法
         * 我们对list的迭代器来说,
         * 为了符合习惯的指针用法
         * 对于结构体,实体可以通过成员访问修饰符去访问成员
         * 
         * 设struct AA{_a1,_a2};如AA._a1 , (&AA)->_a1
         * list<AA> iterator it = lt.begin();要想list<AA>能实现通过list迭代器实现上述功能,我们对迭代器运算符进行重载
         * 由于我们迭代器模拟的是元素的指针,list中的元素是AA,所以让it模拟成AA的指针:&AA
         * 我们希望迭代器能做到和基本类型一样有(*it)._a1 ,it->_a1;
         * 所以,我们将迭代器重载为
         * *it  返回 AA   //然后it便可以实现(*it)._a1;
         * it-> 返回 &AA  //目的是it可以实现it->_a1 ,实际上要访问_a1的过程是it->->_a1,但这样并不协调,为了可读性,所以编译器会将其优化成为it->_a1;
         * 
         * 可以发现,要实现it->并不容易,it毕竟是个结构体,这么实现是个很好的思路
         * 
         * 运算符重载的其中一个目的是可读性要强
         * 
         */

        Ref operator*()
        {
            return _node->_data;
        }
        //箭头重载很难理解,编译器做了一定优化,后续再学习
        //这个重载是会有编译器优化的

        Ptr operator->()
        {
            return &(_node->_data);
        }

        self& operator++()
        {
            _node = _node->_next;
            return *this;
        }
        //后置++返回的是一个拷贝,对原数据没有影响,安全
        self operator++(int)
        {
            self tmp = *this;//将原数据拷贝一份
            _node = _node->_next;
            return tmp;//返回拷贝
        }
        self& operator--()
        {
            _node = (*_node)._prev;
            return *this;
        }
        self operator--(int)
        {
            self tmp = *this;
            _node = _node->_prev;
            return tmp;
        }
        bool operator!=(const self& x)
        {
            return _node != x._node;
        }
        bool  operator==(const self& x)
        {
            return _node == x._node;
        }
    };

//list_const_iterator : const迭代器需要另写一个类 -- 优化:增加模板参数
    //template<class T>
    //struct __list_const_iterator
    //{
    //    typedef list_node<T> node;
    //    typedef __list_const_iterator<T> self;
    //    node* _node; 
    //    __list_const_iterator(node* n)
    //        :_node(n)
    //    {}

    //    const T& operator*()
    //    {
    //        return _node->_data;
    //    }
    //    const T* operator->()
    //    {
    //        return &(_node->date);
    //    }

    //    self& operator++()
    //    {
    //        _node = _node->_next;
    //        return *this;
    //    }
    //    self operator++(int)
    //    {
    //        self tmp = *this;
    //        _node = _node->_next;
    //        return tmp;
    //    }
    //    self& operator--()
    //    {
    //        _node = (*_node)._next;
    //        return *this;
    //    }
    //    self operator--(int)
    //    {
    //        self tmp = *this;
    //        _node = _node->_next;
    //        return tmp;
    //    }
    //    bool operator!=(const self& x) 
    //    {
    //        return _node != x._node;
    //    }
    //    bool  operator==(const self& x)
    //    {
    //        return _node == x._node;
    //    }
    //};



    template<class T>
    class list
    {
    private:
        typedef list_node<T> node;
    public:
        //正向迭代器类型重命名
        typedef __list_iterator<T,T&,T*> iterator;
        typedef __list_iterator<T,const T&,const T*> const_iterator; 

        //反向迭代器类型重命名
        typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
        typedef ReverseIterator<iterator, const T&, const T*> const_reverse_iterator;
//tese
//static int Swap;
//static int destruct;
//static int itstruct;
//static int cpstruct;

        //iterator
//返回迭代器,目的是按规范通过迭代器访问结点
//虽然迭代器不是原生指针,但是list迭代器重载了解引用运算符*,可以和指针一样解引用就能得到数据
        iterator begin()
        {
            //不能直接返回链表头结点的下一个的指针,因为链表的存储空间不连续,不能对指针直接加加减减,所以需要迭代器

            
            //需要实例化迭代器后才能使用迭代器
            //iterator it(_head->_next);
            //return it;

            //可以使用C++提供的匿名对象来简化代码
            return iterator(_head->_next);//正向迭代器类接收链表指针构造出正向迭代器实体
        }
        const_iterator begin() const //const修饰的*this,也就是链表,所以链表不能修改
        {
            return const_iterator(_head->_next);
        }
        iterator end()
        {
            //返回链表头结点的迭代器
            return iterator(_head);
        }
        const_iterator end()const
        {
            return const_iterator(_head);
        }

        //反向迭代器
        reverse_iterator rbegin() //
        {
            return reverse_iterator(end());//返回反向迭代器(适配器)接收正向迭代器的对象构造出反向迭代器
        }
        const_reverse_iterator rbegin() const
        {
            return const_reverse_iterator(end());
        }
        reverse_iterator rend() 
        {
            return reverse_iterator(begin());
        }
        const_reverse_iterator rend() const
        {
            return const_reverse_iterator(begin());
        }

        //list操作这边和数据结构的带头双向循环链表差不多,重点是iterator.写操作前写将迭代器整出来
    private:
        node* _head;//链表的操作就是从一个头开始,所以链表的成员就一个头指针
    public:
        //构造函数目前只写三个,1.无参,只创建头结点 2.迭代器构造 3.初始化n个结点 (不想写)

        //只构造了一个头结点
        list()
        {
            //cout << "list(" << this <<")" << endl;
            empty_init();
        }
        list(const T& x)
        {
            empty_init();
            push_back(x);
        }
        //list(const T& x)
        //{
        //    empty_init();//建一个头结点
        //    //...
        //        push_back(x);
        //}

//全缺省多个结点构造
        //list(size_t n , const T& x = T())
        //{
        //    cout << "list(size_t n , const T& x = T(" << this << ")))" << endl;
        //    empty_init();//建一个头结点
        //    //...
        //    while (n)
        //    {
        //        push_back(x);
        //        --n;
        //    }
        //}
        //list(int n , const T& x = T())
        //{
        //    cout << "list(int n , const T& x = T(" << this << ")))" << endl;
        //    empty_init();//建一个头结点
        //    //...
        //    while (n)
        //    {
        //        push_back(x);
        //        --n;
        //    }
        //}

//迭代器构造
        //深拷贝核心:只要进迭代器,就可以深拷贝
        template <class InputIterator> //可以接收任意类型的迭代器,不只是自己的迭代器
        list(InputIterator first, InputIterator last)
        {
            //cout << "list(InputIterator first, InputIterator last) " << this << ")" << endl;
            empty_init();//建一个头结点
            while (first != last)
            {
                push_back(*first);//"new"一个结点,拷x进来,++first,再new一个结点,拷x进来,通过这样实现了深拷贝,new关键字容易忽略,就是malloc
                ++first;
            }
        }
        void swap(list<T>& tmp)
        {
            //cout << "list(InputIterator first, InputIterator last)" << this << ")" << endl;
            std::swap(_head, tmp._head);
        }
//拷贝构造
        list(const list<T>& lt)
        {
            //深拷贝时,第一次拷贝构造是list<list<int>>,因为构造一个匿名对象,此时x是list<int> , 第二次是list<int>,拷贝构造给此时

            empty_init();
            list<T> tmp(lt.begin(), lt.end()); //深拷贝
            swap(tmp);
        }
        
        //此处不是深拷贝核心 -- 赋值初始化时的深拷贝
        list<T>& operator=(list<T> lt) //:传值传参->拷贝构造+迭代器构造,深拷贝
        //赋值运算符重载:操作数是list<list<>>,在非初始化时走这里,lt1 = lt2
        //使用到的场景,直接赋值给另一个对象:lt1 = lt2 :
        {
            //cout << "operator="<<endl;
            swap(lt);
            return *this;
        }

//移动构造
        list(list&& lt)
        {
            empty_init();
            list<T> tmp(lt.begin(), lt.end()); //深拷贝
            swap(tmp);
        }

        void empty_init()
        {
            //cout << "empty_init()" << this << ")" << endl;
            _head = new node(T());
            _head->_next = _head;
            _head->_prev = _head;
        }

        ~list()
        {
            //cout << "~list()" << this << ")"<<endl;
            clear();
            delete _head;
            _head = nullptr;
        }
        //clear:保留头结点,其他全部清空
        void clear()
        {
            iterator it = begin(); //begin用于初始化it,调用默认生成的值拷贝拷贝构造
            while (it!=end())
            {
                //it = erase(it);
                erase(it++);
            }
        }



        //Capacity
        //size实现需要迭代器计算链表长度会用就行


        //modifiers
        //插入
        //这里的传进来的迭代器是list的迭代器
        void insert(iterator pos , const T& x ) //insert没有迭代器失效问题,pos依然指向同一个结点
        {
            //cout << "insert" << *this << ")" << endl;
            node* cur = pos._node;
            node* prev = cur->_prev;
            node* new_node = new node(x);  //new阿!!!!!!!!!!!!!!!!!new是开辟新结点,然后再把x赋值进去--直接实现了深拷贝6666

            prev->_next = new_node;
            new_node->_prev = prev;
            new_node->_next = cur;
            cur->_prev = new_node;
        }

        //移动构造
        void insert(iterator pos, T&& x) //insert没有迭代器失效问题,pos依然指向同一个结点
        {
            //cout << "insert" << *this << ")" << endl;
            node* cur = pos._node;
            node* prev = cur->_prev;
            node* new_node = new node(std::forward<T>(x));  //new阿!!!!!!!!!!!!!!!!!new是开辟新结点,然后再把x赋值进去--直接实现了深拷贝6666

            prev->_next = new_node;
            new_node->_prev = prev;
            new_node->_next = cur;
            cur->_prev = new_node;
        }

        //删除
        iterator erase(iterator pos) //迭代器失效(野指针),返回链表下一个位置的迭代器
        {
            node* prev = pos._node->_prev;
            node* next = pos._node->_next;

            prev->_next = next;
            next->_prev = prev;
            delete pos._node;
            return iterator(next);
        }
        //尾插
        void push_back(const T& x) //插入必须有具体值,总不能插入一个匿名对象
        {
            //cout << "push_back" << this << ")" << endl;
            //node* n = new node(x);
            //node* tail = _head->_prev;
            //n->_prev = tail;
            //tail->_next = n;
            //n->_next = _head;
            //_head->_prev = n;
            insert(end(), x);
        }

        //右值引用版本
        void push_back(T&& x)
        {
            insert(end(), std::forward<T>(x));
        }

        //头插
        void push_front(const T& x)
        {
            //node* n = new node(x);
            //
            //n->_next = _head->_next;
            //_head->_next->_prev = n;
            //n->_prev = _head;
            //_head->_next = n;
            insert(begin(), x);
        }
        //头删
        void pop_front()
        {
            //node* cur = _head->_next ; //记录要删除的当前结点
            //cur->_next->_prev = _head;
            //_head->_next = cur->_next;
            //delete cur;
            erase(begin());
        }
        //尾删
        void pop_back()
        {
            //node* cur = _head->_prev;
            //cur->_prev->_next = _head;
            //_head->_prev = cur->_prev;
            //delete cur;
            erase(--end());
        }

    };
    //std::ostream& operator<<(std::ostream& out ,list<> )
    //{

    //}



    //测试用例


    //深拷贝验证
    void test_list1()
    {
        //using namespace std;
        list<int> lt(1);
        lt.push_back(2);
        //lt.push_back(3);
        //lt.push_back(4);
        //for (auto x : lt)
        //{
        //    cout << x << endl;
        //}
        //list<int>::iterator it = lt.begin();
        //while (it != lt.end())
        //{
        //    cout << *it << endl;
        //    ++it;
        //}
        list<list<int>> lt1;
        lt1.push_back(lt);
        //lt1.push_back(list<int>(1,1));
        //lt1.push_front(list<int>(1));
        //list<list<int>>::iterator it = lt1.begin();
        //lt1.insert(it, list<int>(2));
        //lt1.erase(it);
        //list<list<int>> lt2(lt1);
        //list<list<int>> lt2 = lt1;
        //lt2.push_back(list<int>(2));
        //lt2.push_back(list<int>(2));
        //lt2.push_back(list<int>(2));
        //lt2.pop_back();
        //lt2.pop_front();


        //list<int> lt1(1,1);
        //lt1.push_back(2);
        //list<int>::iterator it = lt1.begin();
        //cout << *it;

    }

    //迭代器const 运算符重载 
    void print_list(const list<int>& lt)
    {

        list<int>::const_iterator it = lt.begin();
        while (it != lt.end())
        {
            //++(*cit);

            std::cout << *it << std::endl;
            ++it;
        }
    }
    void test_list2()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        print_list(lt);
    }


    //迭代器运算符*,->重载,多模板参数
    struct AA
    {
        int _a1;
        int _a2;

        AA(int a1 = 0, int a2 = 0)
            :_a1(a1)
            , _a2(a2)
        {}
    };
    void test_list3()
    {
        list<AA> lt;
        lt.push_back(AA(1, 1));
        lt.push_back(AA(2, 2));
        lt.push_back(AA(3, 3));

        // AA* ptr
        list<AA>::iterator it = lt.begin();
        while (it != lt.end())
        {
            //cout << (*it)._a1 << ":" << (*it)._a2 << endl;        
            std::cout << it->_a1 << ":" << it->_a2 << std::endl;
            //cout << it.operator->()->_a1 << ":" << it.operator->()->_a1 << endl;
            ++it;
        }
        std::cout << std::endl;
    }

    void test_list4()
    {
        list<int> lt1;
        lt1.push_back(1);
        lt1.push_back(2);
        lt1.push_back(3);
        lt1.push_back(4);
        //list<int>::iterator it = lt1.begin();
        //while (it != lt1.end())
        //{
        //    cout << *it << " ";
        //    ++it;
        //}
        cout << endl<< "=============" << endl;
        list<int>::reverse_iterator rit = lt1.rbegin();
        while (rit != lt1.rend())
        {
            cout << *rit << " ";
            ++rit;
        }

    }
    
}

 

标签:node,const,迭代,iterator,STL,list,next,模拟
From: https://www.cnblogs.com/DSCL-ing/p/18038572

相关文章

  • STL-stack模拟实现
    #pragmaonce#include<assert.h>#include<list>#include<vector>#include<deque>#include<iostream>usingstd::cout;usingstd::endl;usingstd::cin;namespacetest{//template<classT,classContainers=std::vector&......
  • STL-queue模拟实现
    #include<list>#include<assert.h>#include<deque>#include<iostream>usingstd::cout;usingstd::endl;usingstd::cin;namespacetest{//template<classT,classContainers=std::list<T>>template<classT,c......
  • 从面向对象的角度看集合类,以List<String> list = new ArrayList<>()为例
    心血来潮琢磨了这么一个问题:Listlist=newArrayList<>();这句代码挺常用的,但是如果要从面向对象的角度去讲讲这句代码背后的逻辑,该怎么讲?好像真不容易一口气说完整,于是便有了本文的梳理。从关系图我们可以知道,ArrayList继承自一个抽象类AbstractCollection,它们都实现了Lis......
  • 2024.2.27模拟赛T2题解
    题目有一个神奇的结论\(\foralla<b<c,a\oplusc>min(a\oplusb,b\oplusc)\)然后就可以写出\(n^2\)dp,再用TRIE树优化即可code#include<bits/stdc++.h>usingnamespacestd;#defineN200005#defineintlonglongintn,k1,k2;inta[N],fl[2];constintm......
  • C++ STL 容器 list类型
    C++STL容器list类型list对于异常支持很好,要么成功,要么不会发生什么事情以下是std::list在异常处理方面表现良好的几个原因:动态内存管理:std::list使用动态内存分配来存储元素,这意味着它会在需要时自动分配内存,并在不再需要时释放内存。这种自动管理可以减少内存泄漏和悬......
  • C++ STL 容器-Deque
    C++STL容器-Dequestd::deque(双端队列)是C++标准模板库(STL)中的一个容器,它支持在序列的两端快速插入和删除元素。与std::vector和std::list等其他序列容器相比,std::deque在某些特定场景下具有独特的优势。元素的访问和迭代比vector慢,迭代器不是普通的指针。以下是std::deque的一......
  • 安卓模拟器
    安卓模拟器种类雷电夜神逍遥雷神模拟器本质安卓模拟器的本质是一台小型的虚拟机以雷电9模拟器为例在雷电9模拟器的安装目录下有一个vms文件,里面存储着虚拟机的信息 随便点开一个虚拟机分析文件目录下的三个vmdk文件,与安卓手机的文件系统一一对应!data存储用户......
  • Qt QList使用总结
    概述QList是Qt的泛型容器类之一。它将项目存储在一个列表中,该列表提供基于索引的快速访问以及基于索引的插入和删除。QList、QLinkedList和QVector提供了类似的API和功能。它们通常是可互换的,但性能有所区别。QVector应该是默认首选的容器QList是最广泛用于QtAPI中传递值......
  • Qt QList的用法
    在Qt中,QList 是一个常用的容器类,用于存储元素的动态数组。以下是简单的QList用法:1、包含头文件在使用QList之前,确保包含相应的头文件。#include<QList>2、创建QList对象使用QList模板创建一个对象,并指定存储的数据类型。QList<int>myList;//创建一个......
  • Qt QVector、QList、QSet和QMap:性能与用途比较
    Qt提供了多种容器类,用于存储和管理数据。其中,QVector、QList、QSet和QMap是最常用的几种。这些容器类在性能和用途方面存在一些差异,选择合适的容器对于提高应用程序的效率和正确性至关重要。下面我们将从以下几个方面对这四种容器进行比较:1.存储方式QVector:动态数组,元素在......