【C++】STL·List

1. list的介绍及使用

1.1list介绍

List文档介绍

1.2 list的使用

list中的接口比较多,此处类似,只需要掌握如何正确的使用,然后再去深入研究背后的原理,已 达到可扩展的能力。以下为list中一些常见的重要接口。

1.2.1 list的构造

list<int>lt1(5);           构造空的list
list<int>lt2(3, 2);        构造的list中包含n个值为val的元素
list<int>lt3(lt2);         拷贝构造函数
int arr[] = { 1,2,3,4,5 };
list<int>lt4(arr, arr + 5);用[first, last)区间中的元素构造list

1.2.2 list iterator的使用

	lt1.begin();  返回第一个元素的迭代器  lt1.end();    返回最后一个元素下一个位置的迭代器lt1.rbegin(); 返回第一个元素的reverse_iterator, 即end位置lt1.rend();   返回最后一个元素下一个位置的reverse_iterator, 即begin位置

1.2.3 list capacity

	lt1.size();  返回list中有效节点的个数lt1.empty(); 检测list是否为空,是返回true,否则返回false
1.2.4 list element access

	lt1.front(); 返回list的第一个节点中值的引用lt1.back();  返回list的最后一个节点中值的引用
1.2.5 list modifiers

	lt1.push_back(1);			尾插lt1.push_front(1);			头插lt1.pop_back();				尾删lt1.pop_front();			头删lt1.insert(lt1.begin(), 1); 在list position 位置中插入值为val的元素lt1.erase(lt1.begin());		删除list position位置的元素lt1.swap(lt2);				交换两个list中的元素lt1.clear();				清空list中的有效元素
1.2.6 list的迭代器失效

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

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

2. list的模拟实现

2.1 模拟实现list

#pragma once
#include<iostream>
#include<vector>
using namespace std;
namespace XiaoHai
{template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& x = T()):_data(x), _next(nullptr), _prev(nullptr){ }};template<class T, class ref, class Ptr>struct Reverse_iterator{Iterator _it;typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Reverse_iterator(Iterator it):_it(it){}Ref operator*(){iterator tmp(_it);--tmp;return *tmp;}Ptr operator->(){return &(operator*());}self operator++(int){self tmp(_it);--_it;return *tmp;}self operator--(int){self tmp(_it);++_it;return *tmp;}self operator++(){--_it;return *tmp;}self operator--(){++_it;return *tmp;}bool operator!=(const Self& s){return _it != s._it;}};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){ }ref& operator*(){return _node->_data;}T* operator->(){return &_node->_data;}self& operator++(){_node = _node->_next;return *this;}self& operator++(int){__list_iterator<T>tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self& operator--(int){__list_iterator<T>tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const __list_iterator<T>& it)const{return _node != it._node;}bool operator ==(const __list_iterator<T>& it)const{return !(_node != it._node);}};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;iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator begin() const{return iterator(_head->_next);}const_iterator end() const{return iterator(_head);}void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;}list(){empty_init();}//lt2(lt1)list(const list<T>&lt){empty_init();for (const auto& e:lt){push_back(e);}}list(initializer_list<int>il){empty_init();for (const auto& e : il){push_back(e);}}void swap(list<T>&lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}//lt1 = lt2list<T>& operator=(const list<T>* lt){swap(lt);return *this;}/*list<T>& operator=(const list<T>* lt){if (this != &lt){clear();for (const auto& e : il){push_back(e);}}return *this;}*/~list(){clear();delete _head;_head = nullptr;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}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());}void insert(iterator pos, const T& val){Node* cur = pos._node;Node* newnode = new Node(val);Node* prev = cur->_prev;//prev newnode curprev->_next = newnode;newnode->_next = cur;cur->_prev = newnode;newnode->_prev = prev;++_size;}iterator& erase(iterator pos){Node* cur = pos._node;Node* next = cur->_next;Node* prev = cur->_prev;//prev (cur) nextprev->_next = next;next->_prev = prev;delete cur;--_size;return iterator(next);}size_t size(){return _size;}private:Node* _head;size_t _size = 0;};
}

2.2 list的反向迭代器

