【C++】list

目录

[list 的使用](#list 的使用)

[list 的构造函数](#list 的构造函数)

[list iterator的使用](#list iterator的使用)

[list capacity](#list capacity)

[list element access](#list element access)

[list modifiers](#list modifiers)

list的迭代器失效问题

[与 vector 的比较](#与 vector 的比较)

模拟实现


list 的使用

list 的构造函数

list iterator的使用

此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。

【注意】

  1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动

  2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

list capacity

list element access

list modifiers

splice 函数

作用:将 x 的所有(部分)结点转移到 position 位置之前(上面第二个重载函数是转移一个)(可以将自己的一部分转移到自己的另一部分)

示例:

cpp 复制代码
 for (int i=1; i<=4; ++i)
     mylist1.push_back(i);      // mylist1: 1 2 3 4

  for (int i=1; i<=3; ++i)
     mylist2.push_back(i*10);   // mylist2: 10 20 30

  it = mylist1.begin();
  ++it;                         // points to 2

  mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
                                // mylist2 (empty)
                                // "it" still points to 2 (the 5th element)

remove 函数

作用:找出某个值,把这个值所在的结点删除。如果没有这个值,不会报错。

示例:

cpp 复制代码
 int myints[]= {17,89,7,14};
  std::list<int> mylist (myints,myints+4);

  mylist.remove(89); // mylist : 17,7,14

list的迭代器失效问题

前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头双向循环链表 ,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

cpp 复制代码
void TestListIterator1()
{
     int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
     list<int> l(array, array+sizeof(array)/sizeof(array[0]));
     auto it = l.begin();
     while (it != l.end())
    {
         // erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给
         //其赋值
         l.erase(it); 
         ++it;
    }
}
// 改正
void TestListIterator()
{
     int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
     list<int> l(array, array+sizeof(array)/sizeof(array[0]));
     auto it = l.begin();
     while (it != l.end())
     {
         l.erase(it++); // it = l.erase(it);
     }
}

与 vector 的比较

模拟实现

cpp 复制代码
#include<iostream>
using namespace std;


namespace Mylist
{
    // List的节点类
    template<class T>
    struct ListNode
    {
        ListNode(const T& val = T())
        {
            _val = val;
        }
        
        ListNode<T>* _pPre;
        ListNode<T>* _pNext;
        T _val;
    };


    //List的迭代器类
    template<class T, class Ref, class Ptr>
    struct ListIterator
    {
        typedef ListNode<T>* PNode;
        typedef ListIterator<T, Ref, Ptr> Self;// Ref:T&,Ptr:T*
        ListIterator(PNode pNode = nullptr)
        {
            _pNode = pNode;
        }
        ListIterator(const Self& l)
        {
            _pNode = l._pNode;
        }
        Ref operator*()
        {
            return _pNode->_val;
        }
        
        //operator-> 的特殊规则
        //C++ 标准规定,operator-> 会被递归调用,直到返回一个
        //普通指针(或具有 operator-> 的类                                        
        //型),然后编译器会自动使用 -> 访问成员。
        Ptr operator->()
        {
            return &_pNode->_val;
        }
        Self& operator++()
        {
            return _pNode->_pNext;
        }
        Self operator++(int)
        {
            Self tmp = _pNode;
            _pNode = _pNode->_pNext;
            return tmp;
        }
        Self& operator--()
        {
            return _pNode->_pPre;
        }
        Self& operator--(int)
        {
            Self tmp = _pNode;
            _pNode = _pNode->_pPre;
            return tmp;
        }
        bool operator!=(const Self& l)
        {
            return _pNode != l._pNode;
        }
        bool operator==(const Self& l)
        {
            return _pNode == l._pNode;
        }
        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();
            _pHead->_pNext = _pHead;
            _pHead->_pPre = _pHead;
            sz = 0;
        }
        list(int n, const T& value = T())
        {
            CreateHead();
            _pHead->_pNext = _pHead;
            _pHead->_pPre = _pHead;
            sz = 0;
            while (n--)
            {
                push_back(value);
            }
        }
        template <class Iterator>
        list(Iterator first, Iterator last)
        {
            CreateHead();
            _pHead->_pNext = _pHead;
            _pHead->_pPre = _pHead;
            sz = 0;

            while (first != last)
            {
                push_back(*first);
                first++;
            }
        }
        list(const list<T>& l)
        {
            CreateHead();
            _pHead->_pNext = _pHead;
            _pHead->_pPre = _pHead;
            sz = 0;

            const_iterator it = l.begin();
            while (it != l.end())
            {
                push_back(*it);
                it++;
            }
        }
        list<T>& operator=(list<T> l)
        {
            swap(l);

            return *this;
        }
        ~list()
        {
            clear();
            delete _pHead;
        }


        ///////////////////////////////////////////////////////////////
        // List Iterator
        iterator begin()
        {
            return _pHead->_pNext;
        }
        iterator end()
        {
            return _pHead;
        }
        const_iterator begin() const
        {
            return _pHead->_pNext;
        }
        const_iterator end() const
        {
            return _pHead;
        }


        ///////////////////////////////////////////////////////////////
        // List Capacity
        size_t size()const
        {
            return sz;
        }
        bool empty()const
        {
            return sz == 0;
        }


        ////////////////////////////////////////////////////////////
        // 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)
        {
            Node* NewNode = new Node;
            NewNode->_val = val;

            Node* cur = pos._pNode;
            Node* prev = cur->_pPre;
            
            prev->_pNext = NewNode;
            NewNode->_pPre = prev;

            NewNode->_pNext = cur;
            cur->_pPre = NewNode;
            sz++;
            return NewNode;

        }
        // 删除pos位置的节点,返回该节点的下一个位置
        iterator erase(iterator pos)
        {
            Node* cur = pos._pNode;
            Node* prev = cur->_pPre;
            Node* next = cur->_pNext;
            
            prev->_pNext = next;
            next->_pPre = prev;

            delete cur;
            return next;
        }
        void clear()
        {
            iterator it = begin();
            while (it != end())
            {
                it = erase(it);
            }
            sz = 0;
        }
        void swap(list<T>& l)
        {
            iterator tmp = l._pHead;
            l._pHead = _pHead;
            _pHead = tmp._pNode;

            size_t tmp1 = l.sz;
            l.sz = sz;
            sz = tmp1;
        }
    private:
        void CreateHead()
        {
            _pHead = new Node;
        }
        PNode _pHead;
        size_t sz;
    };
};
相关推荐
二进制person13 分钟前
数据结构--双向链表
java·开发语言·数据结构·算法·链表
大树前端老司机18 分钟前
时空数据可视化新范式:基于Three.js的生产全流程时间轴回溯技术解析
开发语言·javascript·信息可视化·three.js
序属秋秋秋20 分钟前
《C++初阶之STL》【string类:详解 + 实现】
开发语言·c++·笔记·学习·stl
Cherl.39 分钟前
C++ <继承> 详解
开发语言·c++
小屁孩大帅-杨一凡1 小时前
在Python中,有多个库可以帮助我们将HTML转换为Markdow
开发语言·前端·python·html
清风丿缠绕心扉1 小时前
[C++11]范围for循环/using使用
c++
YxVoyager1 小时前
C++设计模式:单例模式 (现代C++主流实现方式Meyer‘s Singleton + 使用CRTP模板化)
c++·单例模式·设计模式
左手吻左脸。2 小时前
关于 URL 中 “+“ 号变成空格的问题
开发语言·javascript·ecmascript
Yu_Lijing3 小时前
ODB安装与使用
开发语言·c++·mysql
Python测试之道3 小时前
从零开始:用Python库轻松搭建智能AI代理
开发语言·人工智能·python