【C++/STL】list(常见接口、模拟实现、反向迭代器、)

简介: 【C++/STL】list(常见接口、模拟实现、反向迭代器、)

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

list的常见接口

对迭代器的封装

因为list的空间不是连续的,不能用原生指针,必须对其进行封装。

节点

重载->

当数据是自定义类型时,想通过->访问,就必须重载。

const迭代器

用const迭代器,需要重新弄一个类,而const迭代器跟普通迭代器基本一样,只修改了部分,如果为此就重新弄一个类,代码就太冗余了。

 下面是进行的优化:

本质相当于写了一个类模板,编译器实例化生成了两个类。

list与vector的对比

反向迭代器

反向迭代器的++就是正向迭代器的--,反向迭代器的--就是正向迭代器的++,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行 包装即可。

反向迭代器完整代码

#pragma once 
 
//所以容器的反向迭代器
//迭代器适配器
namespace qjh
{
    //vector<T>::iterator
    template<class Iterator,class Ref,class Ptr>  //给谁的正向迭代器,就适配出对应的反向迭代器
    struct ReverseIterator   
    {
        typedef ReverseIterator<Iterator, Ref, Ptr> Self;
 
        Iterator _it;
        
        ReverseIterator(Iterator it)
            :_it(it)
        {}
 
        Ref operator*()
        {
            Iterator tmp = _it;  //不能修改_it,得用临时变量放回
            return *(--tmp);
        }
 
        Ptr operator->()
        {
            //return _it->;
            //return _it.operator->();
            return &(operator*());
        }
 
        Self& operator++()
        {
            --_it;
            return *this;
        }
 
        Self& operator--()
        {
            ++_it;
            return *this;
        }
 
        bool operator!=(const Self& s)
        {
            return _it != s._it;
        }
    };
}

list完整代码

#pragma once
#include<assert.h>
 
#include"ReverseIterator.h" 
 
namespace qjh
{
    template<class T>
    struct ListNode   //需要全部被公开,用struct
    {
        ListNode<T>* _next;
        ListNode<T>* _prev;
        T _data;
 
