数据结构刷题训练:用栈实现队列(力扣OJ)

目录

前言

1. 题目:用栈实现队列

2. 思路

3. 分析

 3.1 定义 “ 队列 ”

 3.2 创建队列

3.3 入队

 3.4 队头数据

 3.5 出队

 3.6 判空和销毁

4.题解

总结


前言

        栈和队列是数据结构中的两个重要概念,它们在算法和程序设计中都有着广泛的应用。本文将带你深入了解如何使用栈来模拟实现队列,让你在解决问题时更加灵活和创新,便于大家更深入的理解栈和队列。


1. 题目:用栈实现队列

 题目描述:

 题目链接:

用栈实现队列icon-default.png?t=N6B9https://leetcode.cn/problems/implement-queue-using-stacks/description/

2. 思路

         这道题目的解题思路于队列实现栈有很大的相似点。这道题也是给了两个栈,要求使用两个栈来实现队列。这里我们可以使用两边倒的方式来模拟实现队列。

        假设入栈:1、2、3、4那么出栈的顺序就是4、3、2、1,如果我们按照出栈的顺序再入栈到另一个栈中(空栈),再次出栈就可以达到队列出队的效果(1、2、3、4)

3. 分析

        根据上述的思路我们就可以利用两个栈模拟实现队列。思路的大概过程:

         那么我们来考虑一下特殊的情况,如果我们入队了1、2、3、4,出队了1和2,然后再入队5和6,这时候我们考虑一下是否还需要倒一次(将剩下的3和4入栈到原栈中,然后入栈5和6,再将3、4、5、6依次出栈,入栈到另外一个栈中)?

        这里其实是不需要在倒一次,入队1、2、3、4。出队1和2,然后再入队5和6,然后再出队,出队的顺序是:1、2、3、4、5、6。我们可以将5和6入栈到原栈中,然后将3和4继续出栈,当一个栈为空时再入栈原栈中的数据。过程如下:

         好的过程分析完之后,我们来对每个接口进行实现。题目中依然是没有现成的栈,所以我们依然需要 “ 造轮子 ” 前边我们已经实现的栈可以复制过来使用。

 3.1 定义 “ 队列 ”

         由于我们再模拟队列时需要用到两个栈,但调用函数时传两个栈又太麻烦,这里我们就使用结构体来定义两个栈(MyQueue),这样传参时就可以直接传结构体(MyQueue)指针就可以了。

typedef struct {Stack pushst;Stack popst;
} MyQueue;

 3.2 创建队列

         创建队列就非常简单了,我们只需要调用前边实现的InItStack函数将两个栈进行初始化就可以了:

MyQueue* myQueueCreate() {MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));InItStack(&obj->pushst);InItStack(&obj->popst);return obj;
}

         可能对结构体不熟练的同学会有疑惑:

问题一:

        为什么要malloc一个空间?这里注意:前边我们仅仅只是定义了一个模拟实现的队列,定义的是类型,并没有创建结构体变量,这里malloc也仅仅只是创建一个结构体变量。

 问题二:

        那为什么不直接MyQueue obj;这样定义?这是在函数内部,如果这样创建结构体变量它是创建在栈区,一旦出了函数1就会被销毁,为了后续的传参,所以最好使用malloc在堆区开辟空间。

问题三:

        初始化两个栈时需要取地址,那我们可不可以在定义时直接定义成指针类型例如:

Stack* pushst;
Stack* popst;

         这当然可以,但是如果按照这样的写法,那么在创建 “队列” 时就需要malloc给两个栈开辟空间(在调用的初始化函数中并没有开辟空间给栈)。如果是这样定义:

typedef struct {Stack pushst;Stack popst;
} MyQueue;

 那么在malloc,obj时就已经将两个栈的空间开辟好了。这样也更简单便捷。

3.3 入队

         入队就很简单了,直接将数据入栈到pushst中。

void myQueuePush(MyQueue* obj, int x) {StackPush(&obj->pushst,x);
}

 3.4 队头数据

         这里为什么先写队头数据呢?那是因为出队时不仅需要将队头移除,还需要返回被移除队头的数据。所以这里我们先实现队头数据的接口。

        想要得到队头数据,那就需要将pushst中的元素按照出栈顺序入栈到popst中,然后返回popst这个栈的栈顶元素即可,过程如下:

 

int myQueuePeek(MyQueue* obj) {if(IsEmpty(&obj->popst)){while(!IsEmpty(&obj->pushst)){StackPush(&obj->popst,TopData(&obj->pushst));StackPop(&obj->pushst);}}return TopData(&obj->popst);
}

         这里注意:入栈到popst中的条件是popst为空,这也与上述的分析对应,popst栈为空时才可以继续将pushst中入队元素倒到popst中。

 3.5 出队

        有了队头数据的接口,出队接口的实现就非常简单了,在出队前保存一下队头数据(popst栈顶数据),然后将popst中的栈顶元素出栈,最后返回front即可

int myQueuePop(MyQueue* obj) {int front=myQueuePeek(obj);StackPop(&obj->popst);return front;
}

 3.6 判空和销毁

         判空和销毁的接口也非常简单,当两个栈都为空时就表明队列为空,代码如下:

