【C++】stack | queue | priority_queue的模拟实现

news2024/11/15 21:28:41

stack&queue的模拟实现

stack 与 queue 作为容器适配器,都默认选择了 deque 作为其底层容器。

#pragma once
#include <deque>
using namespace std;

namespace zs
{
	template<class T, class Container = deque<T>>
	class stack
	{
	public:
		void push(const T& val)
		{
			_cont.push_back(val);
		}

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

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

		const T& top() const
		{
			return _cont.back();
		}

		bool empty() const 
		{
			return _cont.empty();
		}

		size_t size() const
		{
			return _cont.size();
		}
	private:
		Container _cont;
	};

	template<class T, class Container = deque<T>>
	class queue
	{
	public:
		void push(const T& val)
		{
			_cont.push_back(val);
		}

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

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

		const T& front() const
		{
			return _cont.front();
		}

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

		const T& back() const
		{
			return _cont.back();
		}

		bool empty() const
		{
			return _cont.empty();
		}

		size_t size() const
		{
			return _cont.size();
		}
	private:
		Container _cont;
	};
}

deque 的介绍

deque(双端队列) 是一种双开口的“连续”空间的数据结构。
双开口是指,可以在头尾两端进行插入删除,且时间复杂度都是O(1)。
但deque并不是真的连续的物理空间,而是由一段又一段连续的小空间拼接而成的。
在这里插入图片描述
为什么会选择 deque 作为 stack 和 queue 的默认底层容器呢?
与 vector 相比,deque 头部插入删除效率高,扩容也不需要搬移大量的元素。
与 list 相比,空间利用率更高,不需要存储额外字段。
deque 也有很多缺陷:
deque 的底层结构决定了它的迭代器设计会很复杂。
遍历以及对数据的随机访问效率会比较低。
完成对中间数据的插入删除操作也会更复杂。
stack 和 queue 的特点能够很好地规避 dqeue 的缺陷,而充分利用到了 deque 的优点,而且这也是 deque 为数不多的应用中的一个。

priority_queue的模拟实现

priority_queue(优先级队列)其实就是一个堆结构,默认使用 vector 作为其底层容器。

#pragma once
#include <vector>
using namespace std;

namespace zs
{
	// Compare 进行比较的仿函数 默认less->大堆 greater->小堆
	template<class T, class Container = vector<T>, class Compare = less<T>>
	class priority_queue
	{
	public:
		priority_queue()
		{}

		template <class InputIterator>
		priority_queue(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				_cont.push_back(*first);
				++first;
			}

			// 向下建堆
			for (int i = (_cont.size() - 1 - 1) / 2; i >= 0 ; --i)
			{
				adjust_down(i);
			}
		}

