容器适配器中stack queue priority_queue的介绍及模拟实现

news2025/1/16 14:56:12

文章目录

  • 容器适配器的概念
  • deque的介绍及底层结构
  • stack的介绍
    • stack的模拟实现
  • queue的介绍
    • queue的模拟实现
  • priority_queue的介绍
    • priority_queue的模拟实现

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

deque的介绍及底层结构
要想摸清stack、queue的底层我们就要先学习deque,因为在STL中stack、queue等容器适配器的底层都是默认用deque进行的封装,从而达到我们想要的接口,下图是STL官方文档中stack、queue的接口参数图,可以看到默认的底层容器。
在这里插入图片描述

deque的底层
deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要移动元素;与list比较,空间利用率比较高。
在这里插入图片描述
deque并不是真正连续的空间,而是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,所以deque的迭代器就比较复杂,deque的底层详细结构请参考下图:
在这里插入图片描述
为什么选择deque作为stack和queue的底层默认容器?
stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

  1. stack和queue不需要遍历(因此stack和queue没有迭代器),只要在固定的一端或者两端进行操作。
  2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要挪动大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。

deque的优缺点:与vector相比,头部插入元素、删除元素deque比vector要快,扩容方面,deque不需要挪动数据,vector则需要,与list相比,deque的底层是连续的空间,list不是,所以比list的空间利用率高,缺点是deque不适合遍历,相比于vector、list,deque的遍历需要大量的检查边界,效率不高,所以deque不适合需要大量遍历数据的场景,而stack、queue等不需要遍历,所以完美的避开了deque的缺点。

stack的介绍
在这里插入图片描述

  1. stack是一种容器适配器,专门用在具有后进先出操作的环境中,其删除只能从容器的一端进行元素的插入与提取操作。
  2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。
  3. 满足stack的底层容器有vector、list、deque,默认情况下不指定容器,则使用deque。
    4.

stack的模拟实现

namespace Lh
{
	//template <class T>
	template <class T, class Container = deque<T>>
	class stack
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_back();
		}

		T& top() //栈顶数组
		{
			return _con.back();
		}
		const T& top() const   
		{
			return _con.back();
		}

		bool empty() const
		{
			return _con.empty();
		}
		size_t size() const
		{
			return _con.size();
		}

	private:
		//vector<T> _con;
		Container _con;
	};
}

queue的介绍
在这里插入图片描述

  1. 队列是一种容器适配器,专门用于在先进先出环境中操作,其中从容器一端插入元素,另一端提取元素。
  2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。
  3. 满足stack的底层容器有list、deque,默认情况下不指定容器,则使用deque。
    在这里插入图片描述

queue的模拟实现

namespace Lh
{
	//template <class T>
	template <class T, class Container = deque<T>>
	class queue
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_front();
		}

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

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

		bool empty() const
		{
			return _con.empty();
		}
		size_t size() const
		{
			return _con.size();
		}

	private:
		Container _con;
	};
}

priority_queue的介绍
在这里插入图片描述

  1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。
  2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。
  3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。
  4. 满足stack的底层容器有vector、deque,默认情况下不指定容器,则使用vector。
  5. 需要支持随机访问迭代器,以便始终在内部保持堆结构,priority_queue默认是大堆。

priority_queue的模拟实现