bool myQueueEmpty(MyQueue* obj) {return (IsEmpty(&obj->pushst)&&IsEmpty(&obj->popst));
}

         接下来是销毁,销毁队列前我们需要先将两个栈销毁,最后销毁obj。代码如下:

void myQueueFree(MyQueue* obj) {DestoryStack(&obj->popst);DestoryStack(&obj->pushst);free(obj);
}

4.题解

整体代码如下:

typedef int Datatype;
typedef struct Stack
{Datatype* a;int top;int capacity;
}Stack;void InItStack(Stack* ps);void DestoryStack(Stack* ps);void StackPush(Stack* ps, Datatype x);void StackPop(Stack* ps);int Stacksize(Stack* ps);Datatype TopData(Stack* ps);bool IsEmpty(Stack* ps);void InItStack(Stack* ps)
{assert(ps);ps->top = 0;ps->a = NULL;ps->capacity = 0;
}void DestoryStack(Stack* ps)
{assert(ps);ps->top = ps->capacity = 0;free(ps->a);ps->a = NULL;
}
void StackPush(Stack* ps, Datatype x)
{assert(ps);if (ps->top == ps->capacity){int newcapacity = (ps->capacity == 0 ? 4 : ps->capacity * 2);Datatype* tmp = (Datatype*)realloc(ps->a, sizeof(Datatype) * newcapacity);if (tmp == NULL){perror("realloc fail");exit(-1);}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = x;ps->top++;
}
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}
int Stacksize(Stack* ps)
{assert(ps);return ps->top;
}
Datatype TopData(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];
}
bool IsEmpty(Stack* ps)
{assert(ps);return (ps->top == 0);
}typedef struct {Stack pushst;Stack popst;
} MyQueue;MyQueue* myQueueCreate() {MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));InItStack(&obj->pushst);InItStack(&obj->popst);return obj;
}void myQueuePush(MyQueue* obj, int x) {StackPush(&obj->pushst,x);
}int myQueuePeek(MyQueue* obj) {if(IsEmpty(&obj->popst)){while(!IsEmpty(&obj->pushst)){StackPush(&obj->popst,TopData(&obj->pushst));StackPop(&obj->pushst);}}return TopData(&obj->popst);
}int myQueuePop(MyQueue* obj) {int front=myQueuePeek(obj);StackPop(&obj->popst);return front;
}bool myQueueEmpty(MyQueue* obj) {return (IsEmpty(&obj->pushst)&&IsEmpty(&obj->popst));
}void myQueueFree(MyQueue* obj) {DestoryStack(&obj->popst);DestoryStack(&obj->pushst);free(obj);
}

 

总结

        使用栈模拟实现队列,让我们在实践中深入思考了数据结构的本质和应用,为我们的编程思维和算法设计能力提供了挑战和提升。希望本期内容对你有些许帮助,最后,感谢阅读!

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

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

相关文章

物联网是下一个风口吗?

随着科技的持续进步,物联网行业正在迅速兴起,展现出巨大的潜力。那么,物联网行业的未来是什么样的呢? 1. 5G技术的广泛应用和普及 随着5G技术的快速发展和商业化推广,物联网行业将迎来一个巨大的飞跃。5G技术的高速传…

kube-prometheus 使用 blackbox-exporter 进行icmp 监控

