当前位置: 首页 > news >正文

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;};}

相关文章:

  • 可以隐藏列的表格
  • 单片机 + 图像处理芯片 + TFT彩屏 复选框控件
  • Linux内核中的编译时安全防护:以网络协议栈控制块校验为例
  • 单片机之间的双向通信
  • terraform查看资源建的关联关系
  • 一、linux系统启动过程操作记录
  • 插入排序(直接插入排序、折半插入排序和希尔排序)
  • C++中析构函数
  • log4cpp进阶指南
  • LeetCode 每日一题 2025/4/21-2025/4/27
  • 关于Spark知识点与代码测试的学习总结
  • element-ui dropdown 组件源码分享
  • 【c++】AVL树模拟实现
  • Comfy UI 笔记
  • 文章记单词 | 第47篇(六级)
  • 面试记录1-春招补录0427
  • 基础学习:(9)vit -- vision transformer 和其变体调研
  • 《大型网站技术架构-核心原理与案例分析》笔记
  • UV工具的安装与使用
  • Leetcode:283. 移动零
  • 习近平:在庆祝中华全国总工会成立100周年暨全国劳动模范和先进工作者表彰大会上的讲话
  • 央行副行长:研究建立民营中小企业增信制度,破解民营中小企业信用不足等融资制约
  • 新任浙江省委常委、杭州市委书记刘非开展循迹溯源学习调研
  • 地下管道密布成难题,道路修整如何破局?
  • 四川一国企“80后”掌门人为报领导“知遇之恩”,盲目决策致数亿损失
  • 新闻1+1丨应对外部冲击,中央政治局会议释放哪些信号?