tsx81429 发表于 2024-8-14 15:59:04

C++ list【常用接口、模仿实现等】

1. list的先容及使用

1.1 list的先容

1.list是可以在常数范围内涵恣意位置举行插入和删除的序列式容器,而且该容器可以前后双向迭代。
2.list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
3.list与forward_list非常相似,最主要的差别在于forward_list是单链表,只能朝前迭代,让其更简单高效。
4.与其他的序列式容器相比(array,_vector,deque),list通常在恣意位置举行插入、移除元素的执行效率更好。
5.与其他序列式容器相比,list和forward_list最大的缺陷是不支持恣意位置的随机访问,好比:要访问list的第六个元素,必须从已知的位置(好比头部或尾部)迭代到该位置,在这段位置上迭代器需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息。
 https://i-blog.csdnimg.cn/direct/2731cd35d25c476f92b4aaf8dfe41ac7.png
1.2 list的使用

1.2.1 list的构造

析构函数(constructor)

接口说明

list (size_type n, const value_type& val = value_type())构造的list中包含n个值为val的元素list()构造空的listlist (const list& x)拷贝构造函数list (InputIterator first, InputIterator last)用[first, last)区间中的元素构造list (若为手机阅读,表格可左右移动)
https://i-blog.csdnimg.cn/direct/ed5e5b3dade0414eb563cc9205ca8892.png
1.2.2 list iterato的使用

此处,各人可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。
函数声明

接口说明

begin+end返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器rbegin+rend返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的reverse_iterator,即beign位置  (若为手机阅读,表格可左右移动)
    【注意】
1. begin与end为正向迭代器,对迭代器执行++操纵,迭代器向后移动
2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操纵,迭代器向前移动
https://i-blog.csdnimg.cn/direct/904bb76f87fe46be8b89906e0027045c.png
https://i-blog.csdnimg.cn/direct/c63aef71cfe84ab78f0571ac1155ebd1.png
1.2.3 list capacity

函数声明

接口说明

empty检测list是否为空,是返回true,否则返回falsesize返回list中有用节点的个数  (若为手机阅读,表格可左右移动)
https://i-blog.csdnimg.cn/direct/fc2bde0686a24c5d9425279fccee2098.png
1.2.4 list element access

函数声明

接口说明

front返回list的第一个节点中值的引用back返回list的最后一个节点中值的引用  (若为手机阅读,表格可左右移动)
https://i-blog.csdnimg.cn/direct/49969ffceade4630bfe2635b0cf25287.png
1.2.5 list modifiers

函数声明

接口说明

push_front在list首元素前插入值为val的元素pop_front删除list中的第一个元素push_back在list尾部插入值为val的元素pop_back删除list中最后一个元素insert在list position位置中插入值为val的元素erase删除list position位置的元素swap交换两个list中的元素clear清空list中的有用元素 (若为手机阅读,表格可左右移动)
https://i-blog.csdnimg.cn/direct/2d9c06f7d2b942cfa3587d40226e2b19.png
https://i-blog.csdnimg.cn/direct/eaa8f39c849347e78f52c4c059b8cfca.png
1.2.6 list的迭代器失效

 前面说过,此处各人可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中举行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,而且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
错误:
https://i-blog.csdnimg.cn/direct/c29e1e5a1c1945a8b2eb771a077a2cc5.png
改正:
https://i-blog.csdnimg.cn/direct/9039ae372d794ad99c72c8e8df458987.png
2. list的模仿实现

   实现节点类
https://i-blog.csdnimg.cn/direct/a1e983f4138545a2a0f82a51df304b72.png
template<class T>
struct ListNode
{
        ListNode<T>* _next;
        ListNode<T>* _prev;
        T _data;


