目录
list模拟实现
list节点
list的push_back()函数
list的迭代器操作(非const)
list的迭代器操作(const)
list迭代器const 非const优化
list的insert()函数
list的erase()函数
list的pop_back() push_front() pop_front()
list的clear()函数
list的empty()_Init函数与构造函数
list的拷贝构造
list的析构函数
list的赋值运算符重载
list的initializer_list
项目文件
4.list与vector的对比
list模拟实现
list节点
首先看节点:list底层是一个带头双向循环链表
template <class T>
class list_Node{
public:T _data;list_Node<T>* _prev;list_Node<T>* _next;list_Node(const T& data):_data(data),_prev(nullptr),_next(nullptr){}
};template <class T>
class list{
public:typedef list_Node<T> Node;list(){_head = new Node(T());//不能使用0初始化,因为类型不确定_head->_next = _head;_head->_prev = _head;}private:Node* _head;
}; 
}list的push_back()函数
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);
}list的迭代器操作(非const)
list在物理上空间不是连续的,因此不可以像vector一样使用
typedef Node* iterator
Node* 不符合遍历的行为
List_iterator封装Node*
再通过重载运算符控制它的行为
因此这里我们可以使用一个类来封装使用
template <class T>
class List_iterator{
public:typedef list_Node<T> Node;typedef List_iterator Self;//不需要写析构函数,这个节点又不是这个类的//一个类一般不写析构,也就不需要显示写深拷贝List_iterator(Node* node):_node(node){}//日期类返回一个日期,那么迭代器返回一个迭代器//++itSelf& operator++(){_node = _node->_next;return *this;}//--itSelf& operator--(){_node = _node->_prev;return *this;}//it++Self operator++(int)//加参数 区分前置后置{Self tmp(*this);_node = _node->_next;return tmp;}//it--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}T& operator*(){return _node->_data;}bool operator!=(const Self& it){return _node != it._node;}bool operator==(const Self& it){return _node == it._node;}T* operator->(){return &(_node->_data);}
private:Node* _node;};
注意: T* operator->()的意义,比如下面的例子
    struct Pos{int _x;int _y;Pos(int x = 0,int y = 0):_x(x),_y(y){}};nanyi::list<Pos> ls2;ls2.push_back(Pos(100,200));ls2.push_back(Pos(300,400));ls2.push_back(Pos(500,600));nanyi::list<Pos>::iterator it1 = ls2.begin();while (it1 != ls2.end()) {//cout << (*it1)._x << ":" << (*it1)._y << endl;// 为了可读性,省略了一个->cout << it1->_x << ":" << it1->_y << endl;//cout << it1.operator->()->_row << ":" << it1.operator->()->_col << endl;++it1;}cout << endl;return 0;list类中
iterator begin(){//iterator it(_head->_next);//return it;return iterator(_head->_next);
}iterator end(){return iterator(_head);
}list的迭代器操作(const)
const迭代器不能在普通迭代器前加const修饰,比如这种情况
const迭代器的目标是 迭代器本身可以修改,指定的内容不能修改,类似const T* p

一旦加了不可以使用++it
因此我们重新写一个const类进行封装,我们只需改变解引用即可,使得指向内容不能修改


template <class T>
class const_List_iterator{
public:typedef list_Node<T> Node;typedef const_List_iterator Self;//不需要写析构函数,这个节点又不是这个类的//一个类一般不写析构,也就不需要显示写深拷贝const_List_iterator(Node* node):_node(node){}//日期类返回一个日期,那么迭代器返回一个迭代器//++itSelf& operator++(){_node = _node->_next;return *this;}//--itSelf& operator--(){_node = _node->_prev;return *this;}//it++Self operator++(int)//加参数 区分前置后置{Self tmp(*this);_node = _node->_next;return tmp;}//it--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}const T& operator*(){return _node->_data;}bool operator!=(const Self& it){return _node != it._node;}bool operator==(const Self& it){return _node == it._node;}const T* operator->(){return &(_node->_data);}
private:Node* _node;}; list类中
   const_iterator begin()const{return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}代码是没有问题的,但是我们也可以发现,这样非常的冗余 有些函数是没有变化的,确多写了一遍,有没有什么办法能解决这种冗余呢?
他们的区别主要是返回参数不同,返回是否有const对象
因此我们可以增加模版参数,让编译器完成任务
list迭代器const 非const优化

template <class T,class Ref,class Ptr>
class List_iterator{
public:typedef list_Node<T> Node;typedef List_iterator Self;//不需要写析构函数,这个节点又不是这个类的//一个类一般不写析构,也就不需要显示写深拷贝List_iterator(Node* node):_node(node){}//日期类返回一个日期,那么迭代器返回一个迭代器//++itSelf& operator++(){_node = _node->_next;return *this;}//--itSelf& operator--(){_node = _node->_prev;return *this;}//it++Self operator++(int)//加参数 区分前置后置{Self tmp(*this);_node = _node->_next;return tmp;}//it--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);}
private:Node* _node;};list的insert()函数
    iterator insert(iterator pos , const T& x){Node* cur = pos._node;Node* newnode = new Node(x);Node* prev = cur->_prev;newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;cur->_prev  = newnode;return iterator(newnode);}由于不牵涉扩容问题 这里不存在迭代器失效
list的erase()函数
    iterator erase(iterator pos){assert(pos);Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;// prev cur nextprev->_next = next;next->_prev = prev;delete cur;cur = nullptr;return iterator(next);}这里存在迭代器失效,因此我们和库里一样返回下一个节点迭代器
list的pop_back() push_front() pop_front()
    void pop_back(){erase(--end());}void push_front(const T& x){insert(begin(), x);}void pop_front(){erase(begin());}list的clear()函数
    void clear(){auto it = begin();while (it != end()) {it = erase(it);//不能++it,首先会迭代器失效,其次erase会自动返回下一个位置}}list的empty()_Init函数与构造函数
由于我们经常使用申请头节点,因此我们把头节点封装成一个函数,便于调用
    void empty_Init(){_head = new Node(T());//不能使用0初始化,因为类型不确定_head->_next = _head;_head->_prev = _head;}list(){empty_Init();}list的拷贝构造
如果我们不显示写拷贝构造 ,那么编译器会默认生成一个浅拷贝

浅拷贝生成的ls2,与ls1的地址相同,对ls1操作也会对ls2有影响
因此我们需要显示的写拷贝构造
    //拷贝构造list(const list<T>& ls){empty_Init();for (const auto& e : ls) {//范围for不确定类型,加引用push_back(e);}}
list的析构函数
    ~list(){clear();delete _head;_head = nullptr;}list的赋值运算符重载
    //ls2 = ls1list<T>& operator=(list<T> ls){std::swap(_head, ls._head);return *this;}
list的initializer_list
可以将花括号内容,直接赋值给对象

    list (initializer_list<T> il){empty_Init();for (const auto& e : il) {push_back(e);}}项目文件
//
//  list.hpp
//  List
//
//  Created by 南毅 on 2024/5/28.
//#include <iostream>
using namespace std;namespace nanyi {
template <class T>
class list_Node{
public:T _data;list_Node<T>* _prev;list_Node<T>* _next;list_Node(const T& data):_data(data),_prev(nullptr),_next(nullptr){}
};template <class T,class Ref,class Ptr>
class List_iterator{
public:typedef list_Node<T> Node;typedef List_iterator Self;//不需要写析构函数,这个节点又不是这个类的//一个类一般不写析构,也就不需要显示写深拷贝List_iterator(Node* node):_node(node){}//日期类返回一个日期,那么迭代器返回一个迭代器//++itSelf& operator++(){_node = _node->_next;return *this;}//--itSelf& operator--(){_node = _node->_prev;return *this;}//it++Self operator++(int)//加参数 区分前置后置{Self tmp(*this);_node = _node->_next;return tmp;}//it--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);}
public:Node* _node;};//template <class T>
//class const_List_iterator{
//public:
//    typedef list_Node<T> Node;
//    typedef const_List_iterator Self;
//    
//    //不需要写析构函数,这个节点又不是这个类的
//    //一个类一般不写析构,也就不需要显示写深拷贝
//    const_List_iterator(Node* node)
//    :_node(node)
//    {
//        
//    }
//    
//    //日期类返回一个日期,那么迭代器返回一个迭代器
//    //++it
//    Self& operator++(){
//        _node = _node->_next;
//        return *this;
//    }
//    //--it
//    Self& operator--(){
//        _node = _node->_prev;
//        return *this;
//    }
//    //it++
//    Self operator++(int)//加参数 区分前置后置
//    {
//        Self tmp(*this);
//        _node = _node->_next;
//        return tmp;
//    }
//    //it--
//    Self operator--(int){
//        Self tmp(*this);
//        _node = _node->_prev;
//        return tmp;
//    }
//    
//    
//    const T& operator*(){
//        return _node->_data;
//    }
//    
//    bool operator!=(const Self& it){
//        return _node != it._node;
//    }
//    
//    bool operator==(const Self& it){
//        return _node == it._node;
//    }
//    
//    const T* operator->(){
//        return &(_node->_data);
//    }
//private:
//    Node* _node;
//    
//};template <class T>
class list{
public:typedef list_Node<T> Node;typedef List_iterator<T,T&,T*> iterator;typedef List_iterator<T,const T&,const T*> const_iterator;//typedef const_List_iterator<T> const_iterator;void empty_Init(){_head = new Node(T());//不能使用0初始化,因为类型不确定_head->_next = _head;_head->_prev = _head;}list(){empty_Init();}void clear(){auto it = begin();while (it != end()) {it = erase(it);//不能++it,首先会迭代器失效,其次erase会自动返回下一个位置}}//拷贝构造list(const list<T>& ls){empty_Init();for (const auto& e : ls) {push_back(e);}}//析构~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;insert(end(), x);}void pop_back(){erase(--end());}void push_front(const T& x){insert(begin(), x);}void pop_front(){erase(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);}iterator insert(iterator pos , const T& x){Node* cur = pos._node;Node* newnode = new Node(x);Node* prev = cur->_prev;newnode->_next = cur;newnode->_prev = prev;prev->_next = newnode;cur->_prev  = newnode;return iterator(newnode);}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;// prev cur nextprev->_next = next;next->_prev = prev;delete cur;cur = nullptr;return iterator(next);}//ls2 = ls1list<T>& operator=(list<T> ls){std::swap(_head, ls._head);return *this;}list (initializer_list<T> il){empty_Init();for (const auto& e : il) {push_back(e);}}
public:Node* _head;
};
}4.list与vector的对比
vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及应用场景不同,其主要不同如下:
