数据结构之通过“ 队列 ”实现的“ 栈 ”功能。

                           🌹个人主页🌹:喜欢草莓熊的bear

                           🌹专栏🌹:数据结构


前言

本节内容是利用“ 队列 ”先进先出的特点 实现 “ 栈 ” 先进后出。

一、题目

 1.1 题目描述:

请你仅使用两个队列实现一个后入先出(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(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

提示:

  • 1 <= x <= 9
  • 最多调用100 次 pushpoptop 和 empty
  • 每次调用 pop 和 top 都保证栈不为空

 1.2 分析题目

我们要通过队列实现栈,怎么实现呢?我们发现一个队列无论如何都无法实现栈的功能,所以我们就尝试创建两个队列来试试。分别为 empty(为空的队列) 、 noempty(不为空的队列)。我们把noempty的数据导入到empty的数据里面,也就是在两个队列里面进行数据倒换。文字比较抽象,所以接下来看图帮助理解。

 二、模拟“ 栈 ”实现的功能

2.1 MyStack* myStackCreate()//初始化

根据我们之前对题目的分析可以知道我们要创建两个队列,所以我们就在结构体里面定义两个队列。

typedef struct //匿名结构体
{Queue s1;//创建两个队列Queue s2;} MyStack;

 再对里面的结构体的队列进行初始化!,因为我们前面写的队列是基于单链表完成,要动态开辟空间。所以要malloc一下。具体操作如下:

MyStack* myStackCreate()//初始化
{MyStack* pst = (MyStack* )malloc(sizeof(MyStack));if(pst==NULL){perror("malloc fail");return -1;}QueueInit(&(pst->s1));QueueInit(&(pst->s2));return pst;
}

2.2 myStackPush(MyStack* obj, int x)//插入数据

我们要进行插入数据,就要想明白。我们要实现栈的特点 “  后进先出  ”。我们这里插入数据任何一个队列中都是一样的。所以我们分为,当两个队列都是空时,进行随便插入。如果一个队列有数据那就在这个有数据的队列进行继续插入。代码很简单,要理解为什么这样插入。

void myStackPush(MyStack* obj, int x)//插入数据
{if(!QueueEmpty(&(obj->s1))){QueuePush(&(obj->s1),x);//如果s1里面有数据就继续进行数据插入}else{QueuePush(&(obj->s2),x);//如果是s1为空那么就向s2里面插入数据}}

2.3 myStackPop(MyStack* obj)//删除并且返回栈定元素

我们这里要实现删除栈顶元素并返回栈顶元素。我们这里采用了之前用到过的假设法,我们把不为空的队列里面数据倒换到为空的队列,这样我们就只需要把不为空里面的数据进行pop(删除)就可以了,因为还要返回栈顶元素  so 我们要把最后一个数据储存后进行pop在返回栈顶元素。

千万注意要把不为空里面数据pop!!

int myStackPop(MyStack* obj)//删除并且返回栈定元素
{//假设法MyStack* empty = &(obj->s1);MyStack* nonempty = &(obj->s2);if(!QueueEmpty(&(obj->s1))){empty = &(obj->s2);nonempty = &(obj->s1);}while(QueueSize(nonempty) > 1 ){QueuePush(empty,QueueFront(nonempty));QueuePop(nonempty);}int ret = QueueFront(nonempty);QueuePop(nonempty);return ret;
}

2.4 myStackTop(MyStack* obj) //获取栈顶元素

获取栈顶元素就很简单了,直接返回队列的最后一个数据就可以了。在这之前我们判一下空,不然一个空队列里面都没有数据怎么返回栈顶元素。

int myStackTop(MyStack* obj) //获取栈顶元素
{if(!QueueEmpty(&obj->s1)){return QueueBack(&obj->s1);}else{return QueueBack(&obj->s2);}
}

2.5 myStackEmpty(MyStack* obj) //判空

因为判空用到的地方比较多建议早点写他!  很简单我们把两个队列与一下在返回就可以了。

return QueueEmpty(&obj->s1) && QueueEmpty(&obj->s2);

2.6 myStackFree(MyStack* obj) //销毁

销毁我们要小心一点,因为我们不仅仅动态申请了Mystack的空间,我们还动态申请了队列的空间。所以两个队列也要进行销毁。我们直接调用我们之前写的队列销毁函数后,进行free操作。

还要进行置为空指针。

void myStackFree(MyStack* obj) //销毁
{QueueDestory(&obj->s1);QueueDestory(&obj->s2);free(obj);obj=NULL;
}

三、代码展示

typedef int QDataType;typedef struct QueueNode
{struct QueueNode* next;QDataType val;
}QNode;typedef struct Queue 
{QNode* phead;QNode* ptail;int size;
}Queue;void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}void QueueDestory(Queue* pq)
{assert(pq);QNode* pur = pq->phead;while (pur){QNode* cur = pur->next;free(pur);pur = cur;}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->next = NULL;Newnode->val = x;if (pq->phead==NULL)//空链表{pq->phead = pq->ptail = Newnode;}else{pq->ptail->next = Newnode;pq->ptail = Newnode;}pq->size++;//用来计数
}void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);if (pq->phead == pq->ptail)//只有一个节点{free(pq->phead);pq->phead = pq->ptail = NULL;}else//多个节点{QNode* tmp = pq->phead->next;free(pq->phead);pq->phead = tmp;}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;
}int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}typedef struct //匿名结构体
{Queue s1;//创建两个队列Queue s2;} MyStack;MyStack* myStackCreate()//初始化
{MyStack* pst = (MyStack* )malloc(sizeof(MyStack));if(pst==NULL){perror("malloc fail");return -1;}QueueInit(&(pst->s1));QueueInit(&(pst->s2));return pst;
}void myStackPush(MyStack* obj, int x)//插入数据
{if(!QueueEmpty(&(obj->s1))){QueuePush(&(obj->s1),x);}else{QueuePush(&(obj->s2),x);}}int myStackPop(MyStack* obj)//删除并且返回栈定元素
{//假设法MyStack* empty = &(obj->s1);MyStack* nonempty = &(obj->s2);if(!QueueEmpty(&(obj->s1))){empty = &(obj->s2);nonempty = &(obj->s1);}while(QueueSize(nonempty) > 1 ){QueuePush(empty,QueueFront(nonempty));QueuePop(nonempty);}int ret = QueueFront(nonempty);QueuePop(nonempty);return ret;
}int myStackTop(MyStack* obj) //获取栈顶元素
{if(!QueueEmpty(&obj->s1)){return QueueBack(&obj->s1);}else{return QueueBack(&obj->s2);}
}bool myStackEmpty(MyStack* obj) //判空
{return QueueEmpty(&obj->s1) && QueueEmpty(&obj->s2);
}void myStackFree(MyStack* obj) //销毁
{QueueDestory(&obj->s1);QueueDestory(&obj->s2);free(obj);obj=NULL;
}

总结

我们这里的代码都是基于队列来实现的,我们要掌握这个倒换数据思路来解题。好了谢谢大家的观看!!下期见ヾ(•ω•`)o

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

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

相关文章

成为CMake砖家(1): 在Windows上查看CMake文档

大家好&#xff0c;我是白鱼。 在使用 CMake 的过程中&#xff0c;想必有不少朋友像我一样&#xff0c; 想在本地查看 CMake 文档。 首先安装 CMake, Installer 版本&#xff1a; 安装后&#xff0c;从开始菜单输入 CMake&#xff0c; 选择结果中的 “CMake Documentation”…

如何在 Shell 脚本中使用函数 ?

函数是一个可重用的代码块。我们经常把重复的代码放入一个函数中&#xff0c;并从不同的地方调用该函数&#xff0c;库是函数的集合。我们可以在库中定义常用的函数&#xff0c;其他脚本可以使用它们而无需复制代码。 Calling function 在 Shell 中&#xff0c;调用函数和调用…

1.33、激活可视化卷积神经网络(matalb)

1、激活可视化卷积神经网络原理及流程 激活可视化&#xff08;Activation Visualization&#xff09;指的是通过可视化神经网络中激活函数的输出&#xff0c;来理解神经网络是如何学习并提取特征的过程。在卷积神经网络&#xff08;CNN&#xff09;中&#xff0c;我们可以通过…

tomcat的优化、动静分离

tomcat的优化 tomcat自身的优化 tomcat的并发处理能力不强&#xff0c;大项目不适应tomcat做为转发动态的中间件&#xff08;k8s集群&#xff0c;pytnon rubby&#xff09;&#xff0c;小项目会使用&#xff08;内部使用的&#xff09;动静分离 默认配置不适合生产环境&…

MySQl高级篇 -索引优化篇

索引 InnoDB采用了一个B数来存储索引&#xff0c;使得在千万级数据量的一个情况下&#xff0c;树的高度可以控制在3层以内&#xff0c;而层高代表磁盘IO的一个次数&#xff0c;因此基于索引查找可以减少磁盘IO的次数 MySQL的索引是在存储引擎层实现的&#xff0c;不同的存储引…

头歌资源库(31)象棋中马遍历棋盘的问题

一、 问题描述 二、算法思想 这是一个典型的深度优先搜索问题。 首先&#xff0c;我们创建一个mn的棋盘&#xff0c;并初始化所有的点为未访问状态。 然后&#xff0c;我们从(0, 0)位置开始进行深度优先搜索。 在每一步中&#xff0c;我们先标记当前位置为已访问&#xff0…

Android Viewpager2 remove fragmen不生效解决方案

一、介绍 在如今的开发过程只&#xff0c;内容变化已多单一的fragment&#xff0c;变成连续的&#xff0c;特别是以短视频或者直播为主的场景很多。从早起的Viewpage只能横向滑动&#xff0c;到如今的viewpage2可以支持横向或者竖向滑动。由于viewpage2的adapter在设计时支持缓…

解决mysql,Navicat for MySQL,IntelliJ IDEA之间中文乱码

使用软件版本 jdk-8u171-windows-x64 ideaIU-2021.1.3 mysql-essential-5.0.87-win32 navicat8_mysql_cs 这个问题我调试了好久&#xff0c;网上的方法基本上都试过了&#xff0c;终于是解决了。 三个地方结果都不一样。 方法一 首先大家可以尝试下面这种方法&#xff1a…

基于Python+Django+MySQL+Echarts的租房数据可视化分析系统

租房数据可视化 DjangoMySQLEcharts 基于PythonDjangoMySQLEcharts的租房数据可视化分析系统 Echarts 信息存储在数据库中 不含爬虫代码&#xff0c;或爬虫代码已失效 不支持登录注册 简介 基于DjangoMySQLEcharts的租房数据可视化系统通过连接数据库获取数据&#xff0c…

【格密码基础】旋转格的性质

目录 一. 回顾ZSVP问题 二. 基于ZSVP问题的密码系统 三. 格基旋转与Gram矩阵 四. 补充矩阵QR分解 4.1 矩阵分解 4.2 举例 前序文章请参考&#xff1a; 【格密码基础】详解ZSVP问题-CSDN博客 一. 回顾ZSVP问题 根据之前的讨论我们知道解决ZSVP问题的计算复杂度为&#x…

一款IM即时通讯聊天系统源码,包含app和后台源码

一款IM即时通讯聊天系统源码 聊天APP 附APP&#xff0c;后端是基于spring boot开发的。 这是一款独立服务器部署的即时通讯解决方案&#xff0c;可以帮助你快速拥有一套自己的移动社交、 企业办公、多功能业务产品。可以 独立部署&#xff01;加密通道&#xff01;牢牢掌握通…

您需要了解的欧盟网络弹性法案

了解CRA包含的内容以及如何遵守。 什么是CRA&#xff1f; 《网络弹性法案》&#xff08;CRA&#xff09;是即将出台的欧盟法规&#xff0c;旨在确保在欧盟销售的所有数字产品和服务&#xff08;如连接到互联网的软件和硬件&#xff09;都采用强大的网络安全措施。 该法案要求…

【数据结构与算法】选择排序篇----详解直接插入排序和哈希排序【图文讲解】

欢迎来到CILMY23的博客 &#x1f3c6;本篇主题为&#xff1a;【数据结构与算法】选择排序篇----详解直接插入排序和哈希排序 &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux…

Chrome浏览器的Profile数据内容简介

前文简介了Chrome存储的账密/Cookie数据&#xff1a;一段代码读取Chrome存储的所有账号密码和Cookie 本文再扩展介绍一下Chrome存储的其它一些隐私数据。 注&#xff1a;因为业务需要&#xff0c;简单调研了一些基本内容和存储路径&#xff0c;没有深入去研究&#xff0c;有啥…

新160个crackme - 002-abexcm5

运行分析 猜测需要输入正确序列号 PE分析 32位&#xff0c;ASM程序&#xff0c;无壳 静态分析 ida shift F12 &#xff0c;发现字符串定位主函数 分析主函数 lstrcat&#xff1a;拼接字符串 lstrcmpiA&#xff1a;比较字符串 动态调试 serial输入123456调试 发现序列号…

Codeforces Round 957 (Div. 3)(A~D题)

A. Only Pluses 思路: 优先增加最小的数&#xff0c;它们的乘积会是最优,假如只有两个数a和b&#xff0c;b>a&#xff0c;那么a 1&#xff0c;就增加一份b。如果b 1&#xff0c;只能增加1份a。因为 b > a&#xff0c;所以增加小的数是最优的。 代码: #include<bi…

Spring Boot集成groovy快速入门Demo

1.什么是groovy&#xff1f; Groovy 是构建在 JVM 上的一个轻量级却强大的动态语言&#xff0c;它结合了 Python、Ruby 和 Smalltalk 的许多强大的特性。 Groovy 就是用 Java 写的&#xff0c;Groovy 语法与 Java 语法类似&#xff0c;Groovy 代码能够与 Java 代码很好地结合&…

STM32MP135裸机编程:定时器内核时钟频率计算方法

0 工具准备 STM32MP13xx参考手册 1 定时器内核时钟频率计算方法 1.1 定时器分组 STM32MP135的定时器按照时钟源不同分成了三组&#xff0c;如下&#xff1a; APB1: APB2: APB6&#xff1a; 1.2 定时器内核时钟频率计算方法 APB1DIV是APB1的分频系数&#xff0c;APB2DIV、…

python双下划线怎么打

连续按键盘上的“shift_”键两次即可&#xff0c;不同编辑器可能显示会不太一样。像图1中那样没连起来也是对的&#xff0c;没有语法错误。

基于python豆瓣电影爬虫数据可视化分析推荐系统(完整系统源码+数据库+详细文档+论文+详细部署教程)

文章目录 基于python豆瓣电影爬虫数据可视化分析推荐系统&#xff08;完整系统源码数据库详细文档论文详细部署教程&#xff09;一、 选题背景二、研究目的三、开发技术介绍1、Django框架2、LDA3、机器学习推荐算法4、大数据爬虫5、大数据Echarts可视化 四、系统设计思想五、部…