目录

1、list的介绍及使用

1.1、构造及赋值重载

1.2、迭代器

1.3、空间

1.4、访问

1.5、修改

1.6、操作

2、迭代器失效

3、list的模拟实现

4、forward_list介绍与使用

4.1、构造及赋值重载

4.2、迭代器

4.3、容量

4.4、访问

4.5、修改

4.6、操作

5、迭代器的分类

5.1、按功能分类

5.2、按性质分类

6、list与vector的对比


1、list的介绍及使用

template < class T, class Alloc = allocator<T> > class list;

list文档介绍

list的底层是带头双向链表结构,双向链表中每个元素存储在独立节点中,在节点中通过指针指向其前一个元素和后一个元素。list与forward_list非常相似,最主要的不同在于forward_list是无头单向链表。

与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;此外list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)。

1.1、构造及赋值重载

explicit list (const allocator_type& alloc = allocator_type()); // 默认构造explicit list (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type()); // 构造n个val值template <class InputIterator>  
list (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); // 迭代器区间构造list (const list& x); // 拷贝构造list& operator= (const list& x); // 赋值重载

1.2、迭代器

iterator begin();
iterator end();const_iterator begin() const;
const_iterator end() const;reverse_iterator rbegin();
reverse_iterator rend();const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;

例如: 

int main()
{list<int> lt1;list<int> lt2(10, 2);list<int> lt3(lt2.begin(), lt2.end());list<int> lt4(lt3);lt1 = lt4;list<int>::iterator it1 = lt1.begin();while (it1 != lt1.end()){cout << *it1 << ' ';++it1;}cout << endl;for (auto e : lt4){cout << e << ' ';}cout << endl;return 0;
}

1.3、空间

bool empty() const; // 判断是否为空size_type size() const; // 元素个数

例如: 

int main()
{list<int> lt1;list<int> lt2(10, 2);cout << lt1.empty() << endl;cout << lt2.empty() << endl;cout << lt1.size() << endl;cout << lt2.size() << endl;return 0;
}

1.4、访问

reference front(); // 起始元素
const_reference front() const;reference back(); // 末尾元素
const_reference back() const;

例如: 

int main()
{list<int> lt1(10, 2);lt1.front()++;lt1.back()--;cout << lt1.front() << endl;cout << lt1.back() << endl;return 0;
}

1.5、修改

void push_front (const value_type& val); // 头插
void pop_front(); // 头删void push_back (const value_type& val); // 尾插
void pop_back(); // 尾删iterator insert (iterator position, const value_type& val); // 插入iterator erase (iterator position); // 删除void swap (list& x); // 交换void resize (size_type n, value_type val = value_type()); // 改变元素的个数void clear(); // 清空

例如: 

int main()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_front(5);lt.push_front(6);for (auto e : lt){cout << e << ' ';}cout << endl;lt.resize(10, 9);lt.insert(lt.begin(), 7);for (auto e : lt){cout << e << ' ';}cout << endl;list<int> lt2(lt);lt.clear();for (auto e : lt2){cout << e << ' ';}cout << endl;lt.swap(lt2);for (auto e : lt){cout << e << ' ';}cout << endl;lt.pop_front();lt.pop_back();for (auto e : lt){cout << e << ' ';}cout << endl;return 0;
}

1.6、操作

void sort(); // 排序,默认是升序template <class Compare>
void sort (Compare comp); // 关于仿函数,后面再说void reverse(); // 逆置

例如:

int main()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_front(5);lt.push_front(6);lt.reverse();list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << ' ';++it;}cout << endl;list<int> lt2(lt);lt.sort();for (auto e : lt){cout << e << ' ';}cout << endl;greater<int> gt;lt2.sort(gt);for (auto e : lt2){cout << e << ' ';}cout << endl;return 0;
}

2、迭代器失效

前面说过,迭代器失效即迭代器所指向的节点的无效。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。例如:

int main()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> lt(array, array + sizeof(array) / sizeof(array[0]));auto it = lt.begin();while (it != lt.end()){// erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给其赋值lt.erase(it);++it;}return 0;
}

当运行到++it时就会报错。 改为如下即可:

int main()
{int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> lt(array, array + sizeof(array) / sizeof(array[0]));auto it = lt.begin();while (it != lt.end()){lt.erase(it++); //或者也可以写成://it = lt.erase(it);}for (auto e : lt){cout << e << ' ';}cout << endl;return 0;
}

3、list的模拟实现

template<class T>
struct list_node
{list_node<T>* _prev;list_node<T>* _next;T _data;list_node(const T& x = T()):_prev(nullptr),_next(nullptr),_data(x){}
};// ///////////////////////////////////////////////////////////template<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){}self& operator++(){_node = _node->_next;return *this;}self& operator--(){_node = _node->_prev;return *this;}self& operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}Ref operator*()               {return _node->_data;}Ptr operator->()                 {return &_node->_data;}bool operator!=(const self& s){return _node != s._node;}bool operator==(const self& s){return _node == s._node;}
};// /////////////////////////////////////////template<class T>
class List
{
public:typedef list_node<T> Node;// 正向迭代器typedef __list_iterator<T,T&,T*> iterator;typedef __list_iterator<T,const T&,const T*> const_iterator;// //////////////////////////////////////////////////////iterator begin(){return _head->_next;//这里也可以写为:iterator(_head->_next);}iterator end(){return _head;//这里也可以写为:iterator(_head);}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}// ///////////////////////////////////////////////////////////void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}List(){empty_init();}List(const List<T>& lt){empty_init();const_iterator it = lt.begin();while (it != lt.end()){push_back(*it);++it;}//像下面这样写也是可以的/*for (auto e : lt){push_back(e);}*/}/*List<T>& operator=(const List<T>& lt) // 传统写法{if (this != &lt){clear();for (auto e : lt){push_back(e);}}return *this;}*/void swap(List<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}List<T>& operator=(List<T> lt) // 现代写法{swap(lt);return *this;}iterator insert(iterator pos, const T& x){Node* newnode = new Node(x);Node* cur = pos._node;Node* prev = cur->_prev;prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;++_size;return iterator(newnode);}void push_front(const T& x){insert(begin(), x);}void pop_front(){erase(begin());}void pop_back(){erase(--end());}~List(){clear();delete _head;_head = nullptr;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}iterator erase(iterator pos){Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;delete cur;prev->_next = next;next->_prev = prev;--_size;return iterator(next);}void push_back(const T& x){Node* newnode = new Node(x);Node* end = _head->_prev;end->_next = newnode;newnode->_prev = end;newnode->_next = _head;_head->_prev = newnode;_size++;}size_t size(){return _size;}private:Node* _head;size_t _size;
};

4、forward_list介绍与使用

template < class T, class Alloc = allocator<T> > class forward_list;

forward_list文档介绍

forward_list的底层结构是无头单向链表。

4.1、构造及赋值重载

//默认构造
explicit forward_list (const allocator_type& alloc = allocator_type());//构造n个val
explicit forward_list (size_type n, const value_type& val,const allocator_type& alloc = allocator_type());
//用迭代区间构造
template <class InputIterator>
forward_list (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type());//拷贝构造
forward_list (const forward_list& fwdlst);//赋值重载
forward_list& operator= (const forward_list& fwdlst);

4.2、迭代器

iterator before_begin() noexcept; // 返回容器第一个元素之前的位置
const_iterator before_begin() const noexcept;iterator begin() noexcept; // 返回第一个元素的位置
const_iterator begin() const noexcept;iterator end() noexcept; // 返回最后一个元素之后的位置
const_iterator end() const noexcept;

例如: 

int main()
{   forward_list<int> f1;forward_list<int> f2(5, 3);forward_list<int> f3(f2.begin(), f2.end());forward_list<int> f4(f3);f1 = f4;forward_list<int>::iterator it1 = f2.begin();while (it1 != f2.end()){cout << *it1 << ' ';++it1;}cout << endl;for (auto& e : f3){cout << ++e << ' ';}cout << endl;return 0;
}