通过前面例子知道,反向迭代器的++就是正向迭代器的--,反向迭代器的--就是正向迭代器的++, 因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。

	template<class T, class ref, class Ptr>struct Reverse_iterator{Iterator _it;typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Reverse_iterator(Iterator it):_it(it){}Ref operator*(){iterator tmp(_it);--tmp;return *tmp;}Ptr operator->(){return &(operator*());}self operator++(int){self tmp(_it);--_it;return *tmp;}self operator--(int){self tmp(_it);++_it;return *tmp;}self operator++(){--_it;return *tmp;}self operator--(){++_it;return *tmp;}bool operator!=(const Self& s){return _it != s._it;}};

3. list与vector的对比

vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及 应用场景不同

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

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

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

相关文章

图论2 图的数据结构表示

目录 一 图的数据结构表示 1 邻接矩阵&#xff08;Adjacency Matrix&#xff09; 2 邻接表&#xff08;Adjacency List&#xff09; 3 边列表&#xff08;Edge List&#xff09; 4 十字链表&#xff08;Orthogonal List / Cross-linked List, 十字链表&#xff09; 5 邻接…

在Excel中删除大量间隔空白行

在 Excel 中删除大量间隔空白行&#xff0c;可使用定位空值功能来快速实现。以下是具体方法&#xff1a;首先&#xff0c;选中包含空白行的数据区域。可以通过点击数据区域的左上角单元格&#xff0c;然后按住鼠标左键拖动到右下角最后一个单元格来实现。接着&#xff0c;按下快…

【C 学习】10-循环结构

“知道做不到就是不知道”一、条件循环1. while只要条件为真&#xff08;true&#xff09;&#xff0c;就会重复执行循环体内的代码。while (条件) {// 循环体&#xff08;要重复执行的代码&#xff09; }//示例 int i 1; while (i < 5) {printf("%d\n", i);i; …

音视频的下一站:协议编排、低时延工程与国标移动化接入的系统实践

一、引言&#xff1a;音视频的基础设施化 过去十年&#xff0c;音视频的两条主线清晰可辨&#xff1a; 娱乐驱动&#xff1a;直播、电商、短视频把“实时观看与互动”变成高频日常。 行业扩展&#xff1a;教育、会议、安防、政务逐步把“可用、可管、可控”引入产业系统。 …

SAM-Med3D:面向三维医疗体数据的通用分割模型(文献精读)

1) 深入剖析:核心方法与图示(Figure)逐一对应 1.1 单点三维提示的任务设定(Figure 1) 论文首先将3D交互式分割的提示形式从“2D逐片(每片1点,共N点)”切换为“体素级单点(1个3D点)”。Figure 1直观对比了 SAM(2D)/SAM-Med2D 与 SAM-Med3D(1点/体) 的差异:前两者…

【Spring】原理解析:Spring Boot 自动配置进阶探索与优化策略

一、引言在上一篇文章中&#xff0c;我们对 Spring Boot 自动配置的基本原理和核心机制进行了详细的分析。本文将进一步深入探索 Spring Boot 自动配置的高级特性&#xff0c;包括如何进行自定义扩展、优化自动配置的性能&#xff0c;以及在实际项目中的应用优化策略。同时&…

OpenCV:图像直方图

目录 一、什么是图像直方图&#xff1f; 关键概念&#xff1a;BINS&#xff08;区间&#xff09; 二、直方图的核心作用 三、OpenCV 计算直方图&#xff1a;calcHist 函数详解 1. 函数语法与参数解析 2. 基础实战&#xff1a;计算灰度图直方图 代码实现 结果分析 3. 进…

docke笔记下篇

本地镜像发布到阿里云 本地镜像发布到阿里云流程 镜像的生成方法 基于当前容器创建一个新的镜像&#xff0c;新功能增强 docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]] OPTIONS说明&#xff1a; OPTIONS说明&#xff1a; -a :提交的镜像作者&#xff1b; -m :提交时的说…

《大数据之路1》笔记2:数据模型

一 数据建模综述 1.1 为什么要数据建模背景&#xff1a; 随着DT时代的来临&#xff0c;数据爆发式增长&#xff0c;如何对数据有序&#xff0c;有结构地分类组织额存储是关键定义&#xff1a; 数据模型时数据组织和存储的方法&#xff0c;强调从业务、数据存取、使用角度 合理存…

“量子能量泵”:一种基于并联电池与电容阵的动态直接升压架构