		void adjust_up(size_t child)
		{
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_cont[child] > _cont[parent])
				//if (_cont[parent] < _cont[child])
				if (Compare()(_cont[parent], _cont[child]))
				{
					::swap(_cont[parent], _cont[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void push(const T& val)
		{
			_cont.push_back(val);
			adjust_up(_cont.size() - 1);
		}

		void adjust_down(size_t parent)
		{
			size_t child = parent * 2 + 1;

			while (child < _cont.size())
			{
				//if (child + 1 < _cont.size() && _cont[child + 1] > _cont[child])
				//if (child + 1 < _cont.size() && _cont[child] < _cont[child + 1])
				if (child + 1 < _cont.size() && Compare()(_cont[child], _cont[child + 1]))
				{
					++child;
				}
				//if (_cont[child] > _cont[parent])
				//if (_cont[parent] < _cont[child])
				if (Compare()(_cont[parent], _cont[child]))
				{
					::swap(_cont[parent], _cont[child]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}

		void pop()
		{
			::swap(_cont.front(), _cont.back());
			_cont.pop_back();

			adjust_down(0);
		}

		const T& top() const
		{
			return _cont.front();
		}

		bool empty() const
		{
			return _cont.empty();
		}

		size_t size() const
		{
			return _cont.size();
		}

	private:
		Container _cont;
	};

	/*
	*  仿函数,也叫函数对象,主要还是一个类
	*  因为重载了operator(), 可以像函数一样使用
	*/
	template<class T>
	class less
	{
	public:
		bool operator()(const T& val1, const T& val2) const
		{
			return val1 < val2;
		}
	};

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

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

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

相关文章

【Java基础教程】(四十四)IO篇 · 上:File类、字节流与字符流,分析字节输出流、字节输入流、字符输出流和字符输入流的区别~

Java基础教程之IO操作 上 &#x1f539;本节学习目标1️⃣ 文件操作类&#xff1a;File2️⃣ 字节流与字符流2.1 字节输出流&#xff1a;OutputStream2.2 字节输入流&#xff1a;InputStream2.3 字符输出流&#xff1a;Writer2.4 字符输入流&#xff1a;Reader2.5 字节流与字符…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(15)-Fiddler弱网测试,知否知否,应是必知必会

1.简介 现在这个时代已经属于流量时代&#xff0c;用户对于App或者小程序之类的操作界面的数据和交互的要求也越来越高。对于测试人员弱网测试也是需要考验自己专业技术能力的一种技能。一个合格的测试人员&#xff0c;需要额外关注的场景就远不止断网、网络故障等情况了。还要…

grid map学习笔记2之grid map的一些常规定义和功能包说明

文章目录 0 引言1 常规定义1.1 单层grid map1.2 多层grid map1.3 迭代器类别1.4 移动grid map的位置 2 功能包2.1 grid_map_rviz_plugin2.2 grid_map_sdf2.3 grid_map_visualization2.3.1 订阅的主题2.3.2 发布的主题 2.4 grid_map_filters 0 引言 grid map学习笔记1已成功在U…

数据结构:复习笔记

目录 前言1. 数据结构绪论1.1 数据结构的概念及分类1.1.1 知识点提要1.1.2 选择判断与简答归纳1.1.3 算法编程题 1.2 算法设计与算法分析1.2.1 知识点提要1.2.2 选择判断与简答归纳1.2.3 算法编程题 2. 线性表2.1 线性表的概念2.1.1 知识点提要2.1.2 选择判断与简答归纳2.1.3 算…

【yolov8+人/车流量统计】yolov8案例的追踪case,业务化可以变成计数

文章目录 前言修改点PreprocessInference 另一种方法&#xff0c;work了。一个难点&#xff0c;它走到了这里 业务化修改总结 前言 之前写个yolov8的一个试用版&#xff0c;【深度学习】Yolov8追踪从0到1, 这要是做计数啥的,简单的一批&#xff0c;一套工程化的代码&#xff0…

abp vnext指定版本下载

在本地环境没有达到最新的开发环境时可能无法下载abp vnext的最新版本&#xff0c;我们应该指定下载符合本地开发环境的abp版本&#xff0c;下面一起看一下&#xff1a; 首先查看本地电脑的开发环境版本&#xff1a; cmd dotnet --version dotnet --list-version ABP VNext和…

师从美国四院院士|遗传学老师赴哥伦比亚大学访问交流

H老师为省公派访学&#xff0c;目标为美国知名高校&#xff0c;最终我们获得了哥伦比亚大学的邀请函&#xff0c;导师是美国科学院院士、美国艺术与科学院院士、美国微生物学院院士、美国科学促进会会士等四个学会的院士&#xff0c;堪称学术界的超级大牛。 H老师背景&#xff…

Spark性能调优指南来了!

1、什么是Spark Spark 是一种基于内存的快速、通用、可扩展的大数据分析计算引擎。 Spark Core&#xff1a;实现了Spark的基本功能&#xff0c;包含任务调度、内存管理、错误恢复、与存储系统交互等模块。Spark Core中还包含了对弹性分布式数据集(Resilient Distributed Dat…

【Ansible 的脚本 --- playbook 剧本】

目录 一、playbook 剧本介绍二、示例1、运行playbook2、定义、引用变量 三、使用playbook部署lnmp集群 一、playbook 剧本介绍 playbooks 本身由以下各部分组成 &#xff08;1&#xff09;Tasks&#xff1a;任务&#xff0c;即通过 task 调用 ansible 的模板将多个操作组织在…

从多个基础CMS中学习代码审计

代码审计 概念 什么是代码审计&#xff1f; 代码审计是在一个编程中对源代码旨在发现错误、安全漏洞或违反编程约定的项目。 说人话就是找它这些代码中可能存在问题的地方&#xff0c;然后看它是否真的存在漏洞。(博主小白&#xff0c;可能存在问题&#xff0c;请见谅) 分类…

ScrumMaster认证培训(CSM)记录篇-Leangoo领歌

前不久参加了Leangoo领歌CSM认证公开班&#xff0c;简单记录下我的学习之旅 当初选课程时也很是纠结&#xff0c;最终选择了Leangoo领歌&#xff0c;Leangoo领歌是Scrum中文网旗下的一款敏捷研发管理工具。 Leangoo领歌由Scrum中文网资深的敏捷顾问团队和敏捷研发团队经过近十…

Python scipy Moudle 中的 optimize 方法

Python scipy Moudle 中的 optimize 方法 scipy Moudle 中的 optimize 方法 minimize 最小化一个函数 它提供了多种算法&#xff0c;如 BFGS、Nelder-Mead、Powell 可选参数 fun&#xff1a;要最小化的目标函数x0&#xff1a;函数的初始猜测值。可以是一个数组或列表metho…

Python入门一

目录&#xff1a; python基本操作python基本数据类型python字符串基本操作python的运算符python控制流-判断python控制流-循环python常用数据结构-列表python常用数据结构-元组python常用数据结构-集合python常用数据结构-字典python函数python函数进阶与参数处理pythonlambda…

【7.31】C++编写7254是一个不寻常的数,可以表示为7254 = 39 x 186,这个式子中1~9每个数字正好出现一次

题目题干 7254是一个不寻常的数&#xff0c;因为它可以表示为7254 39 x 186&#xff0c;这个式子中1~9每个数字正好出现一次&#xff0c;输出所有这样的不同的式子&#xff08;乘数交换被认为是相同的式子&#xff09;。结果小的先输出&#xff1b;结果相同的&#xff0c;较小…

IPsec VPN小实验

IPSec 是什么&#xff1a; IPSec是一个框架&#xff0c;它不是具体指某个协议&#xff0c;而是定义了一个框架&#xff0c;由各种协议组和协商而成。该框架涉及到的主要有加密算法、验证算法、封装协议、封装模式、密钥有效期等等。 IPSecVPN建立的前提&#xff1a;要想在两个…

【性能测试】性能测试的概念、策略、指标

一、性能测试的概念 1.1 什么是性能 - 时间&#xff1a;系统处理用户请求的响应时间 -资源&#xff1a;系统运行过程中&#xff0c;系统资源的消耗情况 1.2 什么是性能测试 使用自动化工具&#xff0c;模拟不同的场景&#xff0c;对软件各项性能指标进行测试和评估的过程 …

适配器模式与装饰器模式对比分析:优雅解决软件设计中的复杂性

适配器模式与装饰器模式对比分析&#xff1a;优雅解决软件设计中的复杂性 在软件设计中&#xff0c;我们常常面临着需要将不同接口或类协调工作的情况&#xff0c;同时还要满足灵活性和可扩展性的需求。为了应对这些挑战&#xff0c;适配器模式和装饰器模式应运而生&#xff0c…

12-4_Qt 5.9 C++开发指南_创建和使用共享库

文章目录 1. 创建共享库2. 使用共享库2.1 共享库的调用方式2.2 隐式链接调用共享库2.3 显式链接调用共享库 1. 创建共享库 除了静态库&#xff0c;Qt 还可以创建共享库&#xff0c;也就是 Windows 平台上的动态链接库。动态链接库项目编译后生成 DLL 文件&#xff0c;DLL 文件…

【机器学习】Overfitting and Regularization

Overfitting and Regularization 1. 过拟合添加正则化2. 具有正则化的损失函数2.1 正则化线性回归的损失函数2.2 正则化逻辑回归的损失函数 3. 具有正则化的梯度下降3.1 使用正则化计算梯度&#xff08;线性回归 / 逻辑回归&#xff09;3.2 正则化线性回归的梯度函数3.3 正则化…

SpringCloud集成OpenTelemetry的实现

SpringCloud项目做链路追踪&#xff0c;比较常见的会集成SleuthZipKin来完成&#xff0c;但这次的需求要集成开源框架OpenTelemetry&#xff0c;这里整理下实现过程。相关文章&#xff1a; 【SpringCloud集成SleuthZipkin进行链路追踪】 【OpenTelemetry框架Trace部分整理】 …