list上

文章目录

初步了解list

面试题:为什么会有list?

答:为了解决vector的缺点

vector的缺点:

插入数据需要挪动数据;
插入数据需要增容;
注:
vector和string都是数组,在哪个位置插入数据,后面的数据是要往后挪动位置的;所以时间复杂度是o(n);
而list是链表,插入数据时o(1);

vector、list优点

vector支持下标随机访问;
list头插尾插不需要挪动数据、效率高;并且不需要增容

list结构

本质是带头双向循环链表;
列表种类有哪些?
答:带头、不带头;循环、不循环;单向、双向;这样2^3组合种;
image.png
只要一个容器支持迭代器,就可以用范围for遍历;

迭代器的分类

从支持的接口角度:
单向(forward_list)、双向(list)、随机(vector);
一般从使用场景分类:
正向、反向、正向const、方向const;

list的简单运用

#define _CRT_SECURE_NO_WARNINGS#include<iostream>
#include<list>using namespace std;void print_list(const list<int>& l)
{list<int>::const_iterator it = l.begin();while (it != l.end()){cout << *it << " ";it++;}cout << endl;}void test_vector1()
{list<int> l;l.push_back(1);l.push_back(1);l.push_back(1);l.push_back(1);l.push_back(1);l.push_back(1);list<int>::iterator it = l.begin();while (it != l.end()){cout << *it << " ";it++;}cout << endl;//拷贝list<int> l1(l);print_list(l1);
}void test_vector2()
{//insert、erase//vector的迭代器失效insert、erase都会、list只用erase会迭代器失效list<int> l1;l1.push_back(1);l1.push_back(20);l1.push_back(3);l1.push_back(5);l1.push_back(8);l1.push_back(10);print_list(l1);list<int>::iterator pos = find(l1.begin(), l1.end(), 20);//现在pos就是begin()开始往后面找,里面数值为20的迭代器l1.insert(pos, 22);for (auto e : l1){cout << e << " ";e++;}cout << endl;l1.erase(pos);l1.insert(pos,11);print_list(l1);}int main()
{test_vector2();return 0; 
}

insert、erase、迭代器失效(和vector的区别)

插在这个pos位置
image.png

erase

1、这个pos的所指向的仍是指向20的这个迭代器没有变化,因为他是列表;
2、如果是vector或者string那么在insert之后再用pos会发生迭代器失效,为什么?
答:迭代器失效:因为insert之后pos所指向的内容发生了改变,vector和string本质是一个数组中间插入一个数后面数的位置都要改变、pos这个迭代器指向的地址上的内容改变了就会报错,如果发生了增容、那更加错了、增容的话原本这个数组的地址就变了;
而list是列表,列表和数组(数据结构上的内容),列表是里面存了一个数值、然后还存了一个指向下一个列表的指针,所以插入值后pos指向的位置始终不变、只是插入的新的这个数据里面有个指针指向了pos;
image.png
3、erase的话、list和vector都会存在迭代器失效
erase,list是这个pos迭代器,本质就是pos这个指针指向的空间被销毁了;
vector道理相似;
image.png

class和struct

struct和class是一样的,只是struct默认是public,class默认是private;
struct内数据默认是public类型的,class内数据默认是private类型的;
struct变量放在栈上,而class变量放在堆上,因此struct变量会自动释放,而class变量需要手动释放;

list的迭代器

是另一个struct出来的,不是列表里面的next和prev指针;
image.png
image.png
list::iterator it = lt.begin()

为什么这个迭代器的构造函数不用深拷贝?

描述:这个迭代器就不用深拷贝了,用默认的浅拷贝就行了
image.png
答:这里直接让他两指向同一个空间,不会像vector、string要深拷贝、比如v1(v2),这个v1、v2浅拷贝的话就是他们内部指针指的位置都一样了,那就是v1释放空间v2也没了,但是迭代器用不到这个功能;

tmp 是一个在函数内部创建的局部变量,但它的引用被返回给调用者。当函数执行完毕或者离开 tmp 的作用域时,tmp 对象本身并不会被销毁,因为它的引用仍然存在于调用者的上下文中。
这意味着,即使超出了包含 tmp 的作用域,tmp 对象仍然存在,并且可以通过返回的引用进行访问。只有当调用者不再使用返回的引用时,tmp 对象才会被销毁。

模拟list

注:

delete和delete[]区别是前者释放单个对象、后者释放数组对象

具体代码

写一个列表的结构体

构造函数以及其中的成员函数

	template<class T>//struct__list_node,两个_这种取名方式一般表示一会这个会在别的里面用,在这里就表示,list类里面直接用的类外面定义的struct __list_code这个结构体struct __list_node{__list_node<T>* _next; // 别忘了这里要写<T>__list_node<T>* _prev;T _data;//列表需要构造函数来初始化__list_node(const T& x = T())//这个T(),指的是没有传值过来那就直接为0:_data(x),_next(nullptr)  ,_prev(nullptr){}};

迭代器

主要用到list里面的两个指针,分别指向前后_next、_prev;

	//struct迭代器__list_iteratortemplate<class T>struct __list_iterator{typedef __list_node<T> Node;Node* _node;//构造函数,struct怎么写构造函数、就是看这个里面成员函数有哪些__list_iterator(Node* node):_node(node){}//构造传的是里面的成员函数、拷贝是传的类或者说这个结构体//浅拷贝,这个是默认函数、不用写的__list_iterator(const __list_iterator<T>& it){_node = it._node;}// operator*,读_node中的data,data的类型是T,所以函数返回值类型是TT& operator*(){return _node->_data;}//++__list_iterator<T>& operator++(){_node = _node->_next;return *this;}//后置++__list_iterator<T> operator++(int) //后置++里面就放个int,这是设计出来的伪参数,用来区分前后置用的{__list_iterator<T> tmp(*this); //直接拷贝函数、这个不用写、因为是浅拷贝,深拷贝才要写_node = _node->_next; //++(*this);return tmp;}//--__list_iterator<T>& operator--() {_node = _node->_prev; //_node是指针return *this; //*this就是迭代器,this是指针指向迭代器}__list_iterator<T>& operator--(int) //后置++里面就放个int,这是设计出来的伪参数,用来区分前后置用的{__list_iterator<T> tmp(*this); //直接拷贝函数、这个不用写、因为是浅拷贝,深拷贝才要写//node = _node->_next;--(*this);return tmp;}//!=,两个迭代器之间不相等、迭代器里面的成员函数是_node,比的是这两个,就是他指向一个列表的地址,看这两个地址一样吗bool operator!=(const __list_iterator<T>& it){return _node != it._node;}T* operator->(){return& _node->_data;//返回这个地址//指向这个地址,调用时第一个->返回其地址、第二个->返回地址上的值,迭代器做了优化,调用只需要一个->}};

class类

template<class T>
class list
{typedef __list_node<T> Node;
public:typedef __list_iterator<T> iterator; // 放public里面不然外面动不了T,就是用不了模板,私有的不能用//迭代器用节点的指针就行了iterator begin(){return iterator(_head->_next);//注意这里返回的是迭代器,不是_head头部指针、这个是list类里面的成员变量//现在是把头部指针_head传过去,然后迭代器调用他的拷贝函数;//这里面就是构造函数、因为传过去的是Node类型;}iterator end(){return iterator(_head);}//构造函数list(){_head = new Node;//new node //这里面不用写成Node[],是因为[]是数组用的,这个就里面就开辟一个指针指向的地址空间,[]是一个数组的空间_head->_next = _head;_head->_prev = _head;}void push_back(const T& x = T()){Node* tail = _head->_prev;Node* newnode = new Node(x);tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode; }private:Node* _head;
};

两个测试案例

	void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;}struct Date{int _year = 0;int _month = 1;int _day = 2;};void test_list2(){list<Date> lt;lt.push_back(Date());lt.push_back(Date());list<Date>::iterator it = lt.begin();//调用data,因为现在模板T就是date,传参传过去date是可以的while (it != lt.end()){cout << it->_year << " " << it->_month << " " << it->_day;++it;}cout << endl;}

报错

image.png
修改
image.png

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

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

相关文章

PGSQL安装PostGIS扩展模块

一、PostGIS简介 1、PostGIS介绍 PostGIS是一个空间数据库&#xff0c;空间数据库像存储和操作数据库中其他任何对象一样去存储和操作空间对象。 空间数据与数据库关联起来的三个要素&#xff1a;数据类型、索引和函数。 空间数据类型&#xff1a;用于指定图形为点&#xff0…

指向未来: 量子纠缠的本质是一个指针

指向未来: 量子纠缠的本质是一个指针 概述基本概念理解量子纠缠PythonJavaC 理解波粒二象性PythonJavaC 理解量子隧穿理解宇宙常量PythonJavaC 概述 量子纠缠 (Quantum Entanglement) 是量子系统重两个或多个粒子间的一种特殊连接, 这种连接使得即使相隔很远, 这些粒子的状态也…

Linux系统CPU持续飙高,如何排查?

一、检查CPU使用率 首先在Linux系统中检查CPU使用率。可以通过在命令行中输入top或htop命令来查看当前系统中各个进程的CPU使用率。如果CPU使用率大于80%&#xff0c;则可以考虑进行排查。 $ top 二、检查系统负载 另外可以使用uptime命令来查看系统的平均负载情况。 $ upti…

第二次作业+第三次作业

第二次作业第三次作业 第二次作业 题目&#xff1a; 网站需求&#xff1a; ​ 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于[ww…

Python连接数据库的梳理

我们通常用的数据库类型主要有关系型数据库&#xff0c;非关系型数据库等&#xff0c;其中关系型数据库主要有Microsoft SQL Server ,MySQL,Oracle&#xff0c;SQLite等&#xff0c;常用的非关系型数据库包括Redis、DynamoDB&#xff0c;MongoDB等 ​​​​​​​ 一 关系型…

day2:TCP、UDP网络通信模型

思维导图 机械臂实现 #include <head.h> #define SER_POTR 8899 #define SER_IP "192.168.125.223" int main(int argc, const char *argv[]) {//创建套接字int cfdsocket(AF_INET,SOCK_STREAM,0);if(cfd-1){perror("");return -1;}//链接struct so…

Elasticsearch 数据类型相关总结:快速参考指南【记录】

在Elasticsearch中&#xff0c;有多种数据类型可用于定义字段。 在开始了解数据类型之前&#xff0c;首先要知道&#xff0c;在Elasticsearch中&#xff0c;分词处理主要针对文本字段&#xff0c;而对于其他类型字段&#xff08;如数值、日期、布尔等&#xff09;&#xff0c;通…

虚幻UE 材质-进阶边界混合之运行时虚拟纹理

之前在学习空山新雨后时对于边缘虚化过渡处理有很多技术 今天又要介绍一个边缘过渡的方法&#xff1a;运行时虚拟纹理 文章目录 前言一、运行时虚拟纹理二、使用步骤总结 前言 边缘过渡柔和的方式我们之前介绍了很多&#xff0c;但是效果也不是最好的。 像素偏移PDO和我们今天…

解决国内Linux服务器无法使用Github的方法

解决思路&#xff1a;修改Host https://www.ipaddress.com/ 利用上面的网站查询github.com和raw.githubusercontent.com的DNS解析的IP地址 最后&#xff0c;修改服务器的/etc/hosts 添加如下两行&#xff1a; 140.82.112.3 github.com 185.199.108.133 raw.githubuserconte…

IntelliJ IDEA 常用快捷键一览表(通用型,提高编写速度,类结构、查找和查看源码,替换与关闭,调整格式)

文章目录 IntelliJ IDEA 常用快捷键一览表1-IDEA的日常快捷键第1组&#xff1a;通用型第2组&#xff1a;提高编写速度&#xff08;上&#xff09;第3组&#xff1a;提高编写速度&#xff08;下&#xff09;第4组&#xff1a;类结构、查找和查看源码第5组&#xff1a;查找、替换…

bash shell基础命令(一)

文章目录 1.shell启动2. shell提示符3. bash手册3.1 man手册解读 4. 浏览Linux文件系统4.1 遍历目录4.1.1 绝对路径4.1.2 相对路径 4.2 列出目录和文件4.3 处理文件4.3.1创建文件4.3.2 复制文件4.3.3 链接文件4.3.3.1.软链接4.3.3.2 硬链接 4.3.4 文件重命名4.3.5 删除文件4.3.…

获取域控的方法

在域渗透中、作为渗透测试人员&#xff0c;获取域控的权限基本上可以获取整个内网的权限 1.高权限读取本地密码 当域管理员在域成员机器上登录进行工作的时候&#xff0c;会将明文密码保存在本地进行的lsass.exe&#xff0c;可以通过 mimikatz来读取到本地的明文密码。 priv…

HarmonyOS应用开发者高级认证试题库(鸿蒙)

目录 考试链接&#xff1a; 流程&#xff1a; 选择&#xff1a; 判断 单选 多选 考试链接&#xff1a; 华为开发者学堂华为开发者学堂https://developer.huawei.com/consumer/cn/training/dev-certification/a617e0d3bc144624864a04edb951f6c4 流程&#xff1a; 先进行…

01-开始Rust之旅

1. 下载Rust 官方推荐使用 rustup 下载 Rust&#xff0c;这是一个管理 Rust 版本和相关工具的命令行工具。下载时需要连接互联网。 这边提供了离线安装版本。本人学习的机器环境为&#xff1a; ubuntu x86_64&#xff0c;因此选用第②个工具链&#xff1b; 1. rust-1.75.0-x86_…

设计模式的学习笔记

设计模式的学习笔记 一. 设计模式相关内容介绍 1 设计模式概述 1.1 软件设计模式的产生背景 设计模式最初并不是出现在软件设计中&#xff0c;而是被用于建筑领域的设计中。 1977 年美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任 Christopher Alexander 在…

Vue 3 hooks的基本使用及疑问

前言 vue3也用过一段时间了&#xff0c;hooks听说过&#xff0c;但是一直没有用过。公司的前端项目里也没有相应的应用&#xff0c;因此打算系统的学习一下。 hooks与普通函数的区别 以实现一个加法功能为例。 普通函数未抽离 <template><div class"box&quo…

STM32 GD32 瑞萨 psoc 等单片机 无线wifi蓝牙最佳解决方案

新联鑫威一系列低功耗高性价比sdio wifi/蓝牙combo的模块CYWL6208 , CYWL6312, CYW6209等可以搭配stm32 各种型号例如以下,支持sta/ap/apsta&#xff0c;双模蓝牙的应用&#xff0c;支持rt-thread, freertos, Azure RTOS, Linux, Android系统. 稳定强&#xff0c;功耗低&#x…

HFSS笔记/信号完整性分析(二)——软件仿真设置大全

文章目录 1、多核运算设置1.1 如何设置1.2 如何查看自己电脑的core呢&#xff1f;1.3 查看求解的频点 2、求解模式设置Driven Terminal vs Driven modal 3、Design settings4、自适应网格划分5、更改字体设置 仅做笔记整理与分享。 1、多核运算设置 多核运算只对扫频才有效果&…

Java项目:11 Springboot的垃圾回收管理系统

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 功能介绍 本系统通过利用系统的垃圾回收流程&#xff0c;提高垃圾回收效率&#xff0c;通过垃圾回收的申请&#xff0c;增删改查&#xff0c;垃…

stm32 FOC系列 直流有刷控制原理

1、直流有刷驱动板 使用三极管搭建的简易 H 桥电路&#xff0c;如图 5.3.1 所示&#xff1a; 图 5.3.1 是使用三极管搭建的简易 H 桥电路&#xff0c;其中 MOTOR 表示直流有刷电机&#xff0c; Q1、 Q2、 Q3 和 Q4 为 4 个三极管&#xff0c;其中 Q1 和 Q3 接在了电源正极&…