栈和队列优先级队列适配器原理

栈和队列接口函数

stack 栈接口函数

因为栈的结构限制,栈只能栈顶push和栈顶pop,

所以接口略少

queue 队列接口函数

队列只比栈多了一个接口:back
队列的front相当于栈的top

适配器

栈的类模板

其中第二个参数是Container,

且缺省参数为deque<T>

到这就可以引入一个概念:适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

可以类比为

在数据结构的栈中,这种适配器是什么?

在C语言阶段实现栈时,我们
使用的底层是顺序表来实现,也就是
把顺序表做了一层封装和限制,让它
的功能变得和栈一样,C++这里也是一样!

实现栈时不用再去写一个顺序表
而是直接调用库中的vector!

队列的类模板

其中第二个参数是Container,

且缺省参数为deque<T>

和stack是一样的

栈和队列模拟实现

namespace wr
{
	template<class T, class Container>
		class stack
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_back();
		}
		const T& top()
		{
			return _con.back();
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}

队列

namespace wr1 
{
	template<class T,class Container = std::deque<T>>
	class queue
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_front();
		}
		const T& front()
		{
			return _con.front();
		}
		const T& back()
		{
			return _con.back();
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};

}

我们和库中的缺省值保持一致,使用deque

这样实现栈十分方便,因为此时的栈就好像继承家业一样,

不用再去写构造和析构函数,默认生成的构造析构函数

会去调用内嵌类型的构造或析构,

在基础上实现接口函数就可以了。

deque基本介绍

deque也是STL库中的一个容器:

deque又被称为双端队列是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素,与list比较,空间利用率比较高(啥都能干,啥都干的不是特别好,既支持头插头删也有尾插尾删,也支持[]

接口函数

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:

deque通过一个叫中控数组的来控制(map箭头指向的数组)

deque扩容是直接另外开辟一份空间
再让中控数组指向新开辟的空间
再将原先空间的内容拷贝至新空间

优先级队列

优先级队列:priority_queue

它也是一个容量适配器

优先级队列默认是大堆

它的底层适配器默认是vector

优先级队列默认有三个类模板,第三个
模板就是决定此优先级队列是大堆还是小堆
它是仿函数,默认的less是大堆
我们显示传参greater时是小堆!

优先级队列的接口函数:

如果你想使用小堆,就要将前两个
模板参数实例化后才能实例化第三个
当less变成greater时,就是小堆

如果要改变大小堆,需要将参数补全,vector<int>也需要写上

优先级队列的模拟实现

由于优先级队列实际上就是个堆
所以在插入,删除之后.都需要做一件事
那就是向上调整或向下调整!所以插入和
删除的关键其实就在于向上/下调整!

向上调整:

		void up(size_t child)
		{
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[child] > _con[parent])
				{
					std::swap(_con[child], _con[parent]);
					child = parent;
					parent = (parent - 1) / 2;
				}
				else
					break;
			}
		}

向下调整:

		void down(size_t parent)
		{
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && _con[child + 1] > _con[child])
				{
					++child;

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

全部代码:

namespace wr2 
{
	template<class T,class Container=std::vector<T>>
	class priority 
	{
	public:		
		size_t size()
		{
			return _con.size();
		}
		void up(size_t child)
		{
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[child] > _con[parent])
				{
					std::swap(_con[child], _con[parent]);
					child = parent;
					parent = (parent - 1) / 2;
				}
				else
					break;
			}
		}
		void down(size_t parent)
		{
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && _con[child + 1] > _con[child])
				{
					++child;

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

		void push(const T& x)
		{
			_con.push_back(x);
			up(_con.size() - 1);
		}
		void pop()
		{
			std::swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			down(0);
		}
		const T& top()
		{
			return _con[0];
		}
		bool empty()
		{
			return _con.empty();
		}

	private:
		Container _con;
	};

}

总结

