C++模拟实现栈(stack)和队列 (queue)

news2024/10/4 17:20:54

目录

一、栈(stack) 的介绍

二、队列(queue) 的介绍

三、容器适配器

二、deque的简单介绍

三、模拟实现stack

3.1 stack.h

3.2 test.cpp

四、模拟实现queue

4.1 queue.h

4.2 test.cpp


一、栈(stack) 的介绍

1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出
3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:
empty:判空操作
back:获取尾部元素操作
push_back:尾部插入元素操作
pop_back:尾部删除元素操作

4. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque


二、队列(queue) 的介绍

1. 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。
2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列
3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:
empty:检测队列是否为空
size:返回队列中有效元素的个数
front:返回队头元素的引用
back:返回队尾元素的引用
push_back:在队列尾部入队列
pop_front:在队列头部出队列

4. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque

三、容器适配器

想要清楚明白容器适配器,我们先引入介绍生活中的电源适配器!

我们知道,无论是电脑、手机还是其它电器,充电时都无法直接使用 220V 的交流电,为了方便用户使用,各个电器厂商都会提供一个适用于自己产品的电源线,它可以将 220V 的交流电转换成适合电器使用的低压直流电

同理,容器适配器的作用将不适用的序列式容器(包括 vector、deque 和 list)变得适用!通过封装某个序列式容器,并重新组合该容器中包含的成员函数,使其满足某些特定场景的需要!

举个简单例子:假设有一个模板A,它的构成如下所示:

class A
{
public:
	void fun1()
	{}
	void fun2()
	{}
	void fun3()
	{}
};

还有一个模板B,它的函数功能只需要将模板A的func1和func2函数组合一下即可完成相应功能,如下所示,我们可以这样写:

class B
{
public:
	void b_func1()
	{
		a->fun1();
	}
	void b_func2()
	{
		a->fun2();
		a->fun3();
	}
	//...
private:
	A* a;
};

这样我们就将不直接适用的模板A适配给模板B来实现它想要完成的功能!

我们常用的容器适配器由vector,list,deque! 下面再介绍一下deque容器


二、deque的简单介绍

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

💡💡但需要强调的是:deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组!

deque相比于stack,它支持O(1)头插,下面我们来简单解释一下他的结构,来解释为何头插为O(1)

它的基本结构:

  

尾插相当于在buf1数组插入数据,如果我们的buf1数据满了,那么将会再开辟同样大小的数组buf2,然后让中控器数组下一个下标内容指向buf2!

头插相当于在buf1前面插入数据,那么我们就再开辟一个数组buf0,让中控器数组前一个下标指向buf0,但需要注意的是数据插入是先从数组尾部往前插入

如果你想deque随机位置访问数据,那么会比较麻烦了,因为首先这样插入数据首先你得先定位具体buf数组,然后在具体buf数组访问数据。所以如果我们想在随机位置插入数据,我们首先在寻找上很麻烦!其次,随机位置插入数据后我们仍需要挪动数据!所以不建议使用deque随机位置插入数据!

综上所述,我们可以发现,deque很适合头部尾部数据增删查改!可以很好解决vector和queue的部分不足之处,所以是推荐stack和queue使用的容器。


三、模拟实现stack

3.1 stack.h

#pragma once
#include<deque>
#include<list>
#include<vector>
#include<iostream>
using namespace std;
namespace wyz
{
	template<class T,class Contain=deque<T> >
		class stack
		{
		public:
			stack()
			{}
			void push(const T& val)
			{
				con.push_back(val);
			}
			void pop()
			{
				con.pop_back();
			}
			const T& top()const
			{
				return con.back();
			}
            T& top()
			{
				return con.back();
			}
			size_t size()const
			{
				return con.size();
			}
			bool empty()
			{
				return con.empty();
			}
		private:
			Contain con;
		};
}

 💡💡这里强调的是容器类型的获取

