list下

文章目录

      • 注意:
      • const迭代器
        • 怎么写?
        • 运用场合?
      • insert
      • erase
      • 析构函数
      • 赋值和拷贝构造
        • 区别?
        • 拷贝构造不能写那个swap,为什么?
        • 拷贝构造代码
      • 面试问题
        • 什么是迭代器失效?
        • vector、list的区别?
      • 完整代码

注意:

delete 和delete[]之间不能用错
delete是单个;
delete是一个数组;
vector、string都是delete[];
list本质不是数组是列表,所以delete

const迭代器

怎么写?
		typedef __list_iterator<T, T&, T*> iterator; // 放public里面不然外面动不了T,就是用不了模板,私有的不能用typedef __list_iterator<T,const T&,const T*> const_iterator;//const迭代器//迭代器用节点的指针就行了iterator begin(){return iterator(_head->_next);//注意这里返回的是迭代器,不是_head头部指针、这个是list类里面的成员变量//现在是把头部指针_head传过去,然后迭代器调用他的拷贝函数;//这里面就是构造函数、因为传过去的是Node类型;}iterator end(){return iterator(_head);}//const_iteratorconst_iterator begin() const{return const_iterator(_head->_next); }const_iterator end() const{return const_iterator(_head);}

image.png
模板里面放多个参数,在传模板时候,如上图,右边框起来上面是普通的迭代器,下面有const,用哪种就会自动传过去,同时Self也是对应的迭代器;
image.png

运用场合?

一般const指针是不用的;
什么情况下去用?
传参给另一个函数用的时候会用到;
例如下面功能是打印的成员函数

	void print_list(const list<int>& lt){list<int>::const_iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;}

insert

在pos位置插入,这个pos是一个迭代器,插入后这个节点以及前后节点的_next和_prev要注意怎么赋值;
cur是pos指向的当前节点;
newnode是新插入的节点;
image.png

		//insert//现在要的是列表里面的那两个指针next\prev;//迭代器里面就有_node存的是Node*类型;void insert(iterator pos,const T& x = T()){Node* cur = pos._node;//pos是迭代器所以调用他的成员函数用点符号"."虽然类似指针但是不能->,这个是指针用的Node* prev = cur->_prev;Node* newnode = new Node(x);newnode->_next = cur;newnode->_prev = prev;cur->_prev = newnode;prev->_next = newnode;}

写完insert,push_back和push_front就可以直接用insert的

		//头插void push_front(const T& x = T()){insert(begin(), x);}//尾插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;//再pos是end()的时候插入,end()表示最后一个元素的后一个位置,所以插入这个位置就是尾插insert(end(), x);}

erase

头节点指向的迭代器就是end();
end()的意思是最后一个元素的后一个位置,那就是_head,这个头节点;
和insert类似,_next/_prev都要重新赋值一下:
image.png

		//erase,erase是要返回删除的位置的后一个位置的Node* erase(iterator pos){//cur里面存现在的地址//prev是cur上一个地址assert(pos  != end()); //头节点不能删Node* cur = pos._node;  Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;//delete[]必须是数组,所以要注意return next;}

头删除、和尾删除就可以用erase了

		//尾删void pop_back(){//erase(iterator(_head->_prev));erase(--end());}//头删除void pop_front(){erase(begin());}

析构函数