        ListNode(const T& x=T())
            :_next(nullptr)
            ,_prev(nullptr)
            ,_data(x)
        {}
    };
 
    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)
        {}
 
        //*it
        //T& operator*()
        Ref operator*()
        { 
            return _node->_data;
        }
 
        //T* operator->()
        Ptr operator->()
        {
            return  &_node->_data;
        }
 
        //++it
        Self& operator++()
        {
            _node = _node->_next;
            return *this;
        }
 
        //it++
        Self& operator++(int)
        {
            Self tmp(*this);
            _node = _node->_next;
            return tmp;
        }
 
        //--it
        Self& operator--()
        {
            _node = _node->_prev;
            return *this;
        }
 
        //it--
        Self& operator--(int)
        {
            Self tmp(*this);
            _node = _node->_prev;
            return tmp;
        }
 
        bool operator!=(const Self& it)
        {
            return _node != it._node;
        }
 
        bool operator==(const Self& it)
        {
            return _node == it._node;
        }
    };
 
    //template<class T>
    //struct ListConstIterator    //对指针进行封装,因为结点的空间不是连续的
    //{
    //  typedef ListNode<T> Node;
    //  typedef ListConstIterator<T> Self;
 
    //  Node* _node;
 
    //  ListConstIterator(Node* node)
    //      :_node(node)
    //  {}
 
    //  //*it
    //  const T& operator*()
    //  {
    //      return _node->_data;
    //  }
 
    //  const T* operator->()
    //  {
    //      return  &_node->_data;
    //  }
 
    //  //++it
    //  Self& operator++()
    //  {
    //      _node = _node->_next;
    //      return *this;
    //  }
 
    //  //it++
    //  Self& operator++(int)
    //  {
    //      Self tmp(*this);
    //      _node = _node->_next;
    //      return tmp;
    //  }
 
    //  //--it
    //  Self& operator--()
    //  {
    //      _node = _node->_prev;
    //      return *this;
    //  }
 
    //  //it--
    //  Self& operator--(int)
    //  {
    //      Self tmp(*this);
    //      _node = _node->_prev;
    //      return tmp;
    //  }
 
    //  bool operator!=(const Self& it)
    //  {
    //      return _node != it._node;
    //  }
 
    //  bool operator==(const Self& it)
    //  {
    //      return _node == it._node;
    //  }
    //};
 
    template<class T>
    class list
    {
        typedef ListNode<T> Node;
    public:
        /*typedef ListIterator<T> iterator;
        typedef ListConstIterator<T> const_iterator;*/
 
        typedef ListIterator<T,T&,T*> iterator;
        typedef ListIterator<T,const T&,const T*> const_iterator;
 
        typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
        typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;
 
 
        reverse_iterator rbegin()
        {
            return reverse_iterator(end());
        }
 
        reverse_iterator rend()
        {
            return reverse_iterator(begin());
        }
 
        iterator begin()
        {
            return iterator(_head->_next);
        }
 
        iterator end()
        {
            return iterator(_head);
        }
 
        //const迭代器需要迭代器指向的内容不能修改!const iterator不是我们需要的const迭代器
        //const 迭代器本身可以++等操作
        const_iterator begin() const
        {
            return const_iterator(_head->_next);
        }
 
        const_iterator end() const
        {
            return const_iterator(_head);
        }
 
        void empty_init()
        {
            _head = new Node;
            _head->_next = _head;
            _head->_prev = _head;
 
            _size = 0;
        }
 
        list()
        {
            empty_init();
        }
 
        list(initializer_list<int> il)
        {
            empty_init();
 
            for (auto& e : il)
            {
                push_back(e);
            }
        }
 
        //lt2(lt1)
        list(const list<T>& lt)
        {
            empty_init();
            for (auto& e : lt)
            {
                push_back(e);
            }
        }
 
        void swap(list<T>& lt)
        {
            std::swap(_head, lt._head);
            std::swap(_size, lt._size);
        }
 
        //lt1=lt3
        list<T>& operator=(list<T> lt)
        {
            swap(lt);
            return *this;
        }
 
        void clear()
        {
            iterator it = begin();
            while (it != end())
            {
                it = erase(it);
            }
        }
 
        ~list()
        {
            clear();
            delete _head;
            _head = nullptr;
        }
 
 
        //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;
        //}
 
        void push_back(const T& x)
        {
            insert(end(), x);
        }
 
        void push_front(const T& x)
        {
            insert(begin(), x);
        }
 
        void pop_back()
        {
            erase(--end());//迭代器不能-1,只能用-- 
        }
 
        void pop_front()
        {
            erase(begin());
        }
 
        void insert(iterator pos, const T& val)
        {
            Node* cur = pos._node;
            Node* newnode = new Node(val);
            Node* prev = cur->_prev;
 
            prev->_next = newnode;
            newnode->_prev = prev;
            newnode->_next = cur;
            cur->_prev = newnode;
            _size++;
        }
 
        iterator erase(iterator pos) //节点失效了,需要返回下一个节点
        {
            Node* cur = pos._node;
            Node* prev = cur->_prev;
            Node* next = cur->_next;
 
            prev->_next = next;
            next->_prev = prev;
            delete cur;
            _size--;
            return iterator(next); //匿名对象
        }
 
        size_t size() const
        {
            return _size;
        }
 
        bool empty()
        {
            return _size == 0;
        }
 
    private:
        Node* _head;
        size_t _size;
    };
 
 
    void test_list1()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        lt.push_back(4);
        lt.push_back(5);
 
        list<int>::iterator it = lt.begin();
        while (it != lt.end())
        {
            cout << *it << " ";
            ++it;
        }
        cout << endl;
 
        lt.push_front(10);
        lt.push_front(20);
        lt.push_front(30);
 
        for (auto e : lt)
        {
            cout << e << " ";
        }
        cout << endl;
 
        lt.pop_back();
        lt.pop_back();
        lt.pop_front();
        lt.pop_front();
 
        for (auto e : lt)
        {
            cout << e << " ";
        }
        cout << endl;
 
    }
 
    struct A
    {
        int _a1;
        int _a2;
 
        A(int a1 = 0, int a2 = 0)
            :_a1(a1)
            ,_a2(a2)
        {}
    }; 
 
    void test_list2()
    {
        list<A> lt;
        A aa1(1, 1);
        A aa2 = { 1, 1 };
 
        lt.push_back(aa1);
        lt.push_back(aa2);
        lt.push_back(A(2,2));
        lt.push_back({3,3});
        lt.push_back({4,4});
 
        list<A>::iterator it = lt.begin();
        while (it != lt.end())
        { 
            //cout << (*it)._a1 << ":" << (*it)._a2 << endl;
            //cout << it->_a1 << ":" << it->_a2 << endl;    //如果要遍历自定义类型,就要重载->,编译器为了可读性,省略了一个->
            cout << it.operator->()->_a1 << ":" << it.operator->()->_a2 << endl;
            ++it;
        }
        cout << endl;
    }
 
    void PrintList(const list<int>& clt)
    {
        list<int>::const_iterator it = clt.begin();
        while (it != clt.end())
        {
            //*it += 10; 
 
            cout << *it << " ";
            ++it;
        }
        cout << endl;
    }
 
    void test_list3()
    {
        list<int> lt;
        lt.push_back(1);
        lt.push_back(2);
        lt.push_back(3);
        lt.push_back(4);
        lt.push_back(5);
 
        PrintList(lt);
 
        list<int> lt1(lt);
        PrintList(lt1);
 
    }
}


