STL中的栈(stack)和队列(queue)以及简单(复用)实现

news2025/3/1 16:02:47

适配器:

虽然 stack queue 中也可以存放元素,但在 STL 中并没有将其划分在容器的行列,而是将其称为 容器适配器 ,这是因为 stack 和队列只是对其他容器的接口进行了包装, STL stack queue 默认使用deque

换种生活上的理解:

我国家用电的电压标准一般是220V,现在大家既然看到这篇博客了,那应该自己也是有一条充电器了。充电器,顾名思义,就是用来给电池充电的设备,它通常包括一个电源适配器和一根充电线。而电源适配器,则是充电器的一个重要组成部分,它的主要功能是将交流电(AC)转换成直流电(DC),并调整电压和电流以满足不同设备的充电需求。 这里电源适配器就是一种适配器,防止了220V的电压与我们接触,保证了我们的人身安全

STL stack queue 默认使用deque作为适配器(Container):
可以简单理解为:站和队列就是一个包装(一个比较特别的包装)
stack:

queue:
priority_queue:

stack与queue:(简单回忆)

栈:一种后进先出的数据结构:(表层的印象理解:)

队列:一种先进先出的数据结构:(表层的印象理解:)

deque的简单介绍:

原理介绍:

deque( 双端队列 ) :是一种双开口的 " 连续 " 空间的数据结构 ,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1) ,与 vector 比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

deque其实就是vector和list的缝合怪

vector与list的优缺点
vectorlist
优点:优点:
尾插尾删效率不错,支持高效的下标随机访问按需申请释放空间,不需要扩容
物理空间连续,所以高速缓存利用率高任意位置插入删除
缺点:缺点:
空间需要扩容,扩容有一些代价(效率和空间的浪费)不支持下标随机访问
头部和中间位置插入和删除效率低

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


看STL_deque原码理解更佳:

总结:

  • deque头插尾插效率很高,更甚于vector和list
  • deque下标随机访问也还不错,但是相比于vector,vector更胜一筹 
  • deque的中间插入删除效率很低
    这也是为什么STL中stack和queue的适配器是给deque作为缺省值,因为stack和queue的主要实现功能还是出现在头部与尾部,deque在头尾的操作有着比vector和list更加高效的能力,因此,deque作为stack和queue的Cantainer是更适合不过的了,但是在其他情况就该考虑是否vector/list会不会更好呢?

STL中stack的实现:

丰富请参考(点击进入)

功能介绍:

函数声明

接口说明

stack()
构造空的栈
empty()
检测 stack 是否为空
size()
返回 stack 中元素的个数
top()
返回栈顶元素的引用
push()
将元素 val 压入 stack
pop()
stack 中尾部的元素弹出

底层实现:

#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
using namespace std;

//template<class T>
//class stack
//{
//private:
//	T* _a;
//	size_t _top;
//	size_t _capacity;
//};

namespace home
{
	template<class T,class Container = deque<T>>
	class stack
	{
	public:
		//Container是一个自定义类型,会自动调用其构造函数,我们无需在此实现
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_back();
		}
		const T& top() const
		{
			return _con.back();
		}
		size_t size() const
		{
			return _con.size();
		}
		bool empty() const
		{
			return _con.empty();
		}
	private:
		Container _con;//容器的适配转换出的stack
	};
}

STL中queue的实现:

丰富请参考(点击进入)

功能介绍:

函数声明

接口说明

queue()
构造空的队列
empty()
检测队列是否为空,是返回 true ,否则返回 false
size()
返回队列中有效元素的个数
front()
返回队头元素的引用
back()
返回队尾元素的引用
push()
在队尾将元素 val 入队列
pop()
将队头元素出队列

底层实现:

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

namespace home
{
	template<class T, class Container = deque<T>>
	class queue
	{
	public:
		//Container是一个自定义类型,会自动调用其构造函数,我们无需在此实现
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_front();
		}
		const T& front() const
		{
			return _con.front();
		}
		const T& back() const
		{
			return _con.back();
		}
		size_t size() const
		{
			return _con.size();
		}
		bool empty() const
		{
			return _con.empty();
		}
	private:
		Container _con;//容器的适配转换出的stack
	};
}

STL中priority_queue的实现:

丰富请参考(点击进入)

功能介绍:

1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的;
2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素 ( 优先队列中位于顶部的元素);
3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类, queue提供一组特定的成员函数来访问其元素。元素从特定容器的“ 尾部 弹出,其称为优先队列的顶部;
4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:
  • empty():检测容器是否为空
  • size():返回容器中有效元素个数
  • front():返回容器中第一个元素的引用
  • push_back():在容器尾部插入元素
  • pop_back():删除容器尾部元素
5. 标准容器类 vector deque 满足这些需求。默认情况下,如果没有为特定的 priority_queue类实例化指定容器类,则使用vector;
6. 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数make_heap push_heap pop_heap 来自动完成此操作;
优先级队列默认使用 vector 作为其底层存储数据的容器,在 vector 上又使用了堆算法将 vector 元素构造成堆的结构,因此 priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue 。注意:默认情况下 priority_queue 是大堆