安装kube-prometheus 后默认在monitoring namespace中有创建 blackbox-exporter deployment。但默认没有icmp的module配置,无法执行ping探测。因为即使有icmp module,默认配置也是无法执行ping探测的(这篇文章要解决的就是这个问题&#xff0…

中科亿海微FIFO使用

引言 FPGA(现场可编程门阵列)是一种可编程逻辑器件,具有灵活性和可重构性,广泛用于数字电路设计和嵌入式系统开发。在FPGA中,FIFO(First-In, First-Out)是一种常见的存储器结构,用于…

1001 Battle Over Cities - Hard Version (PAT顶级)

总体思路是用并查集来做。vec记录了目前断掉的路,use记录了使用中的路。将断掉的路按照修复费用从小到大排序。 对每一个城市i失守进行讨论,先根据use将其中两端城市进行union,然后计算一下联通块个数。再按序找两个城市不在同一个联通块中的…

Java常用代码块、工具类、常用框架、mysql常用语句模版汇总

Idea常用插件 Build Generator:生成builder模式的代码MybatisX:mapper.xml文件和dao之间关联、映射LombokMaven Helper:分析maven冲突等Json parserJava后台常用框架 springbootspringmvcmybatis -plusmysqlmavenjunitjacksonguavaapache commons utilsnettyswaggerjoda-tim…

【Nginx】Nginx的重定向——location

location 匹配URI location 匹配的规则和优先级;***重点 nginx常用的变量;要求掌握 rewrite 重定向;掌握/理解 location匹配:*** 正则表达式:匹配的是文件内容 常见的正则表达式&#xff1a…

读《Flask Web开发实战》(狼书)笔记 | 第1、2章

前言 2023-8-11 以前对网站开发萌生了想法,又有些急于求成,在B站照着视频敲了一个基于flask的博客系统。但对于程序的代码难免有些囫囵吞枣,存在许多模糊或不太理解的地方,只会照葫芦画瓢。 而当自己想开发一个什么网站的时&…

【云原生】Kubernetes 概述

Kubernetes 概述 1.Kubernetes 简介 Kubernetes 是一个可移植的、可扩展的、用于管理容器化工作负载和服务的开源平台,它简化(促进)了声明式配置和自动化。它有一个庞大的、快速增长的生态系统。Kubernetes 的服务、支持和工具随处可见。 K…

消息队列kafka及zookeeper机制

一、zookeeper1.1 zookeeper简介1.2 zookeeper工作机制1.3 Zookeeper特点1.4 Zookeeper 数据结构1.5 Zookeeper 应用场景1.5.1 统一命名服务1.5.2 统一配置管理1.5.3 统一集群管理1.5.4 服务器动态上下线1.5.5 软负载均衡 1.6 Zookeeper 选举机制1.6.1 第一次启动选举机制1.6.2…

Jenkins 使用

Jenkins 使用 文章目录 Jenkins 使用一、jenkins 任务执行二、 Jenkins 连接gitee三、Jenkins 部署静态网站 一、jenkins 任务执行 jenkins 创建 job job的名字最好是有意义的 restart_web_backend restart_web_mysql[rootjenkins ~]# ls /var/lib/jenkins/ config.xml …

为什么Tomcat的NIO在读取body时要模拟阻塞?

文章首发地址 Tomcat的NIO完全可以以非阻塞方式处理IO,为什么在读取body部分时要模拟阻塞呢?在Tomcat的NIO读取HTTP请求时,为了保证请求的正确性和可靠性,需要模拟阻塞模式,这是因为servlet规范里定义了ServletInputSt…

W5500-EVB-PICO作为TCP Client 进行数据回环测试(五)

前言 上一章我们用W5500-EVB-PICO开发板通过DNS解析www.baidu.com(百度域名)成功得到其IP地址,那么本章我们将用我们的开发板作为客户端去连接服务器,并做数据回环测试:收到服务器发送的数据,并回传给服务器…

设计模式-单例

概述 在类加载后,整个系统只有一个实例类 饿汉式 public class Mg1 {private static final Mg1 INSTANCE new Mg1();private Mg1(){}public static Mg1 getInstance(){return INSTANCE;}public static void main(String[] args) {System.out.println(Mg1.getIns…

SAP MM学习笔记16-在库品目评价

在库品目评价是指评估物料。具体比如物料价格,数量,保管场所等发生变化的时候,判断是否发生了变化,要不要生成 FI票,用哪个FI科目来进行管理等内容就叫在库品目评价。 在库品目评价有很多层级,这里先讲3兄弟…

物联网嵌入式学习路线发展方向(表格一目了然)

文章目录: 一:学习路线 二:各种分类 1.软件硬件分类 2.发展方向 技术类型 对应岗位分类 3.常见板子芯片内核 4.嵌入式公司 对于小白:不知道嵌入式整个体系?学什么?顺序是什么?可以找什么…

在Linux虚拟机内配置nginx以及docker

目录 1、nginx源码包编译以及安装依赖 1、配置安装所需的编译环境 2、安装函数库(pcre、zlib、openssl) 2、安装nginx 1、获取源码包 2、解压编译 3、启动nginx服务 1、关闭防火墙 2、运行nginx 3、使用本地浏览器进行验证 3、安装docker 1、…

每次执行@Test方法前都执行一次DB初始化(SpringBoot Test + JUnit5环境)

引言 在执行单元测试时,可以使用诸如H2内存数据库替代线上的Mysql数据库等,如此在执行单元测试时就能尽可能模拟真实环境的SQL执行,同时也无需依赖线上数据库,增加了测试用例执行环境的可移植性。而使用H2数据库时,通…

Oracle DB 安全性 : TDE HSM TCPS Wallet Imperva

• 配置口令文件以使用区分大小写的口令 • 对表空间进行加密 • 配置对网络服务的细粒度访问 TCPS 安全口令支持 Oracle Database 11g中的口令: • 区分大小写 • 包含更多的字符 • 使用更安全的散列算法 • 在散列算法中使用salt 用户名仍是Oracle 标识…

【JavaEE】Spring Boot - 日志文件

【JavaEE】Spring Boot 开发要点总结(3) 文章目录 【JavaEE】Spring Boot 开发要点总结(3)1. 日志有什么作用2. 日志格式2.1 日志框架原理 3. 日志的打印3.1 System.out.println3.2 使用日志框架3.3 日志级别3.3.1 设置默认日志显…

深度学习(36)—— 图神经网络GNN(1)

深度学习(36)—— 图神经网络GNN(1) 这个系列的所有代码我都会放在git上,欢迎造访 文章目录 深度学习(36)—— 图神经网络GNN(1)1. 基础知识2.使用场景3. 图卷积神经网…