【STL】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来说这可能是一个重要的因素)

list的迭代器失效

迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

list<int>::iterator it = l.begin();
     while(it != l.end())
     {
         if(*it % 2 == 0)
        {
        	//l.erase(it)(错误)
        	//it++ 
        	//erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给其赋值
            it = l.erase(it);  
         }
         else                     //(正确) 
         {
             ++it;
         }
         //因为标准库的erase返回值是迭代器,而返回的迭代器是被删除元素的下一个迭代器.这样也就不会有野指针的问题了。
     }

实现的接口

list节点类

    struct ListNode
    {
        ListNode<T>* _prev;
        ListNode<T>* _next;
        T _val;
        ListNode(const T& val = T())
            : _val(val)
            , _prev(nullptr)
            , _next(nullptr)
        {}
    };

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)ListIterator(const iterator& l);
    Ref operator*();
    Ptr* operator->();
    iterator& operator++();
    iteratoroperator++(int);
    iterator& operator--();
    iterator& operator--(int);
    bool operator!=(const iterator& l)bool operator==(const iterator& l)private:
    PNode _pNode;
  };

//反向迭代器
    template<class Iterator, class Ref, class Ptr>
    struct reverse_ListIterator {
        typedef reverse_ListIterator<Iterator, Ref, Ptr> reverse_iterator;
        reverse_ListIterator(Iterator cur)
        reverse_iterator& operator++()
        reverse_iterator& operator--()
        Ref operator*() 
        Ptr* operator->()
        bool operator==(const reverse_iterator& l)
        bool operator!=(const reverse_iterator& l) 
        Iterator _cur;
    };

默认成员函数部分

    list();
    list(int n, const T& value = T());
    template <class Iterator>
    list(Iterator first, Iterator last);
    list(const list<T>& l);
    list<T>& operator=(const list<T> l);
    ~list();

迭代器部分

    iterator begin();
    iterator end();
    const_iterator begin();
    const_iterator end();

容量部分

	size_t size()const;
    bool empty()const;

访问部分

    T& front();
    const T& front()const;
    T& back();
    const T& back()const;