函数声明

接口说明

priority_queue()/priority_queue(first, last)
构造一个空的优先级队列
empty()
检测优先级队列是否为空,是返回 true ,否则返回 false
top()
返回优先级队列中最大 ( 最小元素 ) ,即堆顶元
push(x)
在优先级队列中插入元素 x
pop()
删除优先级队列中最大 ( 最小 ) 元素,即堆顶元

在默认情况下priority_queue是大堆,我们可以利用仿函数进行对priority_queue修改成小堆:

仿函数在冒泡排序的使用(参照)(本质一样):(下面有相关的实现代码)

 

在相关文档中,就体现了仿函数:

 仿函数用于回调,又是一个类,可以使用模板参数 

底层实现:

#pragma once
#include<vector>
//仿函数,本质是一个类,这个类重载operator(),他的对象可以像仿函数一样来使用
template<class T>
class Less
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
	//仿函数大多是没有成员变量的
};

template<class T>
class Greater
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x > y;
	}

};

//仿函数用于回调,又是一个类,可以使用模板参数
//注意:常常用匿名对象

namespace home
{
	template<class T, class Container = std::vector<T>, class Compare = Less<T>>
	class priority_stack
	{
		//优先级队列其实就是默认按照大堆来top与pop
	public:
		void AdjustUp(int child)//向上调整
		{
			Compare com;
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[parent] < _con[child])
				if (com(_con[parent], _con[child]))
				{
					swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
		void AdjustDown(int parent)//向下调整
		{
			//假设法:先设左孩子小
			size_t child = parent * 2 + 1;
			Compare com;
			while (child < _con.size())//child>=n说明孩子不存在,调整到叶子了
			{
				//孩子的正真调整
				if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				{
					++child;
				}
				//if (_con[parent] < _con[child])
				if (com(_con[parent], _con[child]))
				{
					swap(_con[parent], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}
		void push(const T& x)
		{
			_con.push_back(x);
			AdjustUp(_con.size() - 1);
		}
		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(0);
		}

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

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

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

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

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

相关文章

【云备份】学习Json

文章目录 1.Json数据类型基础数据类型复合数据类型JSON数据类型的应用 2.学习jsoncpp库利用json实现序列化利用json实现反序列化 1.Json数据类型 json 是一种数据交换格式&#xff0c;采用完全独立于编程语言的文本格式来存储和表示数据。json数据交换格式是将多种数据对象组织…

CVE-2024-38077 Windows远程桌面授权服务漏洞介绍

CVE-2024-38077 是一个在Windows远程桌面授权服务&#xff08;Remote Desktop Licensing Service&#xff09;中存在的严重远程代码执行漏洞。以下是关于此漏洞的详细信息&#xff1a; 漏洞概述 漏洞编号&#xff1a;CVE-2024-38077漏洞类型&#xff1a;远程代码执行 (RCE)影…

基于单片机控制的多功能智能语音风扇

【摘要】 本文简述了一种基于单片机控制的智能多功能语音风扇的设计&#xff0c;该设计以STC11L08XE单片机为主控制器&#xff0c;通过YS-LDV7语音模块对语音信号进行采集识别&#xff0c;并将该信号上传给单片机进而控制风扇的转速和开关&#xff0c;以达到语音控制的效果。该…

Python 安装 PyTorch详细教程

本章教程,介绍如何安装PyTorch,介绍两种安装方式,一种是通过pip直接安装,一种是通过conda方式安装。 一、查看CUDA版本 二、安装PyTorch 1、pip安装方式 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu1162、conda安装方式 …

Leetcode—3151. 特殊数组 I【简单】

2024每日刷题&#xff08;155&#xff09; Leetcode—3151. 特殊数组 I 实现代码 class Solution { public:bool isArraySpecial(vector<int>& nums) {int n nums.size();for(int i 1; i < n; i) {if(nums[i - 1] % 2 nums[i] % 2) {return false;}}return t…

【数据结构-前缀哈希】力扣1124. 表现良好的最长时间段

给你一份工作时间表 hours&#xff0c;上面记录着某一位员工每天的工作小时数。 我们认为当员工一天中的工作小时数大于 8 小时的时候&#xff0c;那么这一天就是「劳累的一天」。 所谓「表现良好的时间段」&#xff0c;意味在这段时间内&#xff0c;「劳累的天数」是严格 大…

练习实践-基础设施-文件共享-linux间的文件共享-NFS服务搭建

参考来源&#xff1a; nfs安装配置-Debian/Ubuntu 什么是NFS&#xff1f;NFS挂载 NFS详解&#xff08;概念实验演示&#xff09; 快速回顾&#xff1a; nfs服务器搭建&#xff1a;1>.服务器端&#xff1a;1&#xff09;创建共享目录2&#xff09;修改配置文件/etc/exports…

深入解析三路快排:一种高效的排序算法

在数据结构和算法的世界中&#xff0c;快排&#xff08;Quick Sort&#xff09;无疑是最受欢迎的排序算法之一。今天&#xff0c;探讨一种优化的快排变体——三路快排&#xff08;3-Way Quick Sort&#xff09;&#xff0c;它在处理具有重复元素的数组时展现出了令人惊叹的效率…

PCIe学习笔记(22)

Transaction Ordering Transaction Ordering Rules 表2-40定义了PCI Express Transactions的排序要求。该表中定义的规则统一适用于PCI Express上所有类型的事务&#xff0c;包括内存、I/O、配置和消息。该表中定义的排序规则适用于单个流量类(TC)。不同TC标签的事务之间没有…

Label-Wise Graph Convolutional Network for Heterophilic Graphs

推荐指数: #paper/⭐⭐ 发表于:LoG 2022 推荐指数是因为22年,所以给2行. 贡献:用MLP来区分不同的标签信息. 思想阐述: 假设 N k ( v ) \mathcal{N}_{k}(v) Nk​(v)表示节点v标签为k的邻居.我们定义基于 a v , k a_{v,k} av,k​为聚合标签为k的邻居:(即只聚合标签为k的邻居) a…

拒绝内卷:利用4P营销理论打造汇报PPT

在当下的职场文化里&#xff0c;越来越激烈的“内卷”现象普遍存在。随着不得已的竞争压力、加班文化、以及技能和学历的通货膨胀&#xff0c;越来越多职场人不惜加大工作负荷和劳动投入。但这种过度的付出往往并未带来成比例的回报&#xff0c;有时还会因为过度工作而导致生产…

Oracle Java JDK 21 下载地址及安装教程

Oracle JDK 21 官方地址 https://www.oracle.com/java/technologies/downloads/#java21 1. Linux 版本 ARM64 Compressed Archive https://download.oracle.com/java/21/latest/jdk-21_linux-aarch64_bin.tar.gz ARM64 RPM Package https://download.oracle.com/java/21/late…

OpenHarmony网络协议通信—nanopb

简介 nanopb是一种小代码量的协议缓冲区实现&#xff0c;适用于任何内存受限的系统。 下载安装 直接在OpenHarmony-SIG仓中搜索nanopb并下载。 使用说明 以OpenHarmony 3.1 Beta的rk3568版本为例 将下载的Nanopb库代码存在以下路径&#xff1a;./third_party/nanopb 修改添…

谷歌反垄断官司败诉后,或又面临被拆分风险?

KlipC报道&#xff1a;上周8月5日&#xff0c;美国法院裁定谷歌的搜索业务违反了美国反垄断法&#xff0c;非法垄断在线搜索和搜索文本广告市场。据悉&#xff0c;胜诉的美国司法部正在考虑拆分谷歌。其他选项包括强制谷歌与竞争对手分享更多数据&#xff0c;以及防止其在人工智…

C# Log4net日志 配置 与AppenderSkeleton

https://www.cnblogs.com/yaopengfei/p/9428206.html 一、Log4Net简介 Log4net是从Java中的Log4j迁移过来的一个.Net版的开源日志框架&#xff0c;它的功能很强大&#xff0c;可以将日志分为不同的等级&#xff0c;以不同的格式输出到不同的存储介质中&#xff0c;比如&#x…

Vue框架学习笔记-6

Vue中的路由 Vue中的路由&#xff08;Routing&#xff09;是通过Vue Router这个官方提供的路由管理器来实现的。Vue Router允许你通过不同的URL访问应用中不同的页面&#xff08;组件&#xff09;&#xff0c;而无需重新加载页面。这对于构建单页应用&#xff08;SPA, Single …

数字引领风尚·智能改变生活“青岛电博会”路演活动(济南站)

2024CICE中国国际消费电子博览会路演活动&#xff08;济南站&#xff09;成功举行 数字引领风尚&#xff0c;智能改变生活。 8月7日&#xff0c;50余家行业协会、企业嘉宾、展商代表等云集2024中国国际消费电子博览会路演活动&#xff08;济南站&#xff09;现场&#xff0c;共…

【香菇带你学Mysql】Linux下Mysql8使用二进制安装包安装教程【建议收藏】

⚠️ 本人声明&#xff1a;本教程可100%复现​ 网上看了很多Mysql8安装的方式&#xff0c;基本上都是都过一个yum方式直接访问公网下载依赖资源安装的。 但是在企业内部一般并不允许生产环境直接连接公网。针对此情况。本文将介绍如何在内网环境下使用二进制安装包本地安装方式…

【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁

文章目录 乐观锁和悲观锁重量级锁和轻量级锁挂起等待锁和自旋锁公平锁和非公平锁可重入锁和不可重入锁读写锁相关面试题 锁&#xff1a;非常广义的概念&#xff0c;不是指某个具体的锁&#xff0c;所有的锁都可以往这些策略中套 synchronized&#xff1a;只是市面上五花八门的锁…

新形势下职业教育云计算人才培养策略

一、引言 在数字化转型的浪潮中&#xff0c;云计算作为核心技术之一&#xff0c;正在深刻影响着各行各业的发展。职业教育作为培养技术技能型人才的重要途径&#xff0c;需要紧跟时代步伐&#xff0c;不断优化和创新云计算人才培养模式&#xff0c;以满足社会对云计算人才的迫…