【1++的C++初阶】之适配器

news2024/11/25 15:50:09

👍作者主页:进击的1++
🤩 专栏链接:【1++的C++初阶】

文章目录

  • 一,什么是适配器
  • 二,栈与队列模拟实现
  • 三,优先级队列
  • 四,reverse_iterator

一,什么是适配器

在这里插入图片描述
适配器作为STL的六大组件之一,其本质是一种设计模式,将一个class的接口转换为另一个class的接口。比如说我们接下来要进行模拟实现的stack。若是以vector为底层,其实就是对vector接口的再次封装。因此其虽然也能够存储数据,但在STL中其却不属于容器。

二,栈与队列模拟实现

栈与队列的详细剖析与说明在前面的【1++的数据结构初阶】中已经写过有关文章。若有疑惑可移步至专栏中查看。本篇中进行的实现主要基于适配器的设计模式,因此底层较为简单。
栈的实现

template <class T,class container=std::deque<T>>
	class stack
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);
		}

		T& top()
		{
			return _con.back();
		}

		void pop()
		{
			_con.pop_back();
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.emnpty();
		}


	private:
		container _con;
	};

队列的实现

template<class T,class container=std::deque<T>>
	class queue
	{
	public:

		void push(const T& val)
		{
			_con.push_back(val);
		}

		void pop()
		{
			_con.pop_front();
		}

		T& front()
		{
			return _con.front();
		}

		T& back()
		{
			return _con.back();
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.empty();
		}
	private:
		container _con;
	};

可能有人会疑惑,模板中的container是什么鬼?
在这里插入图片描述
来,让我们看看官方的解释:
在这里插入图片描述
其就是存储元素的内部容器的类型
在直接点就是成员类型。例如:stack中的成员——_con的类型就为deque。
那么问题来了什么又是deque呢?
在这里插入图片描述
接下来我们对deque进行一个简单的介绍了。
deque是一种双端队列,其可以在头尾进行插入和删除,并且时间复杂度为O(1)。与vector相比,其可以进行头插与头删;与list相比,其对数据的随机访问的效率高。
是不是对deque的底层实现越发的好奇了。

在这里插入图片描述
让我们来解开这层神秘的面纱。
deque的底层空间并不是连续的,而是一个个小块。类似于二维数组一样。
在这里插入图片描述
之所以选择deque作为栈和队列的底层默认容器,正是看中了其头尾在进行操作时的高效率。
deque若如此完美,那为什么不大量应用呢?原因在于其也有缺点。
deque在进行遍历时,要经过稍复杂的计算才能够计算出其在哪一块的哪个位置,所以,当数据量大时,其遍历的效率比较低。并且其中间的插入,删除效率也不高。

三,优先级队列

什么是priority_queue(优先级队列)?
它也是一种适配器,其在默认情况下,第一个位置的元素总是最大的。类似于堆。其底层容器的前提是可以通过随机访问迭代器进行随机访问。
priority_queue的实现

template<class T>
	class less
	{
	public:
		bool operator()(const T& left, const T& right)const
		{
			return left < right;
		}
	};


	template<class T>
	class greater
	{
	public:
		bool operator()(const T& left, const T& right)const
		{
			return left > right;
		}
	};

	template<class T,class container=std::vector<T>,class compare=greater<T>>
	class priority_queue
	{
	public:
		
		void adjust_up()
		{
			size_t child = _con.size() - 1;
			size_t parent = (child-1)/2;
			while (child > 0)
			{
				compare com;
				if (com(_con[parent],_con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent=(child - 1) / 2;
				}
				else
				{
					break;
				}
			}


		}

		void adjust_down()
		{
			//默认左孩子为大----大堆前提下
			size_t parent = 0;
			size_t child = parent* 2+1;
			while (child < _con.size())
			{
				compare com;
				if ((child + 1) < _con.size() && com(_con[child], _con[child+1]))
				{
					child++;
				}

				if (com(_con[parent], _con[child]))
				{
					std::swap(_con[parent], _con[child]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}

			}
		}
		void push(const T& val)
		{
			//向上调整
			_con.push_back(val);
			adjust_up();
		}

		const T& top()const
		{
			return _con[0];
		}


		void pop()
		{
			std::swap(_con.back(), _con[0]);
			_con.pop_back();
			//向下调整
			adjust_down();
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.empty();
		}
	private:
		container _con;
	};

优先级队列在push建堆时,使用的是向上调整,时间复杂度为O(logN) ,在默认为大堆的情况下,孩子结点于父亲结点比较,若大于父亲结点,则进行交换,直到小于父亲结点或者到达根节点。
在代码中,我们还发现了其比较大小的写法与以往不同。
在这里插入图片描述
这叫做做仿函数,其与普通函数的调用相差不大,但其本质是类对象调用重载后的(),即operator() 。

四,reverse_iterator

反向适配器其底层为正向迭代器。其也是适配器的一种。
具体实现如下:

template<class Iterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<Iterator,Ref,Ptr> Riterator;
		
		reverse_iterator(Iterator it)
			:cur(it)
		{}

		Riterator operator++()
		{
			--cur;
			return *this;
		}

		Riterator operator--()
		{
			++cur;
			return *this;
		}

		Ref operator*()
		{
			Iterator tmp = cur;
			--tmp;
			return *tmp;
		}

		Ptr operator->()
		{
			return &(*operator());
		}

		bool operator!=(const Riterator& it)
		{
			return cur != it.cur;
		}

	private:
		Iterator cur;

	};

       reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}

		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}