析构,栈里面的是先定义的后出去,现进后出;
析构是释放了还要置空;

		void clear(){Node* cur = _head->_next;while (cur != _head){_head->_next = cur->_next;delete cur;cur = _head->_next}_head = head->next = head->prev;//重新关联起来,双向带头循环列表;}//析构~list(){clear();detete _head;_head = nullptr;}

clear的作用是清空这个链表里面的内容,_head这个头节点是没有data的,所以是不用动的;
析构是直接这个链表对象空间释放了,所以_head也要释放;

赋值和拷贝构造

区别?

问:string为什么这边写了要先置位nullptr,然而这边的list没有呢?
答:
拷贝构造l1(l2),l1首先要初始化、至少里面是个nullptr,因为他还没有被创建出来;
赋值的话l1 = l2,首先你这个l1是不是已经是先定义出来的,所以不用初始化的;
image.png

拷贝构造不能写那个swap,为什么?

答:这样的话在传参数时就是又一个拷贝构造,那就会无限循环

拷贝构造代码
		//拷贝函数l1(l2)//首先l1是没有创建出来的,所以要初始化list(const list<T>& lt){//先初始化,list里面成员函数是什么?_head,_head里面的内容Node* _head;_head->_next = _head->_prev = _head;//往里面插入后面的值就行了//方法一/*const_iterator it = lt.begin();while (it != it.end()){push_back(*it);//运算符重载过*it了,传过去的是_node->_datait++;}*///方法二for (auto e : lt)//本质调用的迭代器{push_back(e);}}

在string和vector里面是这样的,for循环本质使用的是迭代器,有迭代器就有for循环,e理论上就是*it
image.png

面试问题

什么是迭代器失效?

迭代器失效具体内容

vector、list的区别?

vector是一个动态增长的数据
优点:支持随机访问operator[],排序、二分查找、堆算法等等可用到;
缺点:空间不够要增容、头部或者中间插入效率低o(n);

list是一个带头双向循环的链表
优点:任意位置插入效率高o(1);
缺点:不支持随机访问;

总结:list和vector相辅相成、是两个互补的容器

完整代码

test.c
在这里插入图片描述

#pragma once
namespace list_test
{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){}};//struct迭代器__list_iteratortemplate<class T, class Ref, class Ptr>//这个就是三个模板参数struct __list_iterator{typedef __list_node<T> Node;typedef __list_iterator<T, Ref, Ptr> Self;Node* _node;//构造函数,struct怎么写构造函数、就是看这个里面成员函数有哪些__list_iterator(Node* node):_node(node){}//构造传的是里面的成员函数、拷贝是传的类或者说这个结构体//浅拷贝,这个是默认函数、不用写的__list_iterator(const Self& it) {_node = it._node;}// operator*,读_node中的data,data的类型是T,所以函数返回值类型是TRef operator*(){return _node->_data;}//++Self& operator++(){_node = _node->_next;return *this;}//后置++Self operator++(int) //后置++里面就放个int,这是设计出来的伪参数,用来区分前后置用的{__list_iterator<T> tmp(*this); //直接拷贝函数、这个不用写、因为是浅拷贝,深拷贝才要写_node = _node->_next; //++(*this);return tmp;}//--Self& operator--(){_node = _node->_prev; //_node是指针return *this; //*this就是迭代器,this是指针指向迭代器}Self& operator--(int) //后置++里面就放个int,这是设计出来的伪参数,用来区分前后置用的{Self tmp(*this); //直接拷贝函数、这个不用写、因为是浅拷贝,深拷贝才要写//node = _node->_next;--(*this);return tmp;}//!=,两个迭代器之间不相等、迭代器里面的成员函数是_node,比的是这两个,就是他指向一个列表的地址,看这两个地址一样吗bool operator!=(const Self& it){return _node != it._node;}Ptr operator->(){return &_node->_data;//返回这个地址//指向这个地址,调用时第一个->返回其地址、第二个->返回地址上的值,迭代器做了优化,调用只需要一个->}};template<class T>class list{typedef __list_node<T> Node;public:typedef __list_iterator<T, T&, T*> iterator; // 放public里面不然外面动不了T,就是用不了模板,私有的不能用typedef __list_iterator<T,const T&,const T*> const_iterator;//const迭代器//迭代器用节点的指针就行了iterator begin(){return iterator(_head->_next);//注意这里返回的是迭代器,不是_head头部指针、这个是list类里面的成员变量//现在是把头部指针_head传过去,然后迭代器调用他的拷贝函数;//这里面就是构造函数、因为传过去的是Node类型;}iterator end(){return iterator(_head);}//const_iteratorconst_iterator begin() const{return const_iterator(_head->_next); }const_iterator end() const{return const_iterator(_head);}//构造函数list(){_head = new Node;//new node //这里面不用写成Node[],是因为[]是数组用的,这个就里面就开辟一个指针指向的地址空间,[]是一个数组的空间_head->_next = _head;_head->_prev = _head;}//insert//现在要的是列表里面的那两个指针next\prev;//迭代器里面就有_node存的是Node*类型;void insert(iterator pos,const T& x = T()){Node* cur = pos._node;//pos是迭代器所以调用他的成员函数用点符号"."虽然类似指针但是不能->,这个是指针用的Node* prev = cur->_prev;Node* newnode = new Node(x);newnode->_next = cur;newnode->_prev = prev;cur->_prev = newnode;prev->_next = newnode;}//头插void push_front(const T& x = T()){insert(begin(), x);}//尾插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;//再pos是end()的时候插入,end()表示最后一个元素的后一个位置,所以插入这个位置就是尾插insert(end(), x);}//erase,erase是要返回删除的位置的后一个位置的Node* erase(iterator pos){//cur里面存现在的地址//prev是cur上一个地址assert(pos  != end()); //头节点不能删Node* cur = pos._node;  Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;//delete[]必须是数组,所以要注意return next;}//尾删void pop_back(){//erase(iterator(_head->_prev));erase(--end());}//头删除void pop_front(){erase(begin());}void clear(){Node* cur = _head->_next;while (cur != _head){_head->_next = cur->_next;delete cur;cur = _head->_next}_head = head->next = head->prev;//重新关联起来,双向带头循环列表;}//析构~list(){clear();detete _head;_head = nullptr;}//拷贝函数l1(l2)//首先l1是没有创建出来的,所以要初始化list(const list<T>& lt){//先初始化,list里面成员函数是什么?_head,_head里面的内容Node* _head;_head->_next = _head->_prev = _head;//往里面插入后面的值就行了//方法一/*const_iterator it = lt.begin();while (it != it.end()){push_back(*it);//运算符重载过*it了,传过去的是_node->_datait++;}*///方法二for (auto e : lt)//本质调用的迭代器{push_back(e);}}//赋值运算l1 = l2//方法一:list<T>& operator=(const list<T>& lt){//防止自己给自己赋值if (this != &lt)//用地址来比较{clear();//看clear函数,clear结束后就是初始化后的_head,所以也不用再写一遍_head的初始话for (auto e : lt)push_back(e);//就一行不用写{}了}return *this;//*this,解引用this迭代器就是这个list类的对象了l1}//方法二:list<T>& operator=(list<T> lt)//这里传参用到拷贝构造,lt是临时对象{swap(_head, lt._head)return *this;//*this,解引用this迭代器就是这个list类的对象了l1}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;}void print_list(const list<int>& lt){list<int>::const_iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;}void test_list3(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);print_list(lt);lt.pop_front();lt.pop_back();print_list(lt);}
}

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

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

