栈与队列:用队列实现栈

目录

题目:

栈和队列的数据模型对比: 

思路分析:

 代码分析:

一、定义栈 

二、初始化栈 

三、入栈 

四、出栈⭐ 

代码解析:

五、获取栈顶元素 

六、 判断栈是否为空

七、销毁栈 

完整代码: 

需要手撕的队列代码:


题目:

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。


实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

  • 你只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

题源:225. 用队列实现栈 - 力扣(LeetCode) 

题目内容:

栈和队列的数据模型对比: 

思路分析:

本题的核心部分和原理是如何将队列的特点演变成栈的特点,即如何将队列的先进先出演化为栈的后进先出。

按照题目的要求,我们需要使用两个队列进行栈的实现,以此我们可以根据队列的特点,进行数据的传输交换。

 

如图所示,可以将一个队列中的数据(除去最后一个),转移到另一个空的队列中,并将最后一个数据进行删除,完成表面意义上的栈的出栈!

且当我们需要再次出栈的时候,便又可把含有数据的队列 中的数据进行转移,并保留最后一个进行删除,以此来表示出栈!

                

而入栈,只需要将数据插入在原本就有数据的队列中,如果两个队列都没有数据,则随便插入一个即可。

 代码分析:

一、定义栈 

 

因为本题是需要使用两个队列来实现栈,于是需要对队列的调用,因此栈内部的定义只需要使用两个指向不同队列的指针即可。

二、初始化栈 

使用之前定义的栈(MyStack)创造一个空间,表示栈的创建,随后在这个空间的内部调用队列的初始化函数,对栈中的两个队列进行初始化。

  • 这种方法定义的形式,令人感觉像是栈的内部其实是两个队列。 

注意:->的优先级是比&更高级的,所以&pst-> q1和 &pst-> q2的本意是 取 栈内部的q1、q2的地址,而pst只是一个指向栈(MyStack)的指针。

三、入栈 

 在思路分析中,讲诉过,那个队列是空的数据便尾插到那个队列,如果都为空那就随便插入都行

四、出栈⭐ 

代码解析:

根据之前的思路分析得知,我们需要两段逻辑,队列q1空q2不空,q2空q1不空,而这两段逻辑可以变为一句话,那便是,将不为空的元素(除了最后一个)全部按照顺序转移到另一个为空的队列中。

  • 而因为需要将元素进行转移,所以我们调用了队列中的QueueSize,这个是统计队列长度的,当队列长度=1时,相当于留下的队尾的元素,而>1时进行转移。
  • 转移需要使用插入函数,QueuePush函数,且函数中的参数是之前创立的空队列指针emptyq,另一个是 非空队列队头的元素,非空队列的队头元素使用了QueueFront进行获取
  • 获取之后使用了QueuePop在非空队列中进行删除,以此来减去非空队列的长度

while(QueueSize(nonemptye) > 1)在上图代码和下图的例图中,都表示while是把非空队列变成只剩下队尾元素的操作。

而最后一步的操作,则是在其他元素都转移后,只留下了队尾元素在非空队列中,然后使用获取队头元素的操作,将元素交给临时变量,而后进行删除非空队列的最后一个元素,并返回临时变量,以此表示出栈。

五、获取栈顶元素 

获取栈顶元素在 之前的数据模型对比中可以得知,队尾其实就相当于栈底,所以我们便可以调用队列的获取队尾元素来获取栈底元素,当然这个队列是不为空的队列!

六、 判断栈是否为空

 

  • 需要两个队列同时为空才行!因为我们进行了互换操作! 

七、销毁栈 

 

  • 要分别把两个队列进行销毁后在销毁封存两个队列指针的结构体

完整代码: 

 

需要手撕的队列代码:

//队列的单链表节点结构
typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;
//因为队列是先进先出,先进先出的核心是头删和尾插
//所以需要两个指针分别指向头和尾
//又因为头尾需要变动要传递二级指针,所以使用一个结构体封装
//之后只需要传递一级指针的结构体即可
typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;
//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
//插入——入队
void QueuePush(Queue* pq, QDataType x);
//删除——出队
void QueuePop(Queue* pq);
//获取队头元素
QDataType QueueFront(Queue* pq);
//获取队尾元素
QDataType QueueBack(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//查看队列长度
int QueueSize(Queue* pq);
//初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//销毁
void QueueDestroy(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}

	newnode->val = x;
	newnode->next = NULL;
	//判断尾节点指针是否指向为空,如果为空头节点指针和尾节点指针都是指向新节点
	if (pq->ptail == NULL)
	{
		pq->ptail = pq->phead = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	//别忘了长度需要在插入后+1,为了方便之后的统计队列长度
	pq->size++;
}

// 出队
void QueuePop(Queue* pq)
{
	assert(pq);
	// 
	assert(pq->phead);

	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;
	//头删的第二种情况
	//如果只有一个节点,那么第二个节点就是空的了
	//而现在phead就处在第二个节点
	if (pq->phead == NULL)
		pq->ptail = NULL;

	pq->size--;
}
//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	// 如果队头是空的表示队列不存在
	assert(pq->phead);

	return pq->phead->val;
}
//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	//如果队尾是空的表示队列不存在 
	assert(pq->ptail);

	return pq->ptail->val;
}
//判断队列是否存在
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->phead == NULL;
}
//获取队列长度
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

 

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

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

相关文章

在webstorm中配置sass编译环境

1.下载ruby 下载地址:ruby下载 2.安装ruby 下载之后,有一个exe安装包 双击exe文件 ,并选择自己的安装位置(这个位置一定要记得,需要在webstorm中使用)。其他的步骤默认安装即可。 3.安装sass ruby安装成功后…

记feign调用第三方接口时header是multipart/form-data