        ListNode(const T& data = T())
                :_next(nullptr)
                , _prev(nullptr)
                , _data(data)
        {


        }
};    实现正向迭代器 
迭代器不消实现析构函数和深拷贝。因为迭代器本身就是为了访问链表的节点,节点属于链表,不属于迭代器,如果需要析构和深拷贝,应该在控制链表的类中实现。
https://i-blog.csdnimg.cn/direct/7e21e8502cf54c0ba5804b1428ce1017.png
        template<class T, class Ref, class Ptr>
        struct ListIterator
        {
                typedef ListNode<T> Node;
                typedef ListIterator<T, Ref, Ptr> self;
                Node* _node;


                ListIterator(Node* node)
                        :_node(node)
                {


                }


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


                Ref operator*()
                {
                        return _node->_data;
                }


                bool operator!=(const self& it)
                {
                        return _node != it._node;
                }


                bool operator==(const self& it)
                {
                        return _node == it._node;
                }


                Ptr operator->()
                {
                        return &_node->_data;
                }
        };     实现反向迭代器
template<class T, class Ref, class Ptr>
struct RListIterator
{
        typedef ListNode<T> Node;
        typedef RListIterator<T, Ref, Ptr> self;
        Node* _node;


        RListIterator(Node* node)
                :_node(node)
        {


        }


        self& operator++()
        {

                _node = _node->_prev;


                return *this;
        }


        self operator++(int)
        {
                self tmp(*this);
                _node = _node->_prev;


                return tmp;
        }


        self& operator--()
        {
                _node = _node->_next;


                return *this;
        }


        self operator--(int)
        {

                self tmp(*this);
                _node = _node->_next;


                return tmp;
        }


        Ref operator*()
        {
                return _node->_data;
        }


        bool operator!=(const self& it)
        {
                return _node != it._node;
        }


        bool operator==(const self& it)
        {
                return _node == it._node;
        }


        Ptr operator->()
        {
                return &_node->_data;
        }
};    实现控制list的类
https://i-blog.csdnimg.cn/direct/828ca22440c54ac78c1d7704a4709e58.png
https://i-blog.csdnimg.cn/direct/cbb2758579ba4520980adcdba5b4fc7d.png
template<class T>
class list
{
        typedef ListNode<T> Node;


public:
        typedef ListIterator<T, T&, T*> iterator;
        typedef RListIterator<T, T&, T*> reverse_iterator;
        typedef ListIterator<T, const T&, const T*> const_iterator;


        void empty_init()
        {
                _head = new Node();
                _head->_next = _head;
                _head->_prev = _head;
        }




        list()
        {
                empty_init();
        }



        list(const list<T>& it)
        {
                empty_init();
                for (const auto& e : it)
                //在范围for上加上引用,如果it内的元素体积很大的话可以减小代价,引用并不会导致浅拷贝
                //eg:int a=1;int& a1=a;int b=a1;变量b只是和a的值一样并没有指向同一块空间(int b=a;)
                {
                        push_back(e);
                }
        }


        list(initializer_list<T> il)
        {
                empty_init();
                for (const auto& e : il)
                {
                        push_back(e);
                }
        }


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


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


        list<T>& operator=(list<T> it)
        {
                std::swap(_head, it._head);


                return *this;
        }


        iterator begin()
        {
                return iterator(_head->_next);
        }


        const_iterator begin() const
        {
                return const_iterator(_head->_next);
        }


        iterator end()
        {
                return iterator(_head);
        }


        const_iterator end() const
        {
                return const_iterator(_head);
        }

        reverse_iterator rbegin()
        {
                return reverse_iterator(_head->_prev);
        }

        reverse_iterator rend()
        {
                return reverse_iterator(_head);
        }

        void push_back(const T& x)
        {
                //Node* newnode = new Node(x);
                //Node* tail = _head->_prev;


                //tail->_next = newnode;
                //newnode->_prev = tail;
                //newnode->_next = _head;
                //_head->_prev = newnode;
                insert(end(), x);


        }


        void pop_back()
        {
                erase(--end());
        }


        void push_front(const T& x)
        {
                insert(begin(), x);
        }


        void pop_front()
        {
                erase(begin());
        }


        iterator insert(iterator pos, const T& x)
        {
                Node* cur = pos._node;
                Node* newnode = new Node(x);
                Node* prev = cur->_prev;


                prev->_next = newnode;
                newnode->_prev = prev;
                newnode->_next = cur;
                cur->_prev = newnode;


                return iterator(newnode);
        }


