介绍
- list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
- list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
- list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
- 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
- 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)
list迭代器的实现
普通迭代器
template<class T>struct list_node{T _data;list_node<T>* _prev;list_node<T>* _next;list_node(const T& val = T()):_prev(nullptr),_next(nullptr),_data(val){}};template<class T>struct __list_iterator{typedef list_node<T> node;typedef __list_iterator<T> iterator;node* _node;__list_iterator(node* n):_node(n){}T& operator*(){return _node->_data;}iterator& operator++(){_node = _node->_next;return *this;}iterator operator++(int){iterator tmp(*this);_node = _node->_next;return tmp;}iterator& operator--(){_node = _node->_prev;return *this;}iterator operator--(int){iterator tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const iterator& it )const{return _node != it._node;}bool operator==(const iterator& it)const{return _node == it._node;}};
const迭代器
看下面这段代码能否编译通过
如果传一个const对象,那么就需要实现对应的const迭代器,否则会出现权限的放大,是会报错的。
如果声明成这样呢?
typedef const iterator const_iterator
这是错误的。这就相当于iterator本身是const,那么就不能执行++操作,迭代器不能动还叫啥迭代器。所以我们处理的方法是返回一个const迭代器,重新实现一个const_iterator类。基本都复用普通迭代器的代码,就解引用时返回const T&。
template<class T>struct __list_const_iterator{typedef list_node<T> node;typedef __list_const_iterator<T> const_iterator;node* _node;__list_const_iterator(node* n):_node(n){}const T& operator*(){return _node->_data;}const_iterator& operator++(){_node = _node->_next;return *this;}const_iterator operator++(int){const_iterator tmp(*this);_node = _node->_next;return tmp;}const_iterator& operator--(){_node = _node->_prev;return *this;}const_iterator operator--(int){const_iterator tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const const_iterator& it)const{return _node != it._node;}bool operator==(const const_iterator& it)const{return _node == it._node;}};
这样我们代码就不报错,顺利打印出了数据
成员函数屁股后的const
const iterator begin()const//后面的const修饰的是this指针指向的内容(*this),即_head本身不能被改变,指向对象的内容可变{return const iterator(_head->_next);}
改进代码
const迭代器还要去实现一个几乎相同的类,就改了个名字叫const_iterator,除了解引用返回T的引用时不同(const T&),那么我们在实现iterator迭代器类的时候加一个模版参数Ref表示引用,typedef不同的迭代器实例化不同的Ref即可解决。
不得不说想出这种写法的人真的是个天才
list反向迭代器位置
list迭代器失效
前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的**,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响**
list模拟实现代码
注意反向迭代器的实现是复用了正向迭代器
#include<iostream>
#include<cassert>namespace pqd
{template<class T>struct list_node{T _data;list_node<T>* _prev;list_node<T>* _next;list_node(const T& val = T()):_prev(nullptr),_next(nullptr),_data(val){}};template<class T,class Ref,class Ptr>struct __list_iterator{typedef list_node<T> node;typedef __list_iterator<T,Ref,Ptr> iterator;node* _node;__list_iterator(node* n):_node(n){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}iterator& operator++(){_node = _node->_next;return *this;}iterator operator++(int){iterator tmp(*this);_node = _node->_next;return tmp;}iterator& operator--(){_node = _node->_prev;return *this;}iterator operator--(int){iterator tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const iterator& it )const{return _node != it._node;}bool operator==(const iterator& it)const{return _node == it._node;}};template<class Iterator,class Ref,class Ptr>struct ReverseIterator{typedef ReverseIterator<Iterator,Ref,Ptr> Self;Iterator _cur;ReverseIterator(Iterator it):_cur(it){}Self& operator++(){--_cur;return *this;}Self& operator++(int){Iterator tmp(_cur);--_cur;return tmp;}Self& operator--(){++_cur;return *this;}Self& operator--(int){Iterator tmp(_cur);++_cur;return tmp;}Ref operator*(){Iterator tmp = _cur;--tmp;return *tmp;}bool operator!=(const Self& s){return _cur != s._cur;}};template<class T>class list{public:typedef __list_iterator<T,T&,T*> iterator;typedef __list_iterator<T,const T&,const T*> const_iterator;typedef ReverseIterator<iterator, T&, T*> reverse_iterator;typedef ReverseIterator<iterator, const T&, const T*> const_reverse_iterator;typedef list_node<T> node;void empty_init(){_head = new node;_head->_prev = _head;_head->_next = _head;}list(){empty_init();}template<class Iterator>list(Iterator first, Iterator last){empty_init();while (first != last){push_back(*first);++first;}}//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);}list(const list<T>& lt){empty_init();list<T> tmp(lt.begin(), lt.end());swap(tmp);}list<T>& operator=(list<T> lt){swap(lt);return *this;}iterator begin(){return iterator(_head->_next);}const_iterator begin()const//后面的const修饰的是this指针指向的内容(*this),即_head本身不能被改变,指向对象的内容可变{return const_iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator end()const{return const_iterator(_head);}reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}void push_back(const T& val){node* tail = _head->_prev;node* newnode = new node(val);tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;}void insert(iterator pos, const T& x){node* cur = pos._node;node* prev = cur->_prev;node* newnode = new node(x);prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;}iterator erase(iterator pos){assert(pos != end());node* prev = pos._node->_prev;node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;return iterator(next);}void pop_back(){erase(--end());}void clear()//不清理头节点{iterator it = begin();while (it != end()){it=erase(it);//或者erase(it++);返回的是it++前的拷贝it++;}}~list(){clear();delete _head;_head = nullptr;}private:node* _head;};struct AA{int _a1;int _a2;AA(int a1=0,int a2=0):_a1(a1),_a2(a2){}};void test_list2(){list<AA> lt;lt.push_back(AA(1, 2));lt.push_back(AA(1, 3));lt.push_back(AA(1, 4));list<AA>::iterator it = lt.begin();while (it != lt.end()){std::cout << it->_a1 << ":" << it->_a2 << std::endl;it++;}lt.clear();}void print_list(const list<int>& lt){list<int>::const_iterator it = lt.begin();while (it != lt.end()){std:: cout << *it << " ";++it;}}void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);print_list(lt);}void test_list3(){list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);list<int> lt2(lt1);for (auto e : lt2){std::cout << e << std::endl;}}void test_list4(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(5);auto rit =lt.rbegin();while (rit != lt.rend()){std::cout << *rit << " ";++rit;}}
}