1.请求第三方接口,用feign请求 请求第三方接口,用feign请求,header不通,feign的写法不同 调用时报错Could not write request: no suitable HttpMessageConverter found for request type [com.ccreate.cnpc.mall.dto.zm.ZMPage…

程序员的护城河:技术深度、创新精神与软实力的完美结合

文章目录 1. 技术深度:建立坚实的技术基石2. 创新精神:应对变革的利器3. 软实力:沟通协作构筑团队防线4. 结合三者构筑完美护城河 🎉程序员的护城河:技术深度、创新精神与软实力的完美结合 ☆* o(≧▽≦)o *☆嗨~我是I…

【Maven】进阶

文章目录 1. 聚合2. 继承3. 属性变量定义与使用4. 版本管理5. 资源配置6. 多环境配置7. 跳过测试(了解) 1. 聚合 为了防止某个模块(dao)更新了,重新编译了,导致和其他模块不兼容,需要用一个roo…

移植freertos到qemu上运行

1、freertos源码下载 参考博客:《freertos源码下载和目录结构分析》; 2、编译freertos 2.1、选择合适的Demo freertos官方已经适配过qemu,所以我们并不需要做源码级别的移植,只需要选择合适的Demo文件夹。 2.2、修改Makefile 2.3…

sCrypt 发布零知识证明精选列表

sCrypt 发布了与零知识证明相关的精选列表,包括:教程,编程语言,工具,书籍,社区,证明系统。欢迎收藏 github 代码仓:https://github.com/sCrypt-Inc/awesome-zero-knowledge-proofs。…

spark与scala的对应版本查看

仓库地址 https://mvnrepository.com/artifact/org.apache.spark/spark-core 总结 spark3.0 以后,不再支持 scala2.11spark3.0 以后,只能用 scala2.12以上

Zabbix邮箱告警

1.在邮箱中获取授权码 2.zabbix配置 agengt配置 添加以下配置 [rootserver03 ~]# visudo zabbix ALL(ALL) NOPASSWD: ALL [rootserver03 ~]# vim /etc/zabbix/zabbix_agentd.conf EnableRemoteCommands1 #允许接收远程命令 修改原有的值,不要在末…

Windows系统CMake+VS编译protobuf

目录 一些名词CMake构建VS工程下载protobuf源码下载CMake编译QT中使用 方案二失败:CMakeQT自带的Mingw编译参考链接 一些名词 lib dll lib库实际上分为两种,一种是静态链接lib库或者叫做静态lib库,另一种叫做动态链接库dll库的lib导入库或称…

.Net8 Blazor 尝鲜

全栈 Web UI 随着 .NET 8 的发布,Blazor 已成为全堆栈 Web UI 框架,可用于开发在组件或页面级别呈现内容的应用,其中包含: 用于生成静态 HTML 的静态服务器呈现。使用 Blazor Server 托管模型的交互式服务器呈现。使用 Blazor W…

LINMP搭建wordpress-数据库不分离

目录 一、nginx部署 1.安装nginx前的系统依赖环境检查 2.下载nginx源代码包 3.解压缩源码包 4.创建普通的nginx用户 5.开始编译安装nginx服务 6.创建一个软连接以供集中管理 7.配置nginx环境变量 二、mysql 1.创建普通mysql用户 2.下载mysql二进制代码包 3.创建mys…

吴恩达《机器学习》8-5->8-6:特征与直观理解I、样本与值观理解II

8.5、特征与直观理解I 一、神经网络的学习特性 神经网络通过学习可以得出自身的一系列特征。相对于普通的逻辑回归,在使用原始特征 x1​,x2​,...,xn​ 时受到一定的限制。虽然可以使用一些二项式项来组合这些特征,但仍然受到原始特征的限制。在神经网…

【MySQL】MVCC(多版本并发控制)详解

MVCC MVCC概述 MVCC,全称 Multi-Version Concurrency Control ,即多版本并发控制。MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。 MVCC就是在ReadCommitte…

echarts实现不展示X轴Y轴轴线、刻度

今日工作中需要实现折线图的简图,就是只看个大概趋势不展示具体坐标,查阅了文档记录一下。 initCharts(_id, _name, yAxisData, _unit){if(this[_id]) this[_id].clear();this[_id] $echarts.init(document.getElementById(_id));const options {grid…

基于Springboot+Vue的社区医院管理系统

基于SpringbootVue的社区医院管理系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringBootMyBatisVue工具:IDEA/Ecilpse、Navicat、Maven 系统展示 主页 医生列表 医生详情 登录界面 管理员界面 医生界面 摘要 社区医院管…

van-dialog弹窗异步关闭-校验表单

van-dialog弹窗异步关闭 有时候我们需要通过弹窗去处理表单数据,在原生微信小程序配合vant组件中有多种方式实现,其中UI美观度最高的就是通过van-dialog嵌套表单实现。 通常表单涉及到是否必填,在van-dialog的确认事件中直接return是无法阻止…

POE也收费了

一直通过POE在用chatgpt,今天下午发现要收费了…

二百零三、Flume——Flume实时采集数据频率为1s的高频率Kafka数据直接写入ODS层表的HDFS文件路径下

一、目的 在离线数仓中,需要用Flume去采集Kafka中的数据,然后写入HDFS中。 由于每种数据类型的频率、数据大小、数据规模不同,因此每种数据的采集需要不同的Flume配置文件。玩了几天Flume,感觉Flume的使用难点就是配置文件 二、…

【MATLAB源码-第78期】基于matlab的可见光通信不同调制方式(OOK,PPM,DPPM,DHPIM)误码率,信道容量分析。

操作环境: MATLAB 2022a 1、算法描述 可见光通信(VLC,Visible Light Communication)是一种利用可见光作为信号载体的通信技术。在VLC中,常用的调制方式包括OOK(On-Off Keying)、PPM&#xff…

【C++初阶】三、类和对象(面向过程、class类、类的访问限定符和封装、类的实例化、类对象模型、this指针)

相关代码gitee自取: C语言学习日记: 加油努力 (gitee.com) 接上期: 【C初阶】二、入门知识讲解 (引用、内联函数、auto关键字、基于范围的for循环、指针空值nullptr)-CSDN博客 一 . 面向过程和面向对象初步认识 C语言 -- 面向…