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

list列表 - 指南

 list 容器的优点

  •         高效的插入和删除:由于std::list是基于带头双向循环链表实现的,插入和删除操作复杂度O(1)
  •         稳定的迭代器:相对于vector这种,list迭代器失效的情况比较少
  •         动态内存管理:std::list可以动态调整大小,根据需要分配和释放内存。能够有效地处理大量元素

但因为是链表结构,空间不连续,占用了更多的内存。在list 的迭代器当中也就没有实现 operator+ 这个函数。

定义私有成员:

	private:Node* _head;size_t _size;

在官方的List源代码当中,List容器的结点定义在一个结构体当中。

链表节点
	template                 //模板声明struct list_node{list_node* _next;          //成员变量list_node* _prev;T _val;list_node(const T& val = T()) //构造函数:_next(nullptr), _prev(nullptr), _val(val){}};

使用 struct而不是 class,意味着所有成员默认是 public的。

定义正向迭代器

通过模板参数来同时实现 普通迭代器 和 const 迭代器,避免代码冗余。

	// T: 数据类型, Ref: 引用类型(T&/const T&), Ptr: 指针类型(T*/const T*)templatestruct __list_iterator                          //定义一个类来实现迭代起的行为{typedef list_node Node;typedef __list_iterator self;  //给自己类型起个别名,简化代码Node* _node;                                //节点指针__list_iterator(Node* node)                 //构造函数:_node(node){}// 运算符重载Ref operator*()                  // 解引用{return _node->_val;}Ptr operator->()                 // 成员访问(编译器会优化掉一个->){return &_node->_val;}//前置++self& operator++(){_node = _node->_next;return *this;}//后置++self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const self& it) const{return _node != it._node;}bool operator==(const self& it) const{return _node == it._node;}
};

举例使用