我们可以设置模板参数来获取我们想要的适配的类型,前面提到三种适配器接口函数(函数名要是共有的!!)都可以完成stack的任务,但更提倡使用deque,所以我们模板参数缺省值是deque<T>(模板参数也可以给缺省值

这样使用容器,我们就可以调用容器接口函数来完成我们相应的功能!

3.2 test.cpp

#include"stack.h"

int main()
{
	wyz::stack<int,deque<int>> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.pop();
	st.push(4);
	st.push(5);
	while (!st.empty())
	{
		cout << st.top() << ' ';
		st.pop();
	}
	cout << endl;
    return 0;
}


四、模拟实现queue

4.1 queue.h

#include<iostream>
#include<deque>
#include<list>
#include<vector>
using namespace std;
namespace wyz
{
	template<class T,class Contain=deque<T> >
	class queue
	{
	public:
		queue()
		{}
        
        //队尾入
		void push(const T& val)
		{
			con.push_back(val);
		}
        //队头出
		void pop()
		{
			con.pop_front();
		}

        //取队尾
		const T& back()const
		{
			return con.back();
		}
		T& back()
		{
			return con.back();
		}

        //取队头
		T& front()
		{
			return con.front();
		}
		const T& front()const
		{
			return con.front();
		}
		size_t size()
		{
			return con.size();
		}
		bool empty()
		{
			return con.empty();
		}
	private:
		Contain con;//定义容器适配器!
	};
}

4.2 test.cpp

#include"Queue.h"
int main()
{
	wyz::queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.pop();
	q.push(4);
	q.push(5);
    cout << q.size() << endl;
	while (!q.empty())
	{
		cout << q.front()<<' ';
		q.pop();
	}
	return 0;
}

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

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

相关文章

字符串、内存函数的介绍(13)

目录 1、字符串函数 1、strlen 模拟实现&#xff1a; 2、strcpy 模拟实现&#xff1a; 3、strcat 模拟实现&#xff1a; 4、strcmp 模拟实现&#xff1a; 5、strncpy 6、strncat 7、strncmp 8、strstr 模拟实现&#xff1a; 9、strtok 10、strerror 11、其他字…

回顾2022年5月IB全球统考成绩,这些学校IB成绩非常亮眼

IB大考成绩放榜&#xff0c;全球17&#xff0c;3878名学生在2022年5月的考试中获得文凭课程(DP)和职业课程(CP)的成绩。今年全球640位考生获得满分45分&#xff0c;全球平均分31.98分。以下是部分公布公布成绩的学校&#xff1a; 成都树德中学国际部&#xff1a;在2022年的全球…

电商维权控价方法论

电商经济繁荣发展&#xff0c;品牌销售渠道多样化&#xff0c;带来流量的同时&#xff0c;各种渠道问题也暴露出来&#xff0c;如&#xff0c;低价、侵权……渠道秩序面临着严峻挑战&#xff0c;品牌生命周期也受到了威胁。所以&#xff0c;越来越多的品牌选择维权控价&#xf…

2022年终总结与2023新年展望

前言 时间过得太快了&#xff0c;虽然写博客已经很多年了&#xff0c;但是年终总结一直由于种种原因没有写过&#xff0c;2022年确实是魔幻的一年&#xff0c;不知不觉自己也已经研二了&#xff0c;因为疫情的原因突然放开&#xff0c;提前放假回家&#xff0c;借此机会写一下…

Git(七) - IDEA 集成 GIT

一、配置 Git 忽略文件 &#xff08;1&#xff09;问题1:为什么要忽略他们&#xff1f; 答&#xff1a;与项目的实际功能无关&#xff0c;不参与服务器上部署运行。把它们忽略掉能够屏蔽IDE工具之 间的差异。 &#xff08;2&#xff09;问题2&#xff1a;怎么忽略&#xff1f; …

TP可能用到的函数

说明 该文章来源于同事lu2ker转载至此处&#xff0c;更多文章可参考&#xff1a;https://github.com/lu2ker/ 文章目录说明in_array()filter_var()class_exists()strpos()escapeshellarg()escapeshellcmd()preg_replace()parse_str()无字母数字下划线的webshellstr_replace()e…

GNN algorithm(4): HAN, Heterogeneous Graph Attention Network

目录 background (1) heterogeneity of graph (2) semantic-level attention (3) Node-level attention (4) HAN contributions 2. Related Work 2.1 GNN 2.2 Network Embedding 3. Preliminary background 4. Proposed Model 4.1 Node-level attention ideas: …

Unity脚本(四)

视频教程&#xff1a;https://www.bilibili.com/video/BV12s411g7gU?p149 目录 键盘输入 InputManager 键盘输入 当通过名称指定的按键被用户按住时返回true&#xff1a; bool resultInput.GetKey(KeyCode.A); 当用户按下指定名称按键时的那一帧返回true&#xff1a;…

Python学习笔记——变量和简单数据类型

编码默认情况下&#xff0c;Python 3 源码文件以 UTF-8 编码&#xff0c;所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码。标识符第一个字符必须是字母表中字母或下划线 _ 。标识符的其他的部分由字母、数字和下划线组成。标识符对大小写敏感。在 Pyth…

【深度学习】机器学习\深度学习常见相关公开数据集汇总(图像处理相关数据集、自然语言处理相关数据集、语音处理相关数据集)

一、前言 1. 介绍 常来说&#xff0c;深度学习的关键在于实践。从图像处理到语音识别&#xff0c;每一个细分领域都有着独特的细微差别和解决方法。 然而&#xff0c;你可以从哪里获得这些数据呢&#xff1f;现在大家所看到的大部分研究论文都用的是专有数据集&#xff0c;这…

超声波测距传感器认知

目录 一、超声波测距传感器认知 二、从零编程实现超声波测距 三、项目——感应开关盖垃圾桶 1、开发步骤 2、感应开关盖垃圾桶代码测试 一、超声波测距传感器认知 超声波测距模块是用来测量距离的一种产品&#xff0c;通过发送和接收超声波&#xff0c;利用时间差和声音…

【网络】udp_socket编程

目录 1.认识端口号 1.1 理解端口号和进程ID 1.2 理解源端口号和目的端口号 2.认识TCP协议 3.认识UDP协议 4.网络字节序 5.socket编程接口 5.1socket常见API 5.2sockaddr结构 sockaddr结构 sockaddr_in 结构 in_addr结构 6.简单的UDP网络程序 6.1创建套接字 6.2 …

【Docker】三 镜像容器常用命令

这里写目录标题1 配置镜像加速器2 Docker镜像常用命令2.1 搜索镜像2.2 下载镜像[重要]2.3 列出镜像[重要]2.3 删除本地镜像[重要]2.4 保存镜像2.5 加载镜像2.6 构建镜像[重要]3 容器常用命令3.1 新建并启动容器[重要]3.2 列出容器[重要]3.3 停止容器[重要]3.4 强制停止容器[重要…

你可以不用Git,但不能不会Git(三)基础(下)

目录 一.将文件添加至忽略列 二.日志记录操作 三.比较文件差异 四.还原文件 一.将文件添加至忽略列 一般我们总会有些文件无需纳入Git的管理&#xff0c;也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件&#xff0c;比如日志文件&#xff0c;或者编译过程中…

重学 Java 设计模式-结构型模式-适配器模式

重学 Java 设计模式-结构型模式-适配器模式 内容摘自&#xff1a;添加链接描述 适配器模式介绍 图片来自&#xff1a;https://refactoringguru.cn/design-patterns/adapter(opens new window) 适配器模式的主要作用就是把原本不兼容的接口&#xff0c;通过适配修改做到统一。…

canva绘制(二次、三次)贝塞尔曲线并且图片在曲线上运动

下图为实现效果&#xff08;图片在三次贝塞尔曲线中运动&#xff09; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"…

Spring之注解开发

目录 一&#xff1a;Bean基本注解开发 二&#xff1a;Bean依赖注入注解开发 三&#xff1a;非自定义Bean注解开发 四&#xff1a;Bean配置类的注解开发 五&#xff1a;Spring配置其他注解 六&#xff1a;Spring注解的解析原理 一&#xff1a;Bean基本注解开发 Spring除了…

【区块链】区块链技术学习总结

文章目录一、区块链技术简介1.1 区块链概念1.2 区块链应用1.2.1 区块链1.0技术&#xff1a;比特币1.2.2 区块链2.0技术&#xff1a;以太坊1.2.3 区块链3.0技术&#xff1a;价值互联网二、区块链1.0技术比特币2.1 比特币2.1.1 比特币概念2.1.2 比特币性质2.1.3 比特币解决的问题…

Springboot扩展点之BeanDefinitionRegistryPostProcessor

前言通过这篇文章来大家分享一下&#xff0c;另外一个Springboot的扩展点BeanDefinitionRegistryPostProcessor&#xff0c;一般称这类扩展点为容器级后置处理器&#xff0c;另外一类是Bean级的后置处理器&#xff1b;容器级的后置处理器会在Spring容器初始化后、刷新前这个时间…

第二章 chrony服务器

文章目录第二章 chrony服务器1.1安装与配置1.2同步网络时间服务器1.3 配置时间服务器1.4 chronyc 命令1.5常见时区课后练习第一题&#xff1a;第一台机器从阿里云同步时间&#xff0c;第二台机器从第一台机器同步时间第二题&#xff1a;第一台服务器使用系统时间作为第二台服务…