【C++/STL】list(常见接口、模拟实现、反向迭代器)

 🌈个人主页:秦jh_-CSDN博客
🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12575764.html?spm=1001.2014.3001.5482

9efbcbc3d25747719da38c01b3fa9b4f.gif

目录

前言

 list的常见接口

对迭代器的封装

 节点

重载->

const迭代器

list与vector的对比

反向迭代器

 反向迭代器完整代码

list完整代码


前言

    💬 hello! 各位铁子们大家好哇。

             今日更新了list的相关内容
    🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

 list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。

 list的常见接口

对迭代器的封装

因为list的空间不是连续的,不能用原生指针,必须对其进行封装。 

 节点

重载->

当数据是自定义类型时,想通过->访问,就必须重载。 

const迭代器

用const迭代器,需要重新弄一个类,而const迭代器跟普通迭代器基本一样,只修改了部分,如果为此就重新弄一个类,代码就太冗余了。

  下面是进行的优化:

本质相当于写了一个类模板,编译器实例化生成了两个类。

list与vector的对比

反向迭代器

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

 反向迭代器完整代码

#pragma once //所以容器的反向迭代器
//迭代器适配器
namespace qjh
{//vector<T>::iteratortemplate<class Iterator,class Ref,class Ptr>  //给谁的正向迭代器,就适配出对应的反向迭代器struct ReverseIterator   {typedef ReverseIterator<Iterator, Ref, Ptr> Self;Iterator _it;ReverseIterator(Iterator it):_it(it){}Ref operator*(){Iterator tmp = _it;  //不能修改_it,得用临时变量放回return *(--tmp);}Ptr operator->(){//return _it->;//return _it.operator->();return &(operator*());}Self& operator++(){--_it;return *this;}Self& operator--(){++_it;return *this;}bool operator!=(const Self& s){return _it != s._it;}};
}

list完整代码

#pragma once
#include<assert.h>#include"ReverseIterator.h"	namespace qjh
{template<class T>struct ListNode   //需要全部被公开,用struct{ListNode<T>* _next;ListNode<T>* _prev;T _data;ListNode(const T& x=T()):_next(nullptr),_prev(nullptr),_data(x){}};template<class T,class Ref,class Ptr>struct ListIterator    //对指针进行封装,因为结点的空间不是连续的{typedef ListNode<T> Node;typedef ListIterator<T,Ref,Ptr> Self;Node* _node;ListIterator(Node* node):_node(node){}//*it//T& operator*()Ref operator*(){ return _node->_data;}//T* operator->()Ptr operator->(){return	&_node->_data;}//++itSelf& operator++(){_node = _node->_next;return *this;}//it++Self& operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}//--itSelf& operator--(){_node = _node->_prev;return *this;}//it--Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& it){return _node != it._node;}bool operator==(const Self& it){return _node == it._node;}};//template<class T>//struct ListConstIterator    //对指针进行封装,因为结点的空间不是连续的//{//	typedef ListNode<T> Node;//	typedef ListConstIterator<T> Self;//	Node* _node;//	ListConstIterator(Node* node)//		:_node(node)//	{}//	//*it//	const T& operator*()//	{//		return _node->_data;//	}//	const T* operator->()//	{//		return	&_node->_data;//	}//	//++it//	Self& operator++()//	{//		_node = _node->_next;//		return *this;//	}//	//it++//	Self& operator++(int)//	{//		Self tmp(*this);//		_node = _node->_next;//		return tmp;//	}//	//--it//	Self& operator--()//	{//		_node = _node->_prev;//		return *this;//	}//	//it--//	Self& operator--(int)//	{//		Self tmp(*this);//		_node = _node->_prev;//		return tmp;//	}//	bool operator!=(const Self& it)//	{//		return _node != it._node;//	}//	bool operator==(const Self& it)//	{//		return _node == it._node;//	}//};template<class T>class list{typedef ListNode<T> Node;public:/*typedef ListIterator<T> iterator;typedef ListConstIterator<T> const_iterator;*/typedef ListIterator<T,T&,T*> iterator;typedef ListIterator<T,const T&,const T*> const_iterator;typedef ReverseIterator<iterator, T&, T*> reverse_iterator;typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}//const迭代器需要迭代器指向的内容不能修改!const iterator不是我们需要的const迭代器//const 迭代器本身可以++等操作const_iterator begin() const{return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;}list(){empty_init();}list(initializer_list<int> il){empty_init();for (auto& e : il){push_back(e);}}//lt2(lt1)list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}//lt1=lt3list<T>& operator=(list<T> lt){swap(lt);return *this;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}~list(){clear();delete _head;_head = nullptr;}//void push_back(const T& x)//{//	Node* newnode = new Node(x);//	Node* tail = _head->_prev;//	tail->_next = newnode;//	newnode->_prev = tail;//	newnode->_next = _head;//	_head->_prev = newnode;//}void push_back(const T& x){insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());//迭代器不能-1,只能用-- }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->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;_size++;}iterator erase(iterator pos) //节点失效了,需要返回下一个节点{Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;_size--;return iterator(next); //匿名对象}size_t size() const{return _size;}bool empty(){return _size == 0;}private:Node* _head;size_t _size;};void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;lt.push_front(10);lt.push_front(20);lt.push_front(30);for (auto e : lt){cout << e << " ";}cout << endl;lt.pop_back();lt.pop_back();lt.pop_front();lt.pop_front();for (auto e : lt){cout << e << " ";}cout << endl;}struct A{int _a1;int _a2;A(int a1 = 0, int a2 = 0):_a1(a1),_a2(a2){}}; void test_list2(){list<A> lt;A aa1(1, 1);A aa2 = { 1, 1 };lt.push_back(aa1);lt.push_back(aa2);lt.push_back(A(2,2));lt.push_back({3,3});lt.push_back({4,4});list<A>::iterator it = lt.begin();while (it != lt.end()){ //cout << (*it)._a1 << ":" << (*it)._a2 << endl;//cout << it->_a1 << ":" << it->_a2 << endl;    //如果要遍历自定义类型,就要重载->,编译器为了可读性,省略了一个->cout << it.operator->()->_a1 << ":" << it.operator->()->_a2 << endl;++it;}cout << endl;}void PrintList(const list<int>& clt){list<int>::const_iterator it = clt.begin();while (it != clt.end()){//*it += 10; 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);lt.push_back(5);PrintList(lt);list<int> lt1(lt);PrintList(lt1);}
}

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

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

