C++:STL——list
一简介
底层是一个带头双向循环列表
二、成员函数
(1)构造函数
三、迭代器
四、修饰函数
(1)insert
插入和删除不再使用下标,而是使用迭代器指针作为要插入位置的形参,这是因为:vector是连续的,但list不是连续的
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
int main()
{list<int> lt2(7, 5);for (auto& e : lt2){cout << e << " ";}cout << endl;list<int>::iterator it = lt2.begin();for (int i = 0; i < 3; i++){it++;}//在第四个元素之前插入一个30lt2.insert(it, 30);for (auto& e : lt2){cout << e << " ";}cout << endl;//这里的it是第五个元素(返回it之后一个元素的迭代器)//在第五个元素之前插入6个8lt2.insert(it, 6, 8);for (auto& e : lt2){cout << e << " ";}cout << endl;return 0;
}
上面可以写,下面不可以写,因为list的元素在内存上不连续
list库不接受+的运算符重载,但支持++,所以这样写:
这也实现了在下标为5的地方加入元素 ,它的插入代价极低,前后关系一改就插入了,不需要遍历
list不提供find,vector也没有,但都可以借用算法库中的find进行元素查找(通过迭代器把容器和算法联系起来,并且不暴露容器底层的结构)
这个是算法库中的find函数
通过算法库的find函数找到3,并在它的前面插入30
因为不涉及数据的挪动,没有扩容,所以insert不存在迭代器失效问题
(2)erase
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
int main()
{list<int> lt2;lt2.push_back(1);lt2.push_back(2);lt2.push_back(3);lt2.push_back(4);lt2.push_back(5);lt2.push_back(6);for (auto& e : lt2){cout << e << " ";}cout << endl;list<int>::iterator it = lt2.begin();for (int i = 0; i < 3; i++){it++;}//删除第四个元素lt2.erase(it);for (auto& e : lt2){cout << e << " ";}cout << endl;list<int>::iterator it1 = lt2.begin();list<int>::iterator it2 = lt2.end();it1++;it2--;//删除[2,n-1]这个区间lt2.erase(it1,it2);for (auto& e : lt2){cout << e << " ";}cout << endl;return 0;
}
erase函数会发生迭代器失效,因为erase删除这个节点,它就不存在了,再次访问肯定会报错
list的erase的迭代器通过返回删除元素的后一个元素的迭代器,来实现连续删除元素
删除所以偶数的节点
五、操作函数
(1) reserve
算法库和list库中都有reserve逆置接口,可以说list设计有一点冗余了
一个算法库,一个list库,二者效果是一样的
(2)迭代器分类
上面的迭代器实现的算法下面可以用,但下面的上面不可以用
容器的迭代器是什么类型在库中会说明
(3)sort
接下来解释sort为什么不冗余:算法库中的迭代器类型是随机迭代器,但是list迭代器是双向迭代器,所以list不能用算法库中的sort
但是实际上sort在list中还是冗余的:因为算法库中的sort是快排,但lisit库中的sort是归并排序,二者效率相差太多
我们以这种方式使用算法库的sort函数进行排序显然麻烦,但效率高 ,list的sort的唯一意义就是简便
(4)这两个接口都得先排序
merge
两个链表的归并
unique
去重
(5)remove
remove就是find+eras,如果没有这个数据就啥都不干
(6)splice
把一个链表的内容剪切到另一个链表,全部转移,转移某一个,转移一部分,也可以自己给自己转移
六、list模拟实现
#include<iostream>
using namespace std;namespace djl
{template<class T>struct list_node{list_node(const T& val = T()):_next(nullptr), _prev(nullptr), _val(val){}list_node<T>* _next;list_node<T>* _prev;T _val;};//typedef list_iteraator<T,T&> iterator//typedef list_iteraator<T,const T&> const_iteratortemplate<class T,class Ref,class Ptr>struct list_iterator{typedef list_node<T> Node;typedef list_iterator<T,Ref,Ptr> self;Node* _node;list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_val;}//前置++self& operator++(){_node = _node->_next;return *this;}//后置++self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}bool operator!=(const self& it){return _node != it._node;}bool operator==(const self& it){return _node == it._node;}Ptr operator->(){return &_node->_val;}};template<class T>class list{typedef list_node<T> Node;public:typedef list_iterator<T, T&, T*> iterator;typedef list_iterator<T, const T&, const T*> const_iterator;list(){_head = new Node;_head->_prev = _head;_head->_next = _head;}list(const list<T>& lt){_head = new Node;_head->_next = _head;_head->_prev = _head;for (auto& e : lt){push_back(e);}}~list(){clear();delete _head;_head = nullptr;}void push_back(const T& x){Node* newnode = new Node(x);newnode->_val = x;Node* tail = _head->_prev;newnode->_prev = tail;newnode->_next = _head;tail->_next = newnode;_head->_prev = newnode;}iterator begin(){return _head->_next;}iterator end(){return _head;}iterator insert(iterator pos,const T& x){Node* newnode = new Node(x);Node* cur = pos._node;Node* prev = cur->_prev;cur->_prev = newnode;newnode->_next = cur;prev->_next = newnode;newnode->_prev = prev;return newnode;}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;delete cur;prev->_next = next;next->_prev = prev;return next;}void pop_back(){erase(--end());}void push_front(const T& x){insert(begin(), x);}void pop_front(){erase(begin());}size_t size(){size_t sz = 0;iterator it = begin();while (it != end()){sz++;it++;}return sz;}void clear(){iterator it = begin();while (it!=end()){it = erase(it);}}private:Node* _head;};}