4.3、容量

bool empty() const noexcept; // 判断是否为空

4.4、访问

reference front(); // 返回第一个元素
const_reference front() const;

4.5、修改

void push_front (const value_type& val); //头插void pop_front(); // 头删iterator insert_after ( const_iterator position, const value_type& val ); // 之后插入iterator erase_after (const_iterator position); // 之后删除void swap (forward_list& fwdlst); // 交换void resize (size_type n); // 增大元素个数
void resize (size_type n, const value_type& val);void clear() noexcept; // 清空

例如: 

int main()
{   forward_list<int> f1;f1.push_front(1);f1.push_front(2);f1.push_front(3);f1.push_front(4);f1.push_front(5);cout << f1.empty() << endl;cout << f1.front() << endl;f1.insert_after(f1.before_begin(), 6);forward_list<int>::iterator it1 = f1.begin();while (it1 != f1.end()){cout << *it1 << ' ';++it1;}cout << endl;forward_list<int> f2;f2.resize(10, 5);f1.swap(f2);f2.clear();for (auto e : f1){cout << e << ' ';}cout << endl;return 0;
}

4.6、操作

void sort(); // 排序,默认为升序template <class Compare>
void sort (Compare comp);void reverse() noexcept; // 逆置

例如:

int main()
{   forward_list<int> f1;f1.push_front(5);f1.push_front(4);f1.push_front(3);f1.push_front(5);f1.push_front(2);f1.sort();for (auto e : f1){cout << e << ' ';}cout << endl;f1.reverse();for (auto e : f1){cout << e << ' ';}cout << endl;return 0;
}

5、迭代器的分类

5.1、按功能分类

迭代器按功能分类可以分为正向迭代器反向迭代器。关于反向迭代器,会在模板进阶部分进行模拟实现。

5.2、按性质分类

迭代器按性质(由容器的底层实现决定的)分类可以分为单向迭代器、双向迭代器以及随机迭代器。

单向迭代器:只支持++,不支持--,例如:forward_list(单链表)。

双向迭代器:支持++,也支持--,例如:list(双向链表)

随机迭代器:支持++,也支持--,还支持+以及-,例如:vector(顺序表)、string(顺序表)以及deque(后面讲)。

例如:算法库中有一个sort模板函数,用来进行排序

template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);	template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

但是该模板函数不能用来对list以及forward_list进行排序,因为该模板函数要求的是传随机迭代器,这也就是为什么,明明算法库中有sort模板函数,但是forward_list以及list中也实现了sort函数的原因。

6、list与vector的对比

vectorlist
底层结构动态顺序表,一段连续空间带头结点的双向循环链表
随机访问支持随机访问,访问某个元素效率O(1)不支持随机访问,访问某个元素效率为O(N)
插入和删除任意位置插入和删除效率低,需要搬移元素,时间复杂度为O(N),插入时有可能需要增容,增容会开辟新空间、拷贝元素以及释放旧空间,导致效率更低任意位置插入和删除效率高,不需要搬移元素,时间复杂度为 O(1)
空间利用率底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高。底层节点动态开辟,节点容易造成内存碎片,空间利用率低, 缓存利用率低。
迭代器原生态指针对原生态指针进行封装
迭代器失效在插入元素后,要给迭代器重新赋值,因为插入元素有可能会导致重新扩容,致使原来迭代器失效。删除后,迭代器需要重新赋值否则会失效。插入元素不会导致迭代器失效, 删除元素时,只会导致当前迭代器失效,其他迭代器不受影响。
使用场景需要高效存储,随机访问,不关心插入删除效率。大量插入和删除操作,不关心随机访问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/90245.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/90245.shtml
英文地址,请注明出处:http://en.pswp.cn/web/90245.shtml

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

相关文章

华为云数据库 GaussDB的 nvarchar2隐式类型转换的坑