通过前面的容器学习,栈和队列学习起来也更加得心应手,

不仅仅是模拟实现,可以复用以前的容器,

连使用方法和函数接口都和之前一样,

而deque更像一个”六边形战士“,

不过各项能力都不出众。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux操作系统学习:day02

内容来自&#xff1a;Linux介绍 视频推荐&#xff1a;[Linux基础入门教程-linux命令-vim-gcc/g -动态库/静态库 -makefile-gdb调试]( day02 5、Linux目录结构 操作系统文件结构的开始&#xff0c;只有一个单独的顶级目录结构&#xff0c;叫做根目录。所有一切都从“根”开始…

汇编:数组-寻址取数据

比例因子寻址&#xff1a; 比例因子寻址&#xff08;也称为比例缩放索引寻址或基址加变址加比例因子寻址&#xff09;是一种复杂的内存寻址方式&#xff0c;常用于数组和指针操作。它允许通过一个基址寄存器、一个变址寄存器和一个比例因子来计算内存地址。 语法 比例因子寻…

高清实拍类型视频素材去哪里找?高清实拍素材网站分享

在这篇文章中&#xff0c;我将为大家介绍一些高清实拍类型的视频素材资源&#xff0c;这些资源对于我们新媒体创作者来说至关重要。优质的视频素材能显著提升作品的吸引力&#xff0c;因此选择合适的视频素材平台非常关键。下面我将详细介绍几个非常实用的视频素材平台&#xf…

这才是打开Java面试的正确方式,金九银十互联网大厂Java面试八股来袭

前言 秋招过后招聘旺季就到了&#xff0c;不知道大家是否准备好了&#xff0c;面对金九银十的招聘旺季&#xff0c;如果没有精心准备那笔者认为那是对自己不负责任&#xff1b;就我们 Java 程序员来说&#xff0c;多数的公司总体上面试都是以自我介绍项目介绍项目细节/难点提问…

Java-Lambda表达式基本理解及使用

Lambda表达式基本理解及使用 背景Lambda 表达式语法函数式接口常见的函数式接口Function<T, R>Consumer<T>Supplier<T>Predicate<T>UnaryOperator<T>BinaryOperator<T> Lambda表达式的基本使用有返回值函数式接口无返回值函数式接口Lambda…

excel两个数据表格,怎样实现筛选的联动?

如图&#xff0c;想要通过处理器或者像素条件进行筛选&#xff0c;形成一个右边图2的对比表&#xff0c;如何实现实现联动显示呢&#xff1f; 这个在excel里可以借用数据透视表切片器来完成。步骤如下&#xff1a; 1.添加表 选中数据区域中任意一个单元格&#xff0c;点击 插…

Java--数组的声明和创建

1.首先必须声明数组变量&#xff0c;才能在程序中使用数组。下面是声明数组变量的语法&#xff1a; 首选的方法为Java的方法&#xff0c;另一种方法是由C或C引入过来的&#xff0c;日常使用首选Java的方法 dataType[] arrayRefVar; //首选的方法 或 dataType arrayRefVar[]…

多年不见,我美少女又回来了!

各位&#xff0c;可能很多人都不记得我了&#xff0c;上学的时候喜欢记学习笔记&#xff0c;好多学弟学妹们经常来我的博客看笔记&#xff0c;对于学习也有帮助。 时过境迁&#xff0c;生活中的琐事和繁忙的工作&#xff0c;真的自顾不暇… 还记得之前说要转型给大家分享内容运…

【算法与数据结构】【数组篇】【题6-题10】

系列文章 本人系列文章-CSDN博客https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5502 1.数组基本知识点 1.1概念 数组就是一个集合。数组会用一些名为索引的数字来标识每项数据在数组中的位置&#xff0c;且在大多数编程语言中&…

嵌入式系统概述