        iterator erase(iterator pos)
        {
                assert(pos != end());


                Node* cur = pos._node;
                Node* prev = cur->_prev;
                Node* next = cur->_next;


                prev->_next = next;
                next->_prev = prev;


                delete cur;


                return iterator(next);
        }


private:
        Node* _head;
}; 完整list.h
#pragma once#include <assert.h>namespace wmm{        template<class T>        struct ListNode        {                ListNode<T>* _next;                ListNode<T>* _prev;                T _data;                ListNode(const T& data = T())                        :_next(nullptr)                        , _prev(nullptr)                        , _data(data)                {                }        };        template<class T, class Ref, class Ptr>        struct RListIterator        {                typedef ListNode<T> Node;                typedef RListIterator<T, Ref, Ptr> self;                Node* _node;                RListIterator(Node* node)                        :_node(node)                {                }                self& operator++()                {                        _node = _node->_prev;                        return *this;                }                self operator++(int)                {                        self tmp(*this);                        _node = _node->_prev;                        return tmp;                }                self& operator--()                {                        _node = _node->_next;                        return *this;                }                self operator--(int)                {                        self tmp(*this);                        _node = _node->_next;                        return tmp;                }                Ref operator*()                {                        return _node->_data;                }                bool operator!=(const self& it)                {                        return _node != it._node;                }                bool operator==(const self& it)                {                        return _node == it._node;                }                Ptr operator->()                {                        return &_node->_data;                }        };        template<class T, class Ref, class Ptr>
        struct ListIterator
        {
                typedef ListNode<T> Node;
                typedef ListIterator<T, Ref, Ptr> self;
                Node* _node;


                ListIterator(Node* node)
                        :_node(node)
                {


                }


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


                Ref operator*()
                {
                        return _node->_data;
                }


                bool operator!=(const self& it)
                {
                        return _node != it._node;
                }


                bool operator==(const self& it)
                {
                        return _node == it._node;
                }


                Ptr operator->()
                {
                        return &_node->_data;
                }
        };        template<class T>        class list        {                typedef ListNode<T> Node;        public:                typedef ListIterator<T, T&, T*> iterator;                typedef RListIterator<T, T&, T*> reverse_iterator;                typedef ListIterator<T, const T&, const T*> const_iterator;                void empty_init()                {                        _head = new Node();                        _head->_next = _head;                        _head->_prev = _head;                }                list()                {                        empty_init();                }                list(const list<T>& it)                {                        empty_init();                        for (const auto& e : it)                         //在范围for上加上引用,如果it内的元素体积很大的话可以减小代价,引用并不会导致浅拷贝                        //eg:int a=1;int& a1=a;int b=a1;变量b只是和a的值一样并没有指向同一块空间(int b=a;)                        {                                push_back(e);                        }                }                list(initializer_list<T> il)                {                        empty_init();                        for (const auto& e : il)                        {                                push_back(e);                        }                }                ~list()                {                        clear();                        delete _head;                        _head = nullptr;                }                void clear()                {                        auto it = begin();                        while (it != end())                        {                                it = erase(it);                        }                }                list<T>& operator=(list<T> it)                {                        std::swap(_head, it._head);                        return *this;                }                iterator begin()                {                        return iterator(_head->_next);                }                const_iterator begin() const                {                        return const_iterator(_head->_next);                }                iterator end()                {                        return iterator(_head);                }                const_iterator end() const                {                        return const_iterator(_head);                }                reverse_iterator rbegin()                {                        return reverse_iterator(_head->_prev);                }                reverse_iterator rend()                {                        return reverse_iterator(_head);                }                void push_back(const T& x)                {                        //Node* newnode = new Node(x);                        //Node* tail = _head->_prev;                        //tail->_next = newnode;                        //newnode->_prev = tail;                        //newnode->_next = _head;                        //_head->_prev = newnode;                        insert(end(), x);                }                void pop_back()                {                        erase(--end());                }                void push_front(const T& x)                {                        insert(begin(), x);                }                void pop_front()                {                        erase(begin());                }                iterator insert(iterator pos, const T& x)                {                        Node* cur = pos._node;                        Node* newnode = new Node(x);                        Node* prev = cur->_prev;                        prev->_next = newnode;                        newnode->_prev = prev;                        newnode->_next = cur;                        cur->_prev = newnode;                        return iterator(newnode);                }                iterator erase(iterator pos)                {                        assert(pos != end());                        Node* cur = pos._node;                        Node* prev = cur->_prev;                        Node* next = cur->_next;                        prev->_next = next;                        next->_prev = prev;                        delete cur;                        return iterator(next);                }        private:                Node* _head;        };        //遍历测试        void test()        {                list<int> l;                l.push_back(1);                l.push_back(2);                l.push_back(3);                l.push_back(4);                list<int>::iterator it = l.begin();                while (it != l.end())                {                        cout << *it << endl;                        ++it;                }        }        //结构体数据,重载符号->测试        struct pos        {                int _x;                int _y;                pos(int x = 0, int y = 0)                        :_x(x)                        , _y(y)                {                }        };        void test2()        {                list<pos> l;                struct pos* a = (struct pos*)malloc(sizeof(struct pos));                a->_x = 200;                a->_y = 200;                struct pos b;                b._x = 300;                b._y = 300;                l.push_back(pos(100, 100));                l.push_back(*a);                l.push_back(b);                list<pos>::iterator it = l.begin();                while (it != l.end())                {                        cout << (*it)._x << endl;                        cout << (*it)._y << endl;                        cout << it._node->_data._x << endl;                        cout << it._node->_data._y << endl;                        cout << it->_x << endl;                        cout << it->_y << endl;                        //想让迭代器it像结构体指针一样访问数据,重载了一个->符号                        ++it;                }        }        //erase insert 测试        void test3()        {                list<int> l;                l.push_back(1);                l.push_back(2);                l.push_back(3);                l.push_back(4);                list<int>::iterator it = l.begin();                it=l.erase(it);//注意迭代器失效问题                for (auto e : l)                {                        cout << e << endl;                }                cout << endl;                //it=l.begin();                l.insert(it, 1);                for (auto& e : l)                {                        cout << e << endl;                        e = 3;                }        }        //拷贝构造测试        void test4()        {                list<int> l;                l.push_back(1);                l.push_back(2);                l.push_back(3);                l.push_back(4);                for (auto e : l)                {                        cout << e << endl;                }                cout << endl;                list<int> l1(l);                for (auto e : l1)                {                        cout << e << endl;                }                cout << endl;                list<int>::iterator it = l1.begin();                *it = 0;                for (auto e : l)                {                        cout << e << endl;                }                cout << endl;                for (auto e : l1)                {                        cout << e << endl;                }                cout << endl;        }        //operator=测试        void test5()        {                list<int> l({ 1,2,3,4,5 });                list<int> l1 = { 1,2,3,4,6 };                l1 = l;                for (const auto& e : l)                {                        cout << e << endl;                }                cout << endl;                for (const auto& e : l1)                {                        cout << e << endl;                }                cout << endl;                list<int>::iterator it = l1.begin();                *it = 0;                for (const auto& e : l)                {                        cout << e << endl;                }                cout << endl;                for (const auto& e : l1)                {                        cout << e << endl;                }                cout << endl;        }    //反向迭代器测试        void test6()        {                list<int> l({ 1,2,3,4,5 });                list<int>::iterator it = l.begin();                while (it != l.end())                {                        cout << *it << endl;                        ++it;                }                list<int> l2({ 1,2,3,4,5 });                list<int>::reverse_iterator it1 = l2.rbegin();                while (it1 != l2.rend())                {                        cout << *it1 << endl;                        ++it1;                }        }} 3. list与vector的对比

vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构差别,导致其特性以及应用场景不 同,其主要差别如下:
https://i-blog.csdnimg.cn/direct/d1eb25f713ef443fbb0eb966e340e249.png
 下次再见~~很高兴帮助到你~~

如果有问题欢迎指正批评~~


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: C++ list【常用接口、模仿实现等】