用队列和栈分别实现栈和队列

用队列实现栈
题目解读

在这里插入图片描述
本题的要求是要用两个队列来实现一个先进后出的栈,并且要有以下功能:
1.将元素压入栈中
2.移除栈顶元素并且返回他
3.返回栈顶元素
4.判断栈是否为空

题目构思和代码实现

我们首先要做的就是将实现队列的代码导入该题(也可以自己写)
下面我们来进行题目的构思:
我们知道,栈的增加和删除元素都是从栈顶进行操作的,并且遵循先进后后出的原则,但是队列是遵循先进先出的规则,增加元素从队尾增加,删除元素从队首删除。
怎么解决呢?
其实题目已经给了我们提示:用两个队列!
我们可以这样,先构造两个队列,一个用来删除栈的元素,一个用来增加栈的元素。
所以我们就可以开辟两个队列,一个叫pop,一个叫push

typedef struct 
{Queue push;Queue pop;
} MyStack;MyStack* myStackCreate() 
{MyStack* obj=(MyStack*)malloc(sizeof(MyStack));if(obj==NULL){return NULL;}QueueInit(&obj->push);QueueInit(&obj->pop);return obj;
}

我们需要将元素压入栈中是就看哪一个队列不为空就压入到那个队列中
我们用之前队列写的判断队列 是否为空来增加代码的可读性

void myStackPush(MyStack* obj, int x) 
{if(!QueueEmpty(&obj->push)){QueuePush(&obj->push,x);}else{QueuePush(&obj->pop,x);}
}

移除栈中的元素就要看情况了:
我们首先假设push队列为空,pop队列不为空,然后再用一个if语句进行判断,如果push不为空就交换
然后我们将不为空的那个队列里面的除了队尾元素的所有元素都统统放入为空的那个队列里面,知道不为空队列里面只剩下一个元素,先存储这个元素,然后就直接将他删除,最后返回这个元素
在这里插入图片描述

int myStackPop(MyStack* obj) 
{Queue* empty=&obj->push;Queue* nonempty=&obj->pop;if(!QueueEmpty(&obj->push)){empty=&obj->pop;nonempty=&obj->push;}while(QueueSize(nonempty)>1){QueuePush(empty,QueueFront(nonempty));QueuePop(nonempty);}int top=QueueFront(nonempty);QueuePop(nonempty);return top;
}

返回栈顶元素就直接返回非空队列的队尾元素即可

nt myStackTop(MyStack* obj) 
{if(!QueueEmpty(&obj->push)){return QueueBack(&obj->push);}else{return QueueBack(&obj->pop);}
}

栈为空时两个队列都为空

bool myStackEmpty(MyStack* obj) 
{return QueueEmpty(&obj->pop)&&QueueEmpty(&obj->push);
}

完整代码如下:

typedef struct 
{Queue push;Queue pop;
} MyStack;MyStack* myStackCreate() 
{MyStack* obj=(MyStack*)malloc(sizeof(MyStack));if(obj==NULL){return NULL;}QueueInit(&obj->push);QueueInit(&obj->pop);return obj;
}void myStackPush(MyStack* obj, int x) 
{if(!QueueEmpty(&obj->push)){QueuePush(&obj->push,x);}else{QueuePush(&obj->pop,x);}
}int myStackPop(MyStack* obj) 
{Queue* empty=&obj->push;Queue* nonempty=&obj->pop;if(!QueueEmpty(&obj->push)){empty=&obj->pop;nonempty=&obj->push;}while(QueueSize(nonempty)>1){QueuePush(empty,QueueFront(nonempty));QueuePop(nonempty);}int top=QueueFront(nonempty);QueuePop(nonempty);return top;
}int myStackTop(MyStack* obj) 
{if(!QueueEmpty(&obj->push)){return QueueBack(&obj->push);}else{return QueueBack(&obj->pop);}
}bool myStackEmpty(MyStack* obj) 
{return QueueEmpty(&obj->pop)&&QueueEmpty(&obj->push);
}
用栈实现队列
题目解读

在这里插入图片描述
题目的意思和上一题大同小异,要实现的功能都大差不差的,这里我就不做过多的解读,直接开始构思:

题目构思和代码实现

要想实现队列,我们用两个栈如何实现呢?
首先,栈时遵循先进后出的原则,但是队列时先进先出,难不成也像上一题一样,一个栈用来增加数据,另一个栈用来删除数据?

typedef struct 
{Stack pushstack;Stack popstack;
} MyQueue;MyQueue* myQueueCreate() 
{MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));if(obj==NULL){perror("malloc");return NULL;}StackInit(&obj->pushstack);StackInit(&obj->popstack);return obj;
}