目录
相关文章
|
4月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
110 2
|
4月前
|
存储 算法 C++
【c++丨STL】map/multimap的使用
本文详细介绍了STL关联式容器中的`map`和`multimap`的使用方法。`map`基于红黑树实现,内部元素按键自动升序排列,存储键值对,支持通过键访问或修改值;而`multimap`允许存在重复键。文章从构造函数、迭代器、容量接口、元素访问接口、增删操作到其他操作接口全面解析了`map`的功能,并通过实例演示了如何用`map`统计字符串数组中各元素的出现次数。最后对比了`map`与`set`的区别,强调了`map`在处理键值关系时的优势。
219 73
|
4月前
|
存储 算法 C++
【c++丨STL】set/multiset的使用
本文深入解析了STL中的`set`和`multiset`容器,二者均为关联式容器,底层基于红黑树实现。`set`支持唯一性元素存储并自动排序,适用于高效查找场景;`multiset`允许重复元素。两者均具备O(logN)的插入、删除与查找复杂度。文章详细介绍了构造函数、迭代器、容量接口、增删操作(如`insert`、`erase`)、查找统计(如`find`、`count`)及`multiset`特有的区间操作(如`lower_bound`、`upper_bound`、`equal_range`)。最后预告了`map`容器的学习,其作为键值对存储的关联式容器,同样基于红黑树,具有高效操作特性。
156 3
|
5月前
|
存储 算法 C++
【c++丨STL】priority_queue(优先级队列)的使用与模拟实现
本文介绍了STL中的容器适配器`priority_queue`(优先级队列)。`priority_queue`根据严格的弱排序标准设计,确保其第一个元素始终是最大元素。它底层使用堆结构实现,支持大堆和小堆,默认为大堆。常用操作包括构造函数、`empty`、`size`、`top`、`push`、`pop`和`swap`等。我们还模拟实现了`priority_queue`,通过仿函数控制堆的类型,并调用封装容器的接口实现功能。最后,感谢大家的支持与关注。
214 1
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
1216 1
|
12月前
|
Java API Apache
怎么在在 Java 中对List进行分区
本文介绍了如何将列表拆分为给定大小的子列表。尽管标准Java集合API未直接支持此功能,但Guava和Apache Commons Collections提供了相关API。
171 1
|
12月前
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
存储 安全 Java
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
170 3
|
Java API
使用 Java 来实现两个 List 的差集操作
使用 Java 来实现两个 List 的差集操作
481 3
|
存储 Java 索引
Java List接口实现原理与性能评估
Java List接口实现原理与性能评估
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等