bigint 与 nvarchar2比较时发生隐式类型转换的坑 1. 案例分析 假设&#xff1a; table1有下面两个字段&#xff1a;id:bigint&#xff0c; source_id nvarchar2(50)数据库中id 的值一定大于 int4 的最大值&#xff0c;例如存在一条单据&#xff1a; id1947854462980792321&…

spring boot 集成netty,及其一些基本概念

一、基本概念 1、channel:通道&#xff0c;入站或者出站数据的载体 2、ChannelHandler&#xff1a;通道处理器&#xff0c;业务逻辑写在这里面&#xff0c;netty 5版本将入战和出站合并成了ChannelHandler 3、ChannelPipeline&#xff1a;通道里的管道&#xff0c;是一个或者多…

7月23日华为机考真题第一题100分

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 bishipass.com 01. 创业投资收益优化 问题描述 K小姐刚刚大学毕业,手头有 m m m 元资金想要进行创业投资。她发现了 k k

HTML5 跨文档通信机制:postMessage API 详解与应用

postMessage 是 HTML5 规范中定义的跨文档通信&#xff08;Cross-Document Messaging&#xff09;API&#xff0c;其设计目的是解决不同源&#xff08;协议、域名、端口任一存在差异&#xff09;的窗口&#xff08;如 iframe 嵌入的文档、window.open 创建的新窗口&#xff09;…

Kafka——Kafka中的位移提交

引言&#xff1a;为什么位移提交至关重要&#xff1f;在Kafka的分布式消息系统中&#xff0c;消费者组&#xff08;Consumer Group&#xff09;通过分区分配机制实现负载均衡和容错&#xff0c;但如何准确记录每个消费者的消费进度&#xff0c;是保证消息不丢失、不重复的关键。…

java设计模式 -【装饰器模式】

装饰器模式的定义 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;允许向一个现有对象动态添加新功能&#xff0c;同时不改变其结构。它通过创建包装对象&#xff08;装饰器&#xff09;来包裹原始对象&#xff0c;并在保持原始对象方法…

手写字体生成器:一键模拟真实笔迹

软件介绍 在自媒体创作领域&#xff0c;手写体文案因其独特的艺术感而备受青睐。然而&#xff0c;真实的手写往往效率低下且效果难以保证。今天为大家推荐一款专业的手写模拟软件&#xff0c;能够一键生成逼真的手写字体效果&#xff0c;完美解决创作效率与质量的双重需求。…

【Android】用 ViewPager2 + Fragment + TabLayout 实现标签页切换

文章目录【Android】用 ViewPager2 Fragment TabLayout 实现标签页切换一、引入&#xff1a;什么是 ViewPager2 &#xff1f;二、ViewPager2 的基础使用1. 在布局文件 (activity_main.xml)中添加 ViewPager22. 制作一个 Fragment2.1 创建一个布局文件2.2 创建一个 Fragment 类…

嵌入式学习-土堆目标检测(4)-day28

Pytorch中加载自定义数据集 - VOC其中需要pip install xmltodict#voc_dataset.pyimport os import torch import xmltodict from PIL import Image from torch.utils.data import Dataset import torchvision.transforms as transformsclass VOCDataset(Dataset): def __init_…

Spring MVC上下文容器在Web容器中是如何启动的(源码深入剖析)?

文章目录一、双容器架构&#xff1a;MVC容器与根容器的关系二、启动全流程解析1. 启动流程全景图2. 初始化根容器&#xff08;Root WebApplicationContext&#xff09;2.1 Tomcat 中启动入口源码解析2.2 Spring 根上下文启动源码解析3. 初始化 MVC 容器&#xff08;DispatcherS…

【iOS】编译和链接、动静态库及dyld的简单学习

文章目录编译和链接1️⃣核心结论&#xff1a;一句话区分2️⃣编译过程&#xff1a;从源代码到目标文件&#xff08;.o&#xff09;2.1 预处理&#xff08;Preprocessing&#xff09;&#xff1a;“替换变量复制粘贴”2.2 编译&#xff08;Compilation&#xff09;&#xff1a;…