相关文章

2020长安杯

链接成功 检材一 1检材 1 的操作系统版本是 ()A. CentOS release 6.5 (Final)B. Ubuntu 16.04.3 LTSC. Debian GNU/ Linux 7.8 (wheezy)D. CentOS Linux release 7.6.1810 (Core)D 2检材 1 中&#xff0c;操作系统的内核版本是 ()(答案格式&#xff1a; “1.2.34” 数字和半角…

JVMの堆、栈内存存储

1、JVM栈的数据存储 通过前面的学习&#xff0c;我们知道&#xff0c;将源代码编译成字节码文件后&#xff0c;JVM会对其中的字节码指令解释执行&#xff0c;在解释执行的过程中&#xff0c;又利用到了栈区的操作数栈和局部变量表两部分。 而局部变量表又分为一个个的槽位&…

前端将DOM元素导出为图片

前端工作中经常会用到把一些元素导出&#xff0c;比如表格&#xff0c;正好项目有遇到导出为excel和导出为图片&#xff0c;就都封装实现了一下&#xff0c;以供其他需求的开发者使用&#xff1a; 1.导出为文档 这个说白了就是下载的功能&#xff0c;传过去检索参数&#xff…

超分辨重建——SRGAN网络训练自己数据集与推理测试(详细图文教程)

&#x1f4aa; 专业从事且热爱图像处理&#xff0c;图像处理专栏更新如下&#x1f447;&#xff1a; &#x1f4dd;《图像去噪》 &#x1f4dd;《超分辨率重建》 &#x1f4dd;《语义分割》 &#x1f4dd;《风格迁移》 &#x1f4dd;《目标检测》 &#x1f4dd;《暗光增强》 &a…

计算机视觉与模式识别实验2-1 角点检测算法(Harris,SUSAN,Moravec)

文章目录 &#x1f9e1;&#x1f9e1;实验流程&#x1f9e1;&#x1f9e1;Harris算法SUSAN算法Moravec算法 &#x1f9e1;&#x1f9e1;全部代码&#x1f9e1;&#x1f9e1; &#x1f9e1;&#x1f9e1;实验流程&#x1f9e1;&#x1f9e1; Harris算法 Harris算法实现步骤&…

如何快速定位到影响mysql cpu飙升的原因——筑梦之路

通常我们只需要执行show processlist 进行查看&#xff0c;一般执行时间最长的SQL八九不离十就是罪魁祸首&#xff0c;但当show processlist的输出有近千条&#xff0c;那么很难第一眼就发现有问题的SQL&#xff0c;那么如何快速找到呢&#xff1f;其实也非常简单。我们知道mys…

JS面试题:什么是原型和原型链

一、原型 函数都有prototype属性,称之为原型&#xff0c;也称为原型对象原型 1.可以放一些属性和方法&#xff0c;共享给实例对象使用 2.原型可以做继承 二、原型链: 对象都有proto 属性,这个属性指向它的原型对象,原型对象也是对也有 proto 属性,指向原型对象的原型对象,这样一…