其实我们可以这样:
当你要增加元素,就将这个元素压入pushstack也就是专门存储增加队列的增加的元素的
删除元素时就有点麻烦咯
当需要删除时,我们要删除的是最先进入队列的元素,也就是pushstack的栈底元素,那么如何将他删除呢?
我们可以将pushstack的栈顶元素逐个压入到popstack中,然后删除掉pushstack中的栈底元素即可
这里题目中的查找队首元素也可以搭配使用,当pop栈为空时,队首元素就是push栈的栈底元素,pop栈不为空时,就是pop栈的栈顶元素

int myQueuePeek(MyQueue* obj) 
{if(StackEmpty(&obj->popstack)){while(!StackEmpty(&obj->pushstack)){StackPush(&obj->popstack,StackTop(&obj->pushstack));StackPop(&obj->pushstack);}}return StackTop(&obj->popstack);
}

在这里插入图片描述
增加和删除元素代码如下:

void myQueuePush(MyQueue* obj, int x) 
{StackPush(&obj->pushstack,x);
}int myQueuePop(MyQueue* obj) 
{int front=myQueuePeek(obj);StackPop(&obj->popstack);return front;
}

队列的销毁要注意,free掉obj的同时要记得销毁两个栈:

void myQueueFree(MyQueue* obj) 
{StackDestroy(&obj->popstack);StackDestroy(&obj->pushstack);free(obj);
}

完整代码如下:

typedef struct 
{Stack pushstack;Stack popstack;
} MyQueue;MyQueue* myQueueCreate() 
{MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));if(obj==NULL){perror("malloc");return NULL;}StackInit(&obj->pushstack);StackInit(&obj->popstack);return obj;
}bool myQueueEmpty(MyQueue* obj) 
{return StackEmpty(&obj->popstack)&&StackEmpty(&obj->pushstack);
}void myQueuePush(MyQueue* obj, int x) 
{StackPush(&obj->pushstack,x);
}int myQueuePeek(MyQueue* obj) 
{if(StackEmpty(&obj->popstack)){while(!StackEmpty(&obj->pushstack)){StackPush(&obj->popstack,StackTop(&obj->pushstack));StackPop(&obj->pushstack);}}return StackTop(&obj->popstack);
}int myQueuePop(MyQueue* obj) 
{int front=myQueuePeek(obj);StackPop(&obj->popstack);return front;
}void myQueueFree(MyQueue* obj) 
{StackDestroy(&obj->popstack);StackDestroy(&obj->pushstack);free(obj);
}

好了,今天的分享到这里就结束了,谢谢大家的支持!

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

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

相关文章

SSM 框架整合