反向迭代器与rbegin(),rend() 进行搭配,通过观察我们发现,其rend(),实际返回的是begin(),rbegin()返回的是end()。恰好对称。并且,反向迭代器中的++,实际上为正向迭代器的- -; --则实际上为++。
需要注意的是operator*()的实现。其返回的是当前迭代器指向的元素的下一个元素(右往左数)。这样做的原因是:end()指向的是最后一个元素的下一位置。并且,由于对称的原因,rbegin指向的位置与end相同,因此在返回其元素的时候,就需要返回其下以位置的元素。
在这里插入图片描述

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

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

相关文章

【高阶数据结构】跳表

文章目录 一、什么是跳表二、跳表的效率如何保证&#xff1f;三、skiplist的实现四、skiplist跟平衡搜索树和哈希表的对比 一、什么是跳表 skiplist本质上也是一种查找结构&#xff0c;用于解决算法中的查找问题&#xff0c;跟平衡搜索树和哈希表的价值是 一样的&#xff0c;可…

Windows环境Docker安装

目录 安装Docker Desktop的步骤 Docker Desktop 更新WSL WSL 的手动安装步骤 Windows PowerShell 拉取&#xff08;Pull&#xff09;镜像 查看已下载的镜像 输出"Hello Docker!" Docker Desktop是Docker官方提供的用于Windows的图形化桌面应用程序&#xff0c…

区间预测 | MATLAB实现QRBiLSTM双向长短期记忆神经网络分位数回归多输入单输出区间预测

区间预测 | MATLAB实现QRBiLSTM双向长短期记忆神经网络分位数回归多输入单输出区间预测 目录 区间预测 | MATLAB实现QRBiLSTM双向长短期记忆神经网络分位数回归多输入单输出区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 区间预测 | MATLAB实现QRBiLSTM…

odoo16 用好计量单位中的激活功能

odoo16 用好计量单位中的激活功能 根据国内常用&#xff0c;把不常用的单位去除&#xff0c;删除不了&#xff0c;提示已用&#xff0c;其实不用删除&#xff0c;每个单位后有个激活功能&#xff0c;选一下就可以了&#xff0c;显示成整洁的界面了 第一次用时&#xff0c;小伙伴…

解决spring cloud 中使用spring security全局异常处理器失效

写auth认证模块实现忘记密码与注册功能时&#xff0c;用异常抛出&#xff0c;全局异常处理器无法捕获。 无法进行异常捕捉 解决方案&#xff1a;使用WebSecurityConfigurerAdapter.configure中http实现自定义异常&#xff1a; EnableWebSecurity EnableGlobalMethodSecurity(…

87、springcloud核心组件及其作用

spring Eureka: 服务注册与发现 注册:&#xff1a;每个服务都向Eureka登记自己提供服务的元数据&#xff0c;包括服务的ip地址、端口号、版本号、通信协议等 eureka将各个服务维护在了一个服务清单中 (双层Map&#xff0c;第一层key是服务名&#xff0c;第二层key是实例名&…

macOS 源码编译 qpress

╰─➤ git clone https://github.com/PierreLvx/qpress.git ╰─➤ cd qpress ╰─➤ make g -O3 -o qpress -x c quicklz.c -x c qpress.cpp aio.cpp utilities.cpp -lpthread -Wall -Wextra -Werror ╰─➤ sudo make install …

Vue--》打造个性化医疗服务的医院预约系统(三)

今天开始使用 vue3 + ts 搭建一个医院预约系统的前台页面,因为文章会将项目的每一个地方代码的书写都会讲解到,所以本项目会分成好几篇文章进行讲解,我会在最后一篇文章中会将项目代码开源到我的GithHub上,大家可以自行去进行下载运行,希望本文章对有帮助的朋友们能多多关…

Java基础小知识(待续)

类型转换、ASCII码、除法取余、三元表达式 long x 100;//int->long自动类型转换&#xff08;隐式) 1&#xff0e;特点:代码不需要进行特殊处理&#xff0c;自动完成。2&#xff0e;规则:数据范围从小到大。double y 2.5F;//2.5 float->double自动类型转换&#xff08…