金山办公WPS项目产品总监陈智新受邀为第十四届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会珠海金山办公软件有限公司WPS项目产品总监 陈智新先生 受邀为“PMO评论”主办的2025第十四届中国PMO大会演讲嘉宾&#xff0c;演讲议题为&#xff1a;中小团队PMO的成长之路&#xff0c;敬请关注&#xff01;议题简要&#xff1a;在竞争激烈、需求多变的…

web安全 | docker复杂环境下的内网打点

本文作者&#xff1a;Track-syst1m一.前言本文涉及的相关漏洞均已修复、本文中技术和方法仅用于教育目的&#xff1b;文中讨论的所有案例和技术均旨在帮助读者更好地理解相关安全问题&#xff0c;并采取适当的防护措施来保护自身系统免受攻击。二.大概流程1. 外网打点• 漏洞利…

iTwin 几何属性获取

面积体积半径获取几何属性&#xff0c;如面积&#xff0c;体积&#xff0c;半径&#xff0c;可以使用getMassProperties这个接口async onGetMassProperty(){const vp IModelApp.viewManager.selectedView;const iModel vp?.iModel;if (!iModel) return;console.log("iM…

OpenLayers 快速入门(九)Extent 介绍

看过的知识不等于学会。唯有用心总结、系统记录&#xff0c;并通过温故知新反复实践&#xff0c;才能真正掌握一二 作为一名摸爬滚打三年的前端开发&#xff0c;开源社区给了我饭碗&#xff0c;我也将所学的知识体系回馈给大家&#xff0c;助你少走弯路&#xff01; OpenLayers…

LeetCode 121. 买卖股票的最佳时机 LeetCode 122. 买卖股票的最佳时机II LeetCode 123.买卖股票的最佳时机III

LeetCode 121. 买卖股票的最佳时机尝试一&#xff1a;暴力解决方法常用两个指针去遍历prices数组&#xff0c;dp[i]用于记录在第i天所获得的最大利润。时间复杂度是O(N^2)&#xff0c;超出时间限制。Codeclass Solution(object):def maxProfit(self, prices):"""…

【LeNet网络架构】——深度学习.卷积神经网络

目录 1 MLP 2 LeNet简介 3 Minst数据集 3.1 MINST数据集简介 3.2 MNIST数据集的预处理 4 LeNet手写数字识别 LeNet由Yann Lecun 提出&#xff0c;是一种经典的卷积神经网络&#xff0c;是现代卷积神经网络的起源之一。Yann将该网络用于邮局的邮政的邮政编码识别&#xff…

Python笔记完整版

常用pip源 &#xff08;1&#xff09;阿里云 http://mirrors.aliyun.com/pypi/simple/&#xff08;2&#xff09;豆瓣 http://pypi.douban.com/simple/&#xff08;3&#xff09;清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/&#xff08;4&#xff09;中国科学技术大学…

2025 鸿蒙创新赛又来了,万少教你如何强势切入 HarmonyOS AI特性

2025 鸿蒙创新赛又来了&#xff0c;万少教你如何强势切入 前言 ​ 2025 华为HarmonyOS 创新赛又来了&#xff0c;创新赛是鸿蒙生态最大规模开发者官方赛事&#xff0c;最高获百万激励。 参赛资格 面向所有开发者开放以队伍的形式来参加&#xff0c;可以一个人报名一个队伍&a…

【智能模型系列】Unity通过访问Ollama调用DeepSeek模型进行本地部署

【智能模型系列】Unity通过访问Ollama调用DeepSeek模型进行本地部署 目录 一、前言 二、环境准备 三、核心代码解析 1、参数配置 2. CallDeepSeek.cs - API交互控制器 3、 MainPanel.cs - 用户界面控制器 四、源码 一、前言 在本教程中,我将分享如何在Unity中集成本地…