相关文章

qt学习:QT对话框+颜色+文件+字体+输入

目录 概述 继承图 QColorDialog 颜色对话框 QFileDialog 文件对话框 保存文件对话框 QFontDialog 字体对话框 QInputDialog 输入对话框 概述 对于对话框的功能&#xff0c;在GUI图形界面开发过程&#xff0c;使用是非常多&#xff0c;那么Qt也提供了丰富的对话框类QDia…

网络:FTP

1. FTP 文件传输协议&#xff0c;FTP是用来传输文件的协议。使用FTP实现远程文件传输的同时&#xff0c;还可以保证数据传输的可靠性和高效性。 2. 特点 明文传输。 作用&#xff1a;可以从服务器上下载文件&#xff0c;或将本地文件上传到服务器。 3. FTP原理 FTP有控制层面…

坦克大战游戏代码

坦克大战游戏 主函数战场面板开始界面坦克父类敌方坦克我方坦克子弹爆炸效果数据存盘及恢复图片 主函数 package cn.wenxiao.release9;import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.JFrame; import javax.swing.JMenu; impor…

RS-485通讯

RS-485通讯协议简介 与CAN类似&#xff0c;RS-485是一种工业控制环境中常用的通讯协议&#xff0c;它具有抗干扰能力强、传输距离远的特点。RS-485通讯协议由RS-232协议改进而来&#xff0c;协议层不变&#xff0c;只是改进了物理层&#xff0c;因而保留了串口通讯协议应用简单…

【HarmonyOS】掌握布局组件,提升应用体验

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…

【RT-DETR有效改进】华为 | GhostnetV2移动端的特征提取网络效果完爆MobileNet系列

前言 大家好&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持ResNet32、ResNet101和PP…

自动控制原理——数学模型建立

目标 1.数学模型概念 描述系统输入、输出变量以及内部个变量之间的关系的数学表达式 2.建模方法 解析法&#xff08;机理解析法&#xff09;: 根据系统工作所依据的物理定律写运动方程 实验法&#xff08;系统辨识法&#xff09;&#xff1a; 给系统施加某种测试信号&am…

万户 ezOFFICE wf_process_attrelate_aiframe.jsp SQL注入漏洞复现

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品,统一的基础管理平台,实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台,将外网信息维护、客户服务、互动交流和日…

Intel开发环境Quartus、Eclipse与WSL的安装

