list列表 - 指南

news/2025/10/28 17:30:54/文章来源:https://www.cnblogs.com/yangykaifa/p/19172351

 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.mzph.cn/news/949009.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全域互联,统一管控:EasyCVR构建多区域视频监控“一网统管”新范式

方案背景 在连锁店、企业分支机构、库房、工厂等多元化场景的视频监控项目中,设备品牌众多、型号繁杂,再加上现场网络环境的复杂性,使得跨区域视频联网面临诸多挑战。为有效解决视频监控接入兼容、上云联网等问题,…

魔改frida

魔改frida 魔改fridagit clone https://github.com/frida/frida-core.git安装子分支git submodule update --init --recursive安装ndk,设置环境变量 https://github.com/android/ndk/wiki 下载25版本 设置环境变量v…

云原生周刊:在 Kubernetes 上运行机器学习

云原生热点 KGateway v2.1:面向 AI 场景的高可用网关全新升级 KGateway 是一个面向云原生和 AI 场景的高性能网关,支持多租户、统一接入、智能路由与推理服务集成,兼容 Kubernetes Gateway API 标准。 在最新的 v2.…

ts相关

1、常用类型工具

从模型到智能体——OpenCSG 打造 AI 落地新范式

一、AI 焦虑的现实:技术太快、落地太慢 AI 的世界正在以指数级速度演进。 企业追逐最新模型,却发现落地难度越来越大——模型更新太快、算力成本太高、应用落地太慢。 OpenCSG 的观点是:企业不需要更多的模型,而需…

CF589H 题解

很好的题。但是 CF 主站上看不了。 首先需要观察到一个性质:对于一个包含 \(k\) 个关键点的连通块,一定可以凑出恰好 \(\lfloor\frac{k}{2}\rfloor\) 对路线。 首先这个东西显然是答案上界。然后考虑证明一定能够满足…

2025年上海电动阀门厂最新推荐榜,气动阀门/高压阀门/真空阀门/自控阀门/调节阀门/聚焦产品实力与特色服务竞争力深度剖析

随着工业自动化进程加速,以及石油化工、清洁能源等领域对特种阀门需求的增长,企业在选择阀门供应商时面临诸多考量 —— 如何辨别企业生产资质、如何匹配工况需求的阀门品类、如何规避设备运行中的潜在风险,成为当下…

【每日一面】async/await 的原理

基础问答 问:async/await 的原理是什么? 答:关键字本身就是 Promise 的语法糖,依托于生成器函数 (Generator) 函数能力实现的。async 关键字标志这个函数为异步函数,并且将返回结果封装为一个 Promise,await 则…

gmssl2.5常用命令

参考链接:https://zhuanlan.zhihu.com/p/618494579SM3计算摘要:echo -n hello | gmssl dgst -sm3 SM3计算HMAC:echo -n hello | gmssl dgst -sm3 -hmac 11223344556677881122334455667788SM4对输入字符加密:echo h…

上海电磁阀厂家最新竞争力评估推荐:高温电磁阀/高压电磁阀/防爆电磁阀/真空电磁阀/聚焦服务能力与产品特色

随着工业自动化程度不断提高以及高端流体控制需求增长,用户在选择电磁阀制造企业时面临诸多考量——如何评估企业技术实力、如何匹配不同工况的产品选型、如何保障设备长期稳定运行,成为工业采购决策中的核心关注点。…

如何在iPhone和Android设备上恢复已删除的电话号码

丢失手机上的联系人,感觉就像自己的一部分被抹去了。朋友、家人,甚至必要服务的联系人——所有信息都可能瞬间消失,而且似乎无法恢复。对一些人来说,失去商业联系人更是一场噩梦,会给他们带来巨大的经济压力。 无…

云栖实录:重构可观测 - 打造大模型驱动的云监控 2.0 与 AIOps 新范式

云监控 2.0 历经一年半的演进,已经完成了 ARMS、容器监控(Prometheus)、企业云监控的大部分系统整合、存储迁移等工作,剩余的 SLS CloudLens、基础云监控等也在下半年逐步迁移规划中。作者:司徒放(姬风) 纵观技…

2025 年房屋安全鉴定检测,山东房屋安全鉴定,房屋安全鉴定质量鉴定机构最新推荐,聚焦资质、案例、服务的五家机构深度解读

引言 房屋安全鉴定是保障建筑使用安全的核心环节,尤其在山东这样建筑类型丰富、部分区域面临灾后重建与抗震加固需求的地区,选择正规机构至关重要。当前市场存在资质参差不齐、数据造假等问题,为破解选择难题,本次…

0289-KVS-读取目录中的文件

环境Time 2022-12-16 WSL-Ubuntu 22.04 Rust 1.65.0前言 说明 参考:https://github.com/pingcap/talent-plan 目标 在上一节的基础上,根据提供的目录,到目录中进行文件的读取。 Cargo.toml [package] edition = &qu…

0288-KVS-根据索引读取文件

环境Time 2022-12-13 WSL-Ubuntu 22.04 Rust 1.65.0前言 说明 参考:https://github.com/pingcap/talent-plan 目标 在上一节的基础上,根据提供的索引,到文件中读取命令和值。 Cargo.toml [package] edition = "…

2025年南京机械钻井工程服务权威推荐榜单:砖井工程/打桩工程/环保检测井工程源头公司精选

在城市建设与环保政策双轮驱动下,南京机械钻井工程服务市场正迎来新一轮发展机遇,其中环保检测井工程已成为增长新引擎。 在当今城市基础设施更新和环保政策深入推进的背景下,南京机械钻井工程服务行业依托区域经济…

如何在 Mac 上恢复已删除的文件:解决方案和预防技巧

在 Mac 上删除文件并不意味着一切就此结束。如今,macOS 用户有多种方法可以恢复已删除的数据。即使文件已从 Mac 的“垃圾箱”中删除,您仍然可以选择其他方法。您可以使用 macOS 的内置功能进行数据恢复,也可以使用…

GMT0009 SM2密钥算法使用规范

原文链接:https://blog.csdn.net/A_CAT_journey/article/details/1393903021、什么是国密密钥对加密 国密密钥对加密格式定义在《GMT 0009-2012 SM2密码算法使用规范》文档中,具体的规范格式如下:在SM2密钥对传递时…

2025精密/五金/冲压/塑料/模具配件/司筒/镶件/零件企业推荐榜:锦鸿深耕三十载筑服务网络,这些实力派值得关注​

在有着 “全球模具产业之都” 之称的东莞,模具配件作为 “工业之母” 的核心支撑,正随产业升级不断突破。2025 年市场需求持续向高精度、快响应倾斜,以下几家模具配件企业凭借技术积淀与服务能力脱颖而出。​ 东莞市…

2025发泡混凝土领域厂家推荐榜:云南锦乐建筑领衔,多企业助力绿色建材发展​ 随着

随着绿色建筑理念的普及,兼具轻质、保温、隔音与环保特性的发泡混凝土,在民用建筑、市政配套等领域的需求持续增长。为展现该领域优质企业实力,本次 2025 发泡混凝土领域推荐榜聚焦云南区域,结合企业业务专注度、技…