论文摘要一般要写些什么内容?

论文摘要通常需要包含以下几个关键内容&#xff1a; 研究背景与目的&#xff1a;简要介绍研究的背景信息&#xff0c;包括研究领域的重要性、当前的研究现状以及存在的问题。然后&#xff0c;清晰地阐述研究的目的、研究问题或研究假设&#xff0c;让读者明白研究的出发点和意图…

推荐一个图片识别的llama3微调版本 清华面壁项目

水一篇&#xff1a; MiniCPM-V是面向图文理解的端侧多模态大模型系列。该系列模型接受图像和文本输入&#xff0c;并提供高质量的文本输出。自2024年2月以来&#xff0c;我们共发布了4个版本模型&#xff0c;旨在实现领先的性能和高效的部署&#xff0c;目前该系列最值得关注的…

工业4.0利器:MES系统

工业4.0利器&#xff1a;MES系统 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &#x1f31d;分享学习心得&#xff0c;…

Java如何实现pdf转base64以及怎么反转?

问题需求 今天在做发送邮件功能的时候&#xff0c;发现邮件的附件部分&#xff0c;比如pdf文档&#xff0c;要求先把pdf转为base64&#xff0c;邮件才会发送。那接下来就先看看Java 如何把 pdf文档转为base64。 两种方式&#xff0c;一种是通过插件 jar 包的方式引入&#xf…

英语学习笔记31——Where‘s Sally?

Where’s Sally? Sally在哪&#xff1f; 词汇 Vocabulary garden /ˈɡɑːrdn/ n. 花园&#xff0c;院子&#xff08;属于私人&#xff09; 区别&#xff1a;park n. 公园&#xff08;公共的&#xff09; 例句&#xff1a;我的花园非常大。    My garden is very big. 搭…

【linux-imx6ull-设备树点灯】

目录 1. 设备树简介1.1 编译-引用1.2 设备树文件结构1.3 设备树节点介绍1.3.1 特殊节点chosen 1.4 节点内容追加 2. 设备树常用OF操作函数2.1 节点寻找类2.2 属性提取类2.3 其它常用类 4. 设备树下LED实验4.1 实验简介4.2 添加LED设备节点4.3 获取设备节点并提取属性4.3.1 获取…

深度学习-05-反向传播理论知识

深度学习-05-反向传播理论知识 本文是《深度学习入门2-自製框架》 的学习笔记&#xff0c;记录自己学习心得&#xff0c;以及对重点知识的理解。如果内容对你有帮助&#xff0c;请支持正版&#xff0c;去购买正版书籍&#xff0c;支持正版书籍不仅是尊重作者的辛勤劳动&#xf…

java面试题及答案2024,java2024最新面试题及答案(之一)

发现网上很多Java面试题都没有答案&#xff0c;所以花了很长时间搜集整理出来了这套Java面试题大全&#xff0c;希望对大家有帮助哈~ 本套Java面试题大全&#xff0c;全的不能再全&#xff0c;哈哈~ 一、Java 基础 1. JDK 和 JRE 有什么区别&#xff1f; JDK&#xff1a;Ja…

03_03_初识SpringAOP和应用

一、SpringAOP的初识与原理 1、概述 AOP&#xff1a;面向切面编程OOP&#xff1a;面向对象编程面相切面编程&#xff1a;是基于OOP基础之上的新编程思想&#xff0c;OOP面向的主要是对象是类&#xff0c;而AOP面向的主要对象是切面&#xff0c;它在处理日志、安全管理、事务管…

结账和反结账

结账与反结账功能在财务软件和会计系统中扮演着重要的角色&#xff0c;以下是关于这两个功能的详细解释&#xff1a; 一、结账功能 结账功能是计算和结转各个会计科目本期发生额和期末余额的过程&#xff0c;同时标志着一定时期内财务活动的结束和财务数据的固化。结账功能的…

C语言 链表经典OJ题

链表经典OJ题 移除链表元素链表的中间节点反转链表合并两个有序链表分割链表 移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head […

python小练习03

1.绘制奥运五环旗 #奥运五环的绘制 import turtle as t t.pensize(3) t.speed(0) def draw_circles():i0while i <4:args [[-60,0,"blue"],[0,0,"black"],[60,0,"red"],[-30,-30,"yellow"],[30,-30,"green"]]#定义一个…

lua vm 二: 查看字节码、看懂字节码

本文讲一讲如何查看 lua 的字节码&#xff08;bytecode&#xff09;&#xff0c;以及如何看懂字节码。 以下分析基于 lua-5.4.6&#xff0c;下载地址&#xff1a;https://lua.org/ftp/ 。 1. 查看字节码 1.1 方法一&#xff1a;使用 luac luac 是 lua 自带的编译程序&#x…