“量子能量泵”&#xff1a;一种基于并联电池与电容阵的动态直接升压架构摘要&#xff1a;本文揭示了一种革命性的高效电源解决方案&#xff0c;旨在彻底解决低电压、大功率应用中的升压效率瓶颈与电池一致性难题。该方案摒弃传统磁性升压拓扑&#xff0c;创新性地采用并联电池…

DeepSeek实战--自定义工具

1. 背景 当前已经有很多AI基础平台&#xff08;比如&#xff1a;扣子、Dify&#xff09;&#xff0c;用户可以快速搭建Agent&#xff0c;那怎样将已有的接口能力给大模型调用呢 &#xff1f; 今天我们来探索一个&#xff0c;非常高效、快捷的方案&#xff1a;将http接口做成Dif…

“移动零”思路与题解

给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。思路讲解&#xff1a;举例如下&#xff1a;实现代码是&#xff1a;class Solution { public:v…

关于行内元素,行内块元素和块级元素

1、什么是行内元素&#xff0c;什么是行内块元素&#xff0c;什么是块级元素行内元素的特点&#xff1a;不独占一行&#xff0c;相邻元素会在同一行显示&#xff0c;直到一行排不下才换行。宽度和高度由内容本身决定&#xff0c;无法通过width&#xff0c;height手动设置&#…

⽹络请求Axios的概念和作用

Axios 是一个基于 ​​Promise​​ 的轻量级、高性能 ​​HTTP 客户端库​​&#xff0c;主要用于在浏览器和 Node.js 环境中发起 HTTP 请求&#xff08;如 GET、POST、PUT、DELETE 等&#xff09;。它通过简洁的 API 和强大的功能&#xff0c;简化了前端与后端之间的数据交互过…

在AgentScope中实现结构化输出

在AgentScope中实现结构化输出 概述 在AgentScope框架中&#xff0c;结构化输出功能允许开发者定义明确的输出模式&#xff0c;确保AI模型的响应符合预期的格式和约束。本教程将介绍如何使用AgentScope的structured_model参数来实现结构化输出。 结构化输出的优势 数据一致性&a…

Linux 磁盘I/O高占用进程排查指南:从定位到分析的完整流程

在Linux服务器运维工作中&#xff0c;磁盘I/O瓶颈是导致系统性能下降的常见原因之一。当服务器出现响应缓慢、应用卡顿等问题时&#xff0c;及时定位并解决高I/O占用进程就显得尤为重要。本文将从核心思路出发&#xff0c;通过“确认问题-定位磁盘-锁定进程-深入分析”四个步骤…

解决React中通过外部引入的css/scss/less文件更改antDesign中Modal组件内部的样式不生效问题

不生效原因Ant Design 的 Modal 默认通过 ReactDOM.createPortal 挂在 <body> 下&#xff0c;与你的组件树平级&#xff0c;所以写在 .module.css / scoped less 里的选择器根本匹配不到它&#xff0c;就算写全局样式&#xff0c;也可能因为权重不足或异步挂载时机而“看…

day41 51单片机最小系统、GPIO控制、时序逻辑器件(74HC138/595)与LED点阵驱动原理

day41 51单片机最小系统、GPIO控制、时序逻辑器件&#xff08;74HC138/595&#xff09;与LED点阵驱动原理一、嵌入式系统基础概念 1.1 嵌入式系统定义先设计硬件&#xff0c;基于硬件设计软件实现一个具体的功能 —— 专用的计算机系统硬件/软件可剪裁&#xff1a;根据功能需求…

html列表总结补充

1.有序列表的type属性不同的type值表示不同的排序标号1 表示列表项目用数字标号&#xff08;1,2,3...&#xff09; 1 a 表示列表项目用小写字母标号&#xff08;a,b,c...&#xff09; 2 A 表示列表项目用大写字母标号&#xff08;A,B,C...&#xff09; 3 i 表示列表项目用小写罗…

smartctl Current_Pending_Sector 硬盘待处理扇区

smartctl -a /dev/sdae当前值: 312 个待处理扇区 严重警告信号&#xff0c;硬盘发现了 312 个可疑扇区&#xff0c;正在等待重新分配 197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 312读取错误频发 错误计数: 38 次 ATA 错误 …