namespace Lh
{
	//Compare 实例化进行比较的仿函数    less -> 大堆      
	//Compare 实例化进行比较的仿函数    greater -> 小堆   
	template <class T, class Container = vector<T>, class Compare = std::less<T>>
	class priority_queue     //默认是大堆 也就是降序 
	{
	public:
		priority_queue()
		{}
		template <class InputIterator>
		priority_queue(InputIterator first, InputIterator last)  //迭代器区间构造
		{
			while (first != last)
			{
				_con.push_back(*first);
				++first;
			}

			//向下调整建堆
			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--)
			{
				adjust_down(i);
			}
		}
		void adjust_up(size_t child)   //向上调整
		{
			Compare com;               //用这个类型实例化一个对象 默认是less
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				if (com(_con[parent], _con[child]))
				{
					std::swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
		void push(const T& x)
		{
			_con.push_back(x);
			adjust_up(_con.size()-1);
		}

		void adjust_down(size_t parent)  //向下调整
		{
			Compare com;    
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				{
					child += 1;
				}
				if (com(_con[parent], _con[child]))
				{
					std::swap(_con[parent], _con[child]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}
		void pop()
		{
			assert(_con.size() > 0);

			std::swap(_con[0], _con[_con.size() - 1]);  //最后一个和堆顶的交换 然后删除最后一个
			_con.pop_back();

			adjust_down(0);
		}
		bool empty() const
		{
			return _con.empty();
		}
		const T& top() 
		{
			assert(_con.size() > 0);
			//return _con[0];
			return _con.front();
		}
		size_t size() const
		{
			return _con.size();
		}

	private:
		Container _con;
	};

	//仿函数/函数对象   是一个类  重载了operator()
	template <class T>
	class less
	{
	public:
		bool operator()(const T& l, const T& r) const
		{
			return l < r;
		}
	};

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

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

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

相关文章

清华大佬超全超详细讲解——C++STL看这份教程就够了

2022 年年度编程语言揭榜啦&#xff01;在上个月预想的 C、C、Python 三种候选语言中&#xff0c;C 脱颖而出&#xff0c;成为 TIOBE 2022 年度编程语言的最终获得者&#xff01;新的一波学习热潮要来了。TIOBE 编程语言社区排行榜是编程语言流行趋势的一个指标&#xff0c;每月…

数据分析思维(三)|测试/对比思维

测试/对比思维 1、概念 测试/对比思维可以说在数据分析的工作中随处可见。当我们通过各种手段得到一些结果数据后&#xff0c;如何评价结果的好坏呢&#xff1f;这个时候你可能会想到和标准结果进行比较、和之前的数据进行对照等等方法&#xff0c;这些方法归根结底就是一种测…

ubuntu 安装 Gitkraken 8.1.1 Pro 版本

GitKraken 是一个非常好用的 Git 图形界面客户端, 自 6.5.1 版本以后, GitKraken 对私有仓库不再免费开放使用 本文介绍一个 ubuntu 安装 GitKraken 8.1.1 Pro 版本的方法 环境准备 安装 yarn 测试过 node 18.12.1 版本, 没能升级到 Pro 版, 可能是因为 GitCracken 仓库太久…

springboot+sa-token-quick-login实现快速登录

当你的项目需要一个登录认证功能&#xff0c;这个登录界面可以不华丽、可以烂&#xff0c;但是一定要有&#xff0c;同时你又不想花费太多的时间浪费在登录页面上&#xff0c; 那么你便可以尝试一下Sa-Token-Quick-Login。 1、Sa-Token-Quick-Login Sa-Token-Quick-Login 可以…

5.4、TCP 流量控制(滑动窗口机制)

一般来说&#xff0c;我们总是希望数据传输得更快一些。 但如果发送方把数据发送得过快&#xff0c;接收方就可能来不及接收&#xff0c;这就会造成数据的丢失。 所谓流量控制(flow control)就是让发送方的发送速率不要太快&#xff0c;要让接收方来得及接收\color{red}让发送…

基于微信小程序的个人健康数据管理系统小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏览器…

第一章.机器学习的前期准备—jupyter 更换文件路径的方法,jupyter使用方法,训练/验证/测试数据集的概念,学习方式,常见应用

第一章.机器学习的前期准备 1.1 第一章.机器学习的前期准备 1.jupyter软件的安装 说明:可以使用Anaconda软件中的jupyter软件 1).jupyter 更换文件路径的方法&#xff1a; ①.查找电脑中是否存在 jupyter_notebook_config.py 文件&#xff0c;若不存在&#xff0c;通过命令提…

前端最基础面试题:说说JavaScript中如何判断数据类型?

1. 基本数据类型的判定&#xff1a;typeof [变量名] typeof 1 // number typeof string呀 // string typeof true // boolean typeof Symbol(abc) // symbol控制台验证&#xff1a; 2. 引用类型 object 的判断&#xff1a; ① constructor ② instanceof ③ Object.prototy…

Redux与前端表格施展“组合拳”,实现大屏展示应用的交互增强

Redux 是 JavaScript 状态容器&#xff0c;提供可预测化的状态管理。它可以用在 react、angular、vue 等项目中, 但与 react 配合使用更加方便一些。 Redux 原理图如下&#xff0c;可以看到store仓库是Redux的核心&#xff0c;通过维护一个store仓库管理 state。state 是只读的…

JS严格模式(use strict)

javascript语法不够严谨&#xff0c;例如我们在项目中不用关键字去定义了一个变量a&#xff0c;控制台一切正常。b123;console.log(b)但是&#xff0c;如果开启了严格模式呢&#xff1f;"use strict" b123; console.log(b)此时将会报错Uncaught ReferenceError: b is…

开关电源中功率电感均方根电流是如何推导的?来自《开关电源宝典》

3.2.8 功率电感的有效电流参考“1.7.3 功率电感”章节内容&#xff0c;我们知道&#xff0c;功率电感具有温升电流、RMS电流、饱和电流、额定电流等电流参数。在后续“第5章 降压电路的应用方法”应用实例中进行功率电感选型时&#xff0c;需要保证所选电感的额定电流参数大于实…

自定义类型:结构体,枚举,联合(1)

tips 1. 2. 结构基础知识复习 1. 结构是一些值的集合&#xff0c;这些值被称为成员变量&#xff0c;结构的每个成员可以是不同类型的变量。 2. 结构体类型&#xff0c;结构体成员&#xff0c;结构体变量&#xff0c;结构体指针的创建方式 3. 初始化结构体变量的时候&…

华为开源自研AI框架昇思MindSpore应用实践:FGSM网络对抗攻击

目录一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例二、对抗样本定义三、攻击方法快速梯度符号攻击&#xff08;FGSM&#xff09;四、数据处理五、训练LeNet网络六、实现FGSM七、运行攻击近年来随着数据、计算能力、理论的不断发展演进&#xff0c;深度学习在图…

老板要求总部-分部异地组网,作为IT运维怎样才能避免踩坑?

最近在开年会&#xff0c;老板提出2023年要全面搭建30个分公司的广域网架构&#xff0c;总部和分公司网络实现统一管理。但是公司原有网络架构复杂&#xff0c;各分支又是不同运营商接入的现状&#xff0c;想要实现异地组网并不容易&#xff01;然而&#xff0c;老板还不断提出…

好用的基于vue的组织架构图组件

都是基于vue的组织架构图&#xff0c;有支持vue2.x和vue3.x,可自行选择使用 一、vue-okr-tree&#xff08;支持vue2&#xff09; 文档地址&#xff1a;vue2-okr-tree 这个文档里面只有使用方法&#xff0c;不像vue3-tree-org里面有详细的介绍和安装引入教程 1.安装与引入 n…

第一章 spring框架概述

1.Spring框架概述*Spring是轻量级的开源的JavaEE框架*可以解决企业应用开发的复杂性*有两个核心的部分&#xff1a;IOC、AOPIOC&#xff1a;控制反转&#xff0c;把创建对象的过程交给Spring进行管理AOP&#xff1a;面向切面&#xff0c;不修改源代码的情况下进行功能的增加*Sp…

ThreadLocal与nheritableThreadLocal的区别及使用

ThreadLocal 多线程环境中&#xff0c;共享变量的并发修改常常导致线程同步问题&#xff0c;ThreadLocal可以存储线程私有的本地变量&#xff0c;从而使线程之间的变量相互隔离 因为ThreadLocal在线程执行的上下文可以传递变量的特性&#xff0c;所以可以很好的解决变量值传递…

PostgreSQL11 | pgsql建表、改表与删表

上一篇文章 PostgreSQL11 | pgadmin4基本使用http://t.csdn.cn/PKpde已经讲解了最简单的pgadmin的数据库创建、外键等可视化的操作&#xff0c;以及对应的pgsql语句 这一篇文章将讲解基础的pgsql语句 建表、改表与删表 目录 建表、改表与删表 创建数据表 单字段主键 多…

12.0、VMware-Linux部署springboot项目(图文超详细教程)

12.0、VMware-Linux部署springboot项目&#xff08;图文超详细教程&#xff09; 第一步&#xff1a;启动 Linux 进入 root 用户&#xff0c;打开终端 输入以下命令 -> 查看 Linux 中是否已经装有 jdk &#xff1b; java -version 1.如果有&#xff0c;需要先将原来的 jdk …

ESP-IDF:使用multimap和vector容器给新员工随机分配部门并按照部门打印

例程&#xff1a; /* 创建5个员工&#xff0c;给5个员工随机分配部门&#xff0c;然后按照部门打印员工*/ #include #include #include #include <time.h> #define SALEDEPARTMENT 1 #define RDDEPARTMENT 2 #define MEDEPARTMENT 3 class worker { public: string …