嵌入式系统是为了特定应用而专门构建的计算机系统&#xff0c;其嵌入式软件的架构设计与嵌入式系统硬件组成紧密相关。 1.嵌入式系统发展历程 嵌入式系统的发展大致经历了五个阶段&#xff1a; 第一阶段&#xff1a;单片微型计算机&#xff08;SCM&#xff09;&#xff0c;及…

鸿蒙开发文件管理:【@ohos.fileio (文件管理)】

文件管理 该模块提供文件存储管理能力&#xff0c;包括文件基本管理、文件目录管理、文件信息统计、文件流式读写等常用功能。 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 impor…

我要成为算法高手-双指针篇

目录 什么是双指针?问题1&#xff1a;移动零问题2&#xff1a;复写零问题3&#xff1a;快乐数问题4&#xff1a;盛最多水的容器问题5&#xff1a;有效三角形个数问题6&#xff1a;查找总价格和为目标值的两个商品(两数之和)问题7&#xff1a;三数之和问题8&#xff1a;四数之和…

【Affine / Perspective Transformation】

文章目录 仿射变换介绍仿射变换 python 实现——cv2.warpAffine透视变换透视变换 python 实现——cv2.warpPerspective牛刀小试各类变换的区别与联系仿射变换和单应性矩阵透视变换和单应性矩阵 仿射变换介绍 仿射变换&#xff08;Affine Transformation&#xff09;&#xff0…

鸿蒙轻内核A核源码分析系列四(2) 虚拟内存

本文我们来熟悉下OpenHarmony鸿蒙轻内核提供的虚拟内存&#xff08;Virtual memory&#xff09;管理模块。 本文中所涉及的源码&#xff0c;以OpenHarmony LiteOS-A内核为例&#xff0c;均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_a 获取。如果涉及开发板…

基于微信小程序的“最多跑一次”警务信息管理系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;ssm 【…

Linux用户,用户组,所有者权限分配,sftp用户权限分配

注意以下命令执行需要在root用户下执行 tenant命令切换至root命令 sudo -do root 删除用户信息 1.不删除用户主目录 userdel user_name 2.删除用户主目录 userdel -r user_name usermod命令修改用户账户权限 更改用户名 sudo usermod -l newusername oldusername 更…

亚马逊竞品分析之如何查找竞品

初选之后,要对产品进行竞品分析,查找竞品的方法: 1.Best Seller榜单查找 进入到该类目的BS榜单去找跟你选中的产品的竞品 看完BS榜单会找出一部分竞品 这个找相似也可以点击,是插件的一个以图搜图的功能,不过有的时候不太好使,某些同款产品可能搜不到。 Edge浏览器搭…

The First项目报告:Stargate Finance重塑跨链金融的未来

Stargate Finance是一个基于LayerZero协议的去中心化金融平台&#xff0c;自2022年3月由LayerZero Labs创建以来&#xff0c;一直致力于为不同区块链之间的资产转移提供高效、低成本的解决方案。凭借其独特的跨链技术和丰富的DeFi服务&#xff0c;Stargate Finance已成为连接不…

Vue3相关语法内容,组件传值,事件监听,具名插槽。

1、Vue3相关语法内容 赋值语句(ref、reactive系列)组件传值(父子&#xff0c;子父)watch&#xff0c;watchEffect监听slot具名插槽 1、赋值语法&#xff08;ref&#xff0c;reactive&#xff09; 1.1、ref 、isRef、 shallowRef、triggerRef、customRef 支持所有的类型&…

视觉SLAM14精讲——相机与图像3.2

视觉SLAM14精讲 三维空间刚体运动1.0三维空间刚体运动1.1三维空间刚体运动1.2李群与李代数2.1相机与图像3.1 视觉SLAM14精讲——相机与图像3.2 视觉SLAM14精讲畸变有关重投影误差缩放实际使用 畸变 相机畸变是相机镜头光学缺陷所致的缺陷&#xff0c; 在光学领域这种问题是没…