1 整合配置 1.1 流程 1.2 Spring 整合 MyBatis 1.3 Spring 整合 SpringMVC 1.4 配置代码 JdbcConfig.java public class JdbcConfig {Value("${jdbc.driver}")private String driver;Value("${jdbc.url}")private String url;Value("${jdbc.usern…

C# MemoryCache的使用和封装

封装个缓存类,方便下次使用。 using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic;namespace Order.Core.API.Cache {public class GlobalCache C#有偿Q群:927860652{private static readonly MemoryCache …

四、IDEA创建项目时,Maven Archetype模板工程说明

什么是Maven Archetype Archetype是一个Maven项目的模板工具包,它定义了一类项目的基本架构。Archetype为开发人员提供了创建Maven项目的模板,同时它也可以根据已有的Maven项目生成参数化的模板。 官方文档:https://maven.apache.org/archet…

java_基础_标识符

1.标识符概述 1.标识符:就是给类,方法,变量等起名字的符号. 2.标识符定义规则: 由数字、字母、下划线(_)美元符号($)组成 不能是关键字 区分大小写 3.常见命名约定 小驼峰命名法:方法 和 变量 约定1:标识符是一个单词的时候&am…

苍穹外卖--店铺营业状态设置

需求分析和设计 1.1.1 产品原型 进到苍穹外卖后台,显示餐厅的营业状态,营业状态分为营业中和打烊中,若当前餐厅处于营业状态,自动接收任何订单,客户可在小程序进行下单操作;若当前餐厅处于打烊状态&#…

AIGC(生成式AI)试用 13 -- 数据时效性

数据时效性? 最新的数据,代表最新的状态,使用最新的数据也应该最有说服力。 学习需要时间,AIGC学习并接收最新数据的效果如何? 问题很简单,如何验证?这个需要找点更新快的对像进行验证。…

Apache换行解析漏洞(CVE-2017-15715)

漏洞简介 Apache換行解析漏洞(CVE-2017-15715)是一种解析漏洞,可以影响httpd 2.4.0至2.4.29版本中的PHP解析。攻击者可以通过在上传的文件名中添加特定的换行符,绕过服务器的安全策略,使其被解析成PHP文件而不是普通文件。此漏洞会影响具有以下条件的服务器: 未正确配置…

cuda magma 构建 使用cmake构建的步骤记录

这不是群论代数软件,而是cuda 矩阵计算软件 1. 生成其他精度的源代码 1.1 复制编辑 make.inc cp make.inc-examples/make.inc.openblas ./make.inc 并修改其中的定义: OPENBLASDIR ? /opt/OpenBLAS 这需要实现安装openblas到此处。文件夹解构&…

【通讯协议】REST API vs GraphQL

在API设计方面,REST和GraphQL各有缺点。下图显示了 REST 和 GraphQL 之间的快速比较。 REST 使用标准 HTTP 方法(如 GET、POST、PUT、DELETE)进行 CRUD 操作。当您需要在单独的服务/应用程序之间提供简单、统一的接口时,效果很好…

每日一题 - 231125 - D - Counting Ls

D - Counting Ls TAG - 一眼丁真、鉴定为纯纯大水题 一眼丁真、鉴定为纯纯大水题 一眼丁真、鉴定为纯纯大水题时间复杂度 - O ( N 2 ) O(N^2) O(N2) // #include<bits/stdc.h> using namespace std; #define int long long const int N2005; char g[N][N]; int cnti[N…

超详细csapp-linklab之第一阶段“输出学号”实验报告

该实验的主题是“链接”。 准备工具 虚拟机&#xff0c;Ubuntu32位&#xff0c;hexedit&#xff0c;main.o&#xff0c;phase1.o&#xff0c;该实验的C代码框架如下 // main.c void (*phase)(); /*初始化为0*/int main( int argc, const char* argv[] ) {if ( phase )(*ph…

TDlib readme

不同开发语言使用TDlib的连接入口&#xff1a;td/example/README.md at master tdlib/td (github.com) 如golang:td/example/README.md at master tdlib/td (github.com)

java_基础_类型转换

1.自动类型转换 格式&#xff1a;把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量 示例&#xff1a;double d 10; 2.强制类型转换 格式&#xff1a;目标数据类型 变量名称 &#xff08;目标数据类型&#xff09;值或者变量 示例&#xff1a;int k …

链表经典面试题

1 回文链表 1.1 判断方法 第一种&#xff08;笔试&#xff09;&#xff1a; 链表从中间分开&#xff0c;把后半部分的节点放到栈中从链表的头结点开始&#xff0c;依次和弹出的节点比较 第二种&#xff08;面试&#xff09;&#xff1a; 反转链表的后半部分&#xff0c;中间节…

leetcode刷题详解五

117. 填充每个节点的下一个右侧节点指针 II 关键点&#xff1a;先递归右子树 画一下就知道了&#xff0c;画一个四层的二叉树&#xff0c;然后右子树多画几个节点就知道为啥了 Node* connect(Node* root) {if(!root || (!root->left && !root->right)){return ro…

实战oj题——括号匹配问题

前言&#xff1a;前面我们已经做了一些关于顺序表和链表的oj题&#xff0c;今天我们就来解决一些有关于栈和队列的oj题。 我们对这个题看起来毫无头绪&#xff0c;但是我们刚学习了栈&#xff0c;就可以用栈来解决这一类问题&#xff0c;如果我们读取到左括号就入栈&#xff0c…

2023年最新Visual Studio下载安装以及C语言环境搭建教程(含C语言入门教程)

文章目录 写在前面C语言简介Visual Studio简介Visual Studio安装教程 C语言入门Visual Studio使用教程 写在后面 写在前面 2023年最新Visual Studio下载安装以及C语言环境搭建教程来啦&#xff01;一起来看看吧~ C语言简介 C语言是一种高级编程语言&#xff0c;由美国贝尔实…

90. 打家劫舍II (房子围成一圈)

题目 题解 class Solution:def rob(self, nums: List[int]) -> int:def dp(nums: List[int]) -> int:N len(nums)# 定义状态&#xff1a;dp[i]表示从第i个房屋开始偷窃&#xff0c;能够偷到的最高金额dp [0 for i in range(N)]for i in range(N-1, -1, -1):if i N-1:…

uiautomator2 无法连接 ATX-Agent

最近需要写个安卓自动项目&#xff0c;本身不想用appium 。主要是appium需要安装的依赖太多&#xff0c;一单换个环境又要配置新的环境。但是ATX-Agent装好之后怎么都连接不是。 报错信息如下&#xff1a; .........省略............ uiautomator2.exceptions.GatewayError: (…

Zookeeper(一):在WSL单机搭建Zookeeper伪集群

目录 Zookeeper1 启动单个Zookeeper实例1.1 下载Zookeeper安装包并解压1.2 添加环境变量1.3 修改默认配置1.4 新建数据存储目录和日志目录1.5 启动Zookeeper1.6 停止Zookeeper 2 搭建Zookeeper集群2.1 新建集群目录2.2 配置环境变量2.3 创建节点目录2.4 修改配置2.5 创建节点ID…