修改部分

    void push_back(const T& val){insert(begin(), 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);
    // 删除pos位置的节点,返回该节点的下一个位置
    iterator erase(iterator pos);
    void clear();
    void swap(List<T>& l);

代码实现

#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
namespace lc
{
    // List的节点类
    template<class T>
    struct ListNode
    {
        ListNode<T>* _prev;
        ListNode<T>* _next;
        T _val;
        ListNode(const T& val = T())
            : _val(val)
            , _prev(nullptr)
            , _next(nullptr)
        {}
    };
    //反向迭代器
    template<class Iterator, class Ref, class Ptr>
    struct reverse_ListIterator {
        typedef reverse_ListIterator<Iterator, Ref, Ptr> reverse_iterator;
        reverse_ListIterator(Iterator cur)
            :_cur(cur)
        {}
        reverse_iterator& operator++() {
            --_cur;
            return *this;
        }
        reverse_iterator& operator--() {
            ++_cur;
            return *this;
        }
        it++
        //reverse_iterator& operator++(int) {
        //    auto tmp = *this;
        //    _cur--;
        //    return *tmp;;
        //}
        it--
        //reverse_iterator& operator++(int) {
        //    auto tmp = *this;
        //    _cur++;
        //    return *this;
        //}
        Ref operator*() {
            auto tmp = _cur;
            --tmp;
            return *tmp;
        }
        Ptr* operator->() {
            return &(operator*());
        }
        
        bool operator==(const reverse_iterator& l) {
            return _cur == l._cur;
        }
        bool operator!=(const reverse_iterator& l) {
            return _cur != l._cur;
        }
        Iterator _cur;

    };
    //正向迭代器
    template<class T, class Ref, class Ptr>
    class ListIterator
    {
          typedef ListNode<T>* PNode;
          typedef ListIterator<T, Ref, Ptr> iterator;

          
    public:
          ListIterator (PNode node = nullptr) 
              :_node(node)
          {}
          
          ListIterator (const iterator& l) {
              _node = l._node;
          }
              
           Ref operator*() {
              return _node->_val;
          }
          
           Ptr* operator->() {
               return &(operator*());
           }
          //++it
          iterator& operator++() {
              _node = _node->_next;
              return *this;
          }
          //it++
          iterator& operator++(int) {
              iterator tmp(*this);
              _node = _node->_next;
              return tmp;
          }
          //--it
          iterator& operator--() {
              _node = _node->_prev;
              return *this;
          }
          iterator& operator--(int) {
              iterator tmp(*this);
              _node = _node->_prev;
              return *this;
          }
          bool operator!=(const iterator& l) {
              return _node != l._node;
          }
          //lt1 == lt2
          bool operator==(const iterator& l) {
              return _node == l._node;
          }
    
          PNode _node;
    };
    //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;
        typedef reverse_ListIterator<iterator, T&, T*> reverse_iterator;
        typedef reverse_ListIterator<const_iterator, const T&, const T*> const_reverse_iterator;
    public:

        //List的构造
        list() {
            CreateHead();
        }
        //构造的list中包含n个值为val的元素
        list(int n, const T& value = T()) {
            CreateHead();
            while (n--) {
                push_back(value);
            }
        }
        template <class Iterator>
        //list<int> lt1(lt.begin(), lt.end());
        list(Iterator first, Iterator last) {
            CreateHead();
            while (first != last) {
                push_back(*first);
                first++;
            }
        }
        //list<int> lt1(lt2)
        list(const list<T>& l) {
            CreateHead();
            list<int> tmp(l.begin(), l.end());
            this->swap(tmp);
            //list(l.begin(), l.end());
        }
        //lt3 = lt2
        list<T>& operator=(list<T> l) {
            
            swap(l);
            return *this;
        }
        ~list() {
            clear();
            delete _head;
            _head = nullptr;
        }
        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_iterator begin() const {
            return const_iterator(_head->_next);
        }
        const_iterator end() const {
            return const_iterator(_head);
        }
        size_t size() const{
            size_t count = 0;
            list<int>::const_iterator it = (*this).begin();
            while (it != (*this).end()) {
                count++;
                it++;
            }
            return count;
        }
        bool empty() const{
            return size() == 0;
        }

        T& front()  {
            return _head->_next->_val;
        }
        const T& front()const {
            return _head->_next->_val;
        }
        T& back() {
            return _head->_prev->_val;
        }
        const T& back()const {
            return _head->_prev->_val;
        }
        void push_back(const T& val) { 
              //Node* cur = new Node(val);
              //Node* prev = _head->_prev;
              //prev->_next = cur;
              //cur->_prev = prev;
              //_head->_prev = cur;
              //cur->_next = _head;
              
              insert(end(), val);
          }
        void pop_back() { 

            erase(--end()); 
        }
        void push_front(const T& val) {
            insert(begin(), val);
 /*           PNode cur = new Node(val);
            _head->_next->_prev = cur;
            cur->_next = _head->_next;
            _head->_next = cur;
            cur->_prev = _head;*/   
        }
        void pop_front(){
            //PNode next = _head->_next->_next;
            //delete _head->_next;
            //_head->_next = next;
            //next->_prev = _head;
            erase(begin());
        }
//        // 在pos位置前插入值为val的节点
        iterator insert(iterator pos, const T& val) {
            PNode cur = new Node(val);
            PNode prev = pos._node->_prev;
            prev->_next = cur;
            cur->_prev = prev;
            cur->_next = pos._node;
            pos._node->_prev = cur;
            return iterator(cur);
        }
//        // 删除pos位置的节点,返回该节点的下一个位置
         iterator erase(iterator pos) {
             assert(pos._node != _head);
             PNode prev = pos._node->_prev;
             PNode next = pos._node->_next;
             prev->_next = next;
             next->_prev = prev;
             delete pos._node;
             return iterator(next);
         }
         void clear() {
             list<T>::iterator it = begin();
             while (it != end()) {
                 it = erase(it);
    
             }
            
         }
          // swap(lt2)
          void swap(list<T>& l)  {
              std::swap(_head, l._head);
        }
    private:
        void CreateHead() {
            _head = new Node;
            _head->_prev = _head;
            _head->_next = _head;
        }
        PNode _head;
    };

list与vector的对比

vector和数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随机存取(即使用[]操作符访问其中的元素),但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝(复杂度是O(n)),另外,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。
list是由数据结构中的双向链表实现的,因此它的内存空间可以是不连续的。因此只能通过指针来进行数据的访问,这个特点使得它的随机存取变的非常没有效率,需要遍历中间的元素,搜索复杂度O(n),因此它没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除和插入。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁华的梦境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值