定义反向迭代器
  1. 核心思想​​:rbegin()对应 end()(即最后一个元素的下一个),rend()对应 begin()

  2. ​​操作​​:对反向迭代执行 ++操作,实际是调用其内部封装的正向迭代器的 --操作。

	templatestruct __list_reverse_iterator{typedef list_node Node;typedef __list_reverse_iterator self;Node* _node;__list_reverse_iterator(Node* node):_node(node){}Ref operator*(){return _node->_val;}Ptr operator->(){return &_node->_val;}// 注意:反向迭代器的++是正向的--self& operator++(){_node = _node->_prev;return *this;}self operator++(int){self tmp(*this);_node = _node->_prev;return tmp;}// 反向迭代器的--是正向的++self& operator--(){_node = _node->_next;return *this;}self operator--(int){self tmp(*this);_node = _node->_next;return tmp;}bool operator!=(const self& it) const{return _node != it._node;}bool operator==(const self& it) const{return _node == it._node;}};
定义一个list类

对之前

  • list_node结构体 重命名为 Node
  • 正向迭代器重命名为 iterator 和 const_iterator
  • 反向迭代器重命名为 reverse_iterator 和 const_reverse_iterator
	templateclass list{typedef list_node Node; //重命名public://正向迭代器typedef __list_iterator iterator;typedef __list_iterator const_iterator;//反向迭代器typedef __list_reverse_iterator reverse_iterator;typedef __list_reverse_iterator const_reverse_iterator;......};

构造函数

		void empty_init()       //创建一个空指针{_head = new Node;_head->_prev = _head;_head->_next = _head;_size = 0;}list()                //构造函数{empty_init();}

析构函数

		~list(){clear();                //析构函数delete _head;_head = nullptr;}void clear()                //清理{iterator it = begin();while (it != end()){it = erase(it);}_size = 0;}

拷贝构造函数

		// lt2(lt1)list(const list& lt)//list(const list& lt){empty_init();for (auto& e : lt){push_back(e);}}

push_back

		void push_back(const T& x){insert(end(), x);}

push_front

		void push_front(const T& x){insert(begin(), x);}

pop_back

		void pop_back(){erase(--end());}

pop_front

		void pop_front(){erase(begin());}

insert

		iterator insert(iterator pos, const T& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);prev->_next = newnode;newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;++_size;return newnode;}

要返回新插入的元素的位置,防止外部迭代器失效。 

erase

		iterator erase(iterator pos){assert(pos != end());Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;return next;}

size()

		size_t size()	{ return _size;	}

empty

		bool empty() const { return _size == 0; }

front()

		T& front(){assert(_size > 0);return _head->_next->_val;}

back()

		T& back(){assert(_size > 0);return _head->_prev->_val;}

赋值运算符重载函数和swap()函数

		void swap(list& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}list& operator=(list lt)//list& operator=(list lt){swap(lt);return *this;}

其实上述的 赋值重载运算符函数当中的模板类的类型名可以不用 List<T>,我们知道List<T>是类型名,List是类名,对于模版类,类型名不是 List,而是List<T>,但是如果是在类模板当中写,可以写类名也可以写类型名(下述写法也可以):

list& operator=(list lt)

总代码
#pragma once
#include
#include 
using namespace std;
namespace bit
{templatestruct list_node      //底层是结构体{list_node* _next;list_node* _prev;T _val;list_node(const T& val = T()):_next(nullptr), _prev(nullptr), _val(val){}};// typedef __list_iterator iterator;// typedef __list_iterator const_iterator;// T: 数据类型, Ref: 引用类型(T&/const T&), Ptr: 指针类型(T*/const T*)templatestruct __list_iterator{typedef list_node Node;typedef __list_iterator self;  // 简化类型名Node* _node;// 核心:持有一个指向节点的指针__list_iterator(Node* node):_node(node){}// 运算符重载Ref operator*()// 解引用{return _node->_val;}Ptr operator->() // 成员访问(编译器会优化掉一个->){return &_node->_val;}//前置++self& operator++(){_node = _node->_next;return *this;}//后置++self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const self& it) const{return _node != it._node;}bool operator==(const self& it) const{return _node == it._node;}};// 反向迭代器templatestruct __list_reverse_iterator{typedef list_node Node;typedef __list_reverse_iterator self;Node* _node;__list_reverse_iterator(Node* node):_node(node){}Ref operator*(){return _node->_val;}Ptr operator->(){return &_node->_val;}// 注意:反向迭代器的++是正向的--self& operator++(){_node = _node->_prev;return *this;}self operator++(int){self tmp(*this);_node = _node->_prev;return tmp;}// 反向迭代器的--是正向的++self& operator--(){_node = _node->_next;return *this;}self operator--(int){self tmp(*this);_node = _node->_next;return tmp;}bool operator!=(const self& it) const{return _node != it._node;}bool operator==(const self& it) const{return _node == it._node;}};/*templatestruct __list_const_iterator{typedef list_node Node;Node* _node;__list_const_iterator(Node* node):_node(node){}const T& operator*(){return _node->_val;}__list_const_iterator& operator++(){_node = _node->_next;return *this;}__list_const_iterator operator++(int){__list_const_iterator tmp(*this);_node = _node->_next;return tmp;}bool operator!=(const __list_const_iterator& it){return _node != it._node;}bool operator==(const __list_const_iterator& it){return _node == it._node;}};*/templateclass list{typedef list_node Node; //重命名public://正向迭代器typedef __list_iterator iterator;typedef __list_iterator const_iterator;//反向迭代器typedef __list_reverse_iterator reverse_iterator;typedef __list_reverse_iterator const_reverse_iterator;// 这么设计太冗余了,看看库里面如何设计的//typedef __list_const_iterator const_iterator;// 这样设计const迭代器是不行的,因为const迭代器期望指向内容不能修改// 这样设计是迭代器本身不能修改// typedef const __list_iterator const_iterator;// const T* ptr1;// T* const ptr2;// 如何设计const迭代器?iterator begin(){//return _head->_next;return iterator(_head->_next);}iterator end(){return _head;//return iterator(_head);}const_iterator begin() const{//return _head->_next;return const_iterator(_head->_next);}const_iterator end() const{return _head;//return const_iterator(_head);}// 反向迭代器的起始是最后一个元素reverse_iterator rbegin(){return reverse_iterator(_head->_prev);}// 反向迭代器的结束是头节点(第一个元素的前一个位置)reverse_iterator rend(){return reverse_iterator(_head);}const_reverse_iterator rbegin() const{return const_reverse_iterator(_head->_prev);}const_reverse_iterator rend() const{return const_reverse_iterator(_head);}void empty_init()         //ok{_head = new Node;_head->_prev = _head;_head->_next = _head;_size = 0;}list()                  //构造函数{empty_init();}// lt2(lt1)list(const list& lt)   //拷贝构造函数//list(const list& lt){empty_init();for (auto& e : lt){push_back(e);}}void swap(list& lt)      //swap{std::swap(_head, lt._head);std::swap(_size, lt._size);}list& operator=(list lt)    //赋值运算符重载//list& operator=(list lt){swap(lt);return *this;}~list()          //析构函数{clear();delete _head;_head = nullptr;}void clear()      // ok{iterator it = begin();while (it != end()){it = erase(it);}_size = 0;}void push_back(const T& x)  //{insert(end(), x);}void push_front(const T& x) //{insert(begin(), x);}void pop_back()				//{erase(--end());}void pop_front()			//{erase(begin());}// pos位置之前插入iterator insert(iterator pos, const T& x) //insert{Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);prev->_next = newnode;newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;++_size;return newnode;}iterator erase(iterator pos)  //erase{assert(pos != end());Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;return next;}size_t size()          //ok{/*size_t sz = 0;iterator it = begin();while (it != end()){++sz;++it;}return sz;*/return _size;}bool empty() const { return _size == 0; }T& front(){assert(_size > 0);return _head->_next->_val;}T& back(){assert(_size > 0);return _head->_prev->_val;}private:Node* _head;size_t _size;};

list与vector的区别
vector        list
底 层 结 构动态顺序表,是一段连续空间带头结点的双向循环链表
随 机 访 问支持随机访问,访问某个元素效率O(1)不支持随机访问,访问某个元素
效率O(N)
插 入 和 删 除任意位置插入和删除效率低,需要搬移元素,时间复杂
度为O(N),插入时有可能需要增容,增容:开辟新空
间,拷贝元素,释放旧空间,导致效率更低
任意位置插入和删除效率高,不
需要搬移元素,时间复杂度为
O(1)
空 间 利 用 率底层为连续空间,不容易造成内存碎片,空间利用率
高,缓存利用率高
底层节点动态开辟,小节点容易
造成内存碎片,空间利用率低,
缓存利用率低
迭 代 器原生态指针对原生态指针(节点指针)进行封装
迭 代 器 失 效失效情况相对较多失效情况相对较少
使 用 场 景需要随机访问,不关心插入删除大量插入和删除操作,不关心随
机访问

http://www.jsqmd.com/news/24836/

相关文章:

  • 全域互联,统一管控:EasyCVR构建多区域视频监控“一网统管”新范式
  • 魔改frida
  • 云原生周刊:在 Kubernetes 上运行机器学习
  • ts相关
  • 从模型到智能体——OpenCSG 打造 AI 落地新范式
  • CF589H 题解
  • 2025年上海电动阀门厂最新推荐榜,气动阀门/高压阀门/真空阀门/自控阀门/调节阀门/聚焦产品实力与特色服务竞争力深度剖析
  • 【每日一面】async/await 的原理
  • gmssl2.5常用命令
  • 上海电磁阀厂家最新竞争力评估推荐:高温电磁阀/高压电磁阀/防爆电磁阀/真空电磁阀/聚焦服务能力与产品特色
  • 如何在iPhone和Android设备上恢复已删除的电话号码
  • 云栖实录:重构可观测 - 打造大模型驱动的云监控 2.0 与 AIOps 新范式
  • 2025 年房屋安全鉴定检测,山东房屋安全鉴定,房屋安全鉴定质量鉴定机构最新推荐,聚焦资质、案例、服务的五家机构深度解读
  • 0289-KVS-读取目录中的文件
  • 0288-KVS-根据索引读取文件
  • 2025年南京机械钻井工程服务权威推荐榜单:砖井工程/打桩工程/环保检测井工程源头公司精选
  • 如何在 Mac 上恢复已删除的文件:解决方案和预防技巧
  • GMT0009 SM2密钥算法使用规范
  • 2025精密/五金/冲压/塑料/模具配件/司筒/镶件/零件企业推荐榜:锦鸿深耕三十载筑服务网络,这些实力派值得关注​
  • 2025发泡混凝土领域厂家推荐榜:云南锦乐建筑领衔,多企业助力绿色建材发展​ 随着
  • 2025年泳池水循环设备厂家权威推荐榜单:泳池水净化设备 /钢结构泳池/泳池恒温设备源头厂家精选
  • EasyExcel碰到问题记录
  • 2025年修护/二硫化硒去屑/香氛/控油蓬松/洗发水推荐榜:西安悦己容生物主打植萃护理,四大品牌以精准配方适配多元发质
  • 2025喷涂/聚脲涂料领域源头厂家推荐榜:宁国创遂新材料领衔,多企业助力防腐防护升级​
  • 2025弯管领域源头厂家推荐榜:合肥市翼达机械领衔,多企业助力工业管件加工升级​
  • 2025不锈钢剪板折弯推荐榜:上海一步一金属主打定制加工,四大企业以精准工艺赋能工业制造
  • 2025年碳氢肥料生产厂家权威推荐榜单:农产品用料/增产用肥/碳氢核肥邮沃源头厂家精选
  • 算法分析--分治--3.矩阵乘法
  • 三立轴承:精密轴承安装后怎么检查?
  • 2025年灭火装置厂家推荐排行榜,气体灭火装置,自动灭火装置,机床灭火装置,七氟丙烷灭火装置,二氧化碳灭火装置,清洗机灭火装置,走心机灭火装置,搓丝机灭火装置,磨床灭火装置,火花机灭火装置公司推荐