pyqt5-Ctrl+鼠标滚轮实现文本区文字大小调整

技术简介 在 PyQt5 中&#xff0c;你可以使用 QTextEdit 的 wheelEvent 方法和 QKeyEvent 的 key() 方法来检测 Ctrl 键和鼠标滚轮事件&#xff0c;从而实现按下 Ctrl 键并滚动鼠标滚轮时&#xff0c;调整 QTextEdit 的字体大小。 这个示例中&#xff0c;我们创建了一个窗口&am…

模板方法模式(java)

目录 结构 案例 代码实现 抽象类 具体子类 测试类 优缺点 优点 缺点 结构 模板方法&#xff08;Template Method&#xff09;模式包含以下主要角色&#xff1a; 抽象类&#xff08;Abstract Class&#xff09;&#xff1a;负责给出一个算法的轮廓和骨架。它由一个模板…

基于SPDK-vhost的云原生Kubevirt虚拟化存储IO的优化方案

摘要 本文主要介绍针对云原生kubernetes虚拟化IO的应用场景&#xff0c;在Kubevirt中引入SPDK-vhost的支持&#xff0c;来加速虚机中IO存储性能。同时基于Intel开源的Workload Service Framework[1]平台集成部署一套端到端虚拟化IO的应用场景做基本的性能对比测试。 云原生Kube…

Failed to load response data:No data found for resource with given identifier

前言 关于跨域的另一种解释 前端Ajax访问后端&#xff0c;表单提交&#xff0c;有一个接口报错&#xff0c;其他都没问题 网上看了很多案例方法&#xff0c;均不适用&#xff1b;早上改代码过程中&#xff0c;改好了&#xff0c;话不多说&#xff0c;上原因 原因 提前关闭页…

CentOS7系统下Docker容器基于TensorFlow测试GPU

前言 当基于nvidia gpu开发的docker镜像在实际部署时&#xff0c;需要先安装nvidia docker。安装nvidia docker前需要先安装原生docker compose 1. CentOS7安装docker详细教程 安装docker 1. Docker 要求 CentOS 系统的内核版本高于 3.10 &#xff0c;查看本页面的前提条件来验…

辅助笔记-linux新增硬盘

linux新增硬盘 文章目录 linux新增硬盘步骤1&#xff1a;添加硬盘步骤2&#xff1a;对硬盘进行分区步骤3&#xff1a;对硬盘分区进行格式化步骤4&#xff1a;将硬盘分区挂载到目录上步骤5&#xff1a;设置“永久挂载” 本文主要参考B站视频“P59_韩顺平Linux_增加磁盘应用实例”…

IDEA: 将第三方依赖打入jar包

文章目录 一、添加自定义的jar包到lib目录下二、将自定义依赖包打入jar包方式1、使用springboot自带的插件 一、添加自定义的jar包到lib目录下 参考往期文章&#xff1a;IDEA中Java项目创建lib目录(添加依赖jar包代替maven依赖) 二、将自定义依赖包打入jar包 方式1、使用spr…

centos7下载mysql5.7,jdk1.8

前言&#xff1a;最近公司服务器从阿里云换到腾讯云了&#xff08;为了省钱啧啧&#xff09;&#xff0c;所以这个相关环境的配置工作&#xff0c;由我来负责了。 1.Mysql 1.下载 第一步&#xff1a; rpm -ivh https://dev.mysql.com/get/mysql57-community-release-el7-11…

【算法基础:数学知识】4.4 快速幂

文章目录 快速幂例题列表875. 快速幂⭐⭐⭐⭐⭐&#xff08;重要&#xff01;&#xff09;代码写法1——递归代码写法2——迭代递归写法 与 迭代写法的 对比 876. 快速幂求逆元&#x1f6b9;&#xff08;需要理解逆元的概念&#xff09;TODO乘法逆元介绍解法代码 快速幂 https…

python机器学习(三)特征预处理、鸢尾花案例--分类、线性回归、代价函数、梯度下降法、使用numpy、sklearn实现一元线性回归

K-近邻算法(K-Nearest Neighboor) 特征预处理 数据预处理的过程。数据存在不同的量纲、数据中存在离群值&#xff0c;需要稳定的转换数据&#xff0c;处理好的数据才能更好的去训练模型&#xff0c;减少误差的出现。 标准化 数据集的标准化对scikit-learn中实现的大多数机器…

WPF实战项目十(API篇):引入工作单元UnitOfWork

1、通过github地址&#xff1a;https://github.com/arch/UnitOfWork&#xff0c;下载UnitOfWork的代码&#xff0c;将工作单元部分的代码引用到自己的项目&#xff0c;新增UnitOfWork文件夹。 2、在UnitOfWork文件夹下引用UnitOfWork下的IPagedList.cs、PagedList.cs类&#xf…