PC &#xff1a;win10 64bit 安装顺序&#xff1a;先安装Quartus 21.4&#xff0c;接着Eclipse或者WSL&#xff08;Windows Subsystem for Linux&#xff09;&#xff0c;Eclipse与WSL的安装不分先后。 为什么要安装Eclipse&#xff1f; 因为Eclipse可以开发基于Nios II的C/…

SwiftUI 框架有哪些主要优势

SwiftUI是苹果公司在2019年推出的一种用于构建用户界面的框架&#xff0c;它使用Swift语言编写&#xff0c;并且与iOS、iPadOS、macOS、watchOS和tvOS等平台兼容。下面简单的看下有哪些主要的优势。 声明式的界面描述 使用声明式编程风格&#xff0c;通过简洁的代码描述用户界…

力扣645.错误的集合

一点一点地刷&#xff0c;慢慢攻克力扣&#xff01;&#xff01; 王子公主请看题 集合 s 包含从 1 到 n 的整数。不幸的是&#xff0c;因为数据错误&#xff0c;导致集合里面某一个数字复制了成了集合里面的另外一个数字的值&#xff0c;导致集合 丢失了一个数字 并且 有一个数…

C++:基于C的语法优化

C&#xff1a;基于C的语法优化 命名空间命名空间域域作用限定符展开命名空间域 输入输出缺省参数全缺省参数半缺省参数 函数重载参数类型不同参数个数不同参数类型的顺序不同 引用基本语法按引用传递返回引用引用与指针的区别 内联函数autoauto与指针和引用结合 范围for循环nul…

红队打靶练习:W34KN3SS: 1

目录 信息收集 1、arp 2、nmap 3、nikto 4、gobuster 5、dirsearch WEB web信息收集 目录探测 漏洞利用 openssl密钥碰撞 SSH登录 提权 get user.txt get passwd 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, type: EN10MB…

羊驼系列大模型LLaMa、Alpaca、Vicuna

羊驼系列大模型&#xff1a;大模型的安卓系统 GPT系列&#xff1a;类比ios系统&#xff0c;不开源 LLaMa让大模型平民化 LLaMa优势 用到的数据&#xff1a;大部分英语、西班牙语&#xff0c;少中文 模型下载地址 https://huggingface.co/meta-llama Alpaca模型 Alpaca是斯…

java枚举详细解释

枚举的基本认识 我们一般直接定义一个单独的枚举类 public enum 枚举类名{枚举项1,枚举项2,枚举项3 } 可以通过 枚举类名.枚举项 来访问该枚举项的 - 可以理解为 枚举项就是我们自己定义的一个数据类型,是独一无二的 接下来我们直接用一个例子来完全理解 加深理解 这里…

VScode代码查找、替换

快捷方法按CtrlF Mac为CommandF 右上角出现的框就是查找框&#xff0c;可以输入想找的内容 点击左边的小尖儿&#xff0c;输入替换的内容后 按回车是替换一个&#xff0c;按Ctrl回车&#xff08;Command回车&#xff09;是全替换&#xff0c;点击右边那两个图案也可以&#x…

DHCP配置(路由器,交换机)

DHCP接口地址池配置 拓扑 PC配置DHCP点击应用。 路由器配置命令 <Huawei>sy Enter system view, return user view with CtrlZ. [Huawei]int g0/0/1[Huawei-GigabitEthernet0/0/1]ip address 10.1.1.1 24[Huawei-GigabitEthernet0/0/1]q[Huawei]dhcp enable Info: T…

DBA技术栈MongoDB: 索引和查询优化

2.1 批量插入数据 单条数据插入db.collection.insertOne()多条数据插入db.collection.insertMany() db.inventory.insertMany( [{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },{ item: "notebook"…

web蓝桥杯真题--12、由文本溢出引发的“不友好体验”

背景介绍 通常情况下&#xff0c;为保证布局的稳定性&#xff0c;以及遵循在有限的空间展示更多内容的原则&#xff0c;页面的某块区域不会随内容的增多而无限增高或增宽&#xff0c;一般会有一个约束。 例如&#xff1a;整体元素过多可以使用滚动条&#xff1b;文字内容过多…

供应链安全项目in-toto开源框架详解

引言&#xff1a;in-toto 是一个开源框架&#xff0c;能够以密码学的方式验证构件生产路径上的每个组件和步骤。它可与主流的构建工具、部署工具进行集成。in-toto已经被CNCF技术监督委员会 (Technical Oversight Committee&#xff0c;TOC)接纳为CNCF孵化项目。 1. 背景 由于…