栈和队列oj题——232. 用栈实现队列

在这里插入图片描述在这里插入图片描述

.

个人主页:晓风飞
专栏:LeetCode刷题|数据结构|Linux|C语言
路漫漫其修远兮,吾将上下而求索


文章目录

  • 题目要求:
    • 实现 MyStack 类:
    • 注意:
    • 示例:
    • 解释:
    • 提示:
  • 解题核心概念
  • 数据结构的定义
  • 初始化队列
  • 入队操作
  • 出队操作
  • 查看队列前端元素
  • 检查队列是否为空
  • 释放队列


要做题目的点击这里–>栈和队列oj题——232. 用栈实现队列

题目要求:

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

实现 MyStack 类:

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

注意:

你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 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 次 push、pop、top 和 empty
每次调用 pop 和 top 都保证栈不为空

进阶:你能否仅用一个队列来实现栈。
在这里插入图片描述

解题核心概念

在我们的实现中,我们定义了两个栈 s1 和 s2。栈 s1 负责处理入队操作,而栈 s2 负责出队操作。通过这种方式,我们可以保证队列的 FIFO 特性,即首先入队的元素将首先出队。

数据结构的定义

首先,我们定义了栈的结构体 ST,它包含一个指向数组的指针、一个表示栈顶的变量和一个表示栈容量的变量。然后,我们定义了队列的结构体 MyQueue,它包含两个栈 s1 和 s2。

// 使用两个栈实现的队列结构体定义
typedef struct 
{ST s1; // 第一个栈,用于入队操作ST s2; // 第二个栈,用于出队操作
} MyQueue;

初始化队列

使用 myQueueCreate 函数来初始化队列。在这个函数中,我们分配内存给 MyQueue 结构体,并初始化两个栈。

MyQueue* myQueueCreate() 
{MyQueue* newQu = (MyQueue*)malloc(sizeof(MyQueue));STInit(&newQu->s1); // 初始化第一个栈STInit(&newQu->s2); // 初始化第二个栈    return newQu; // 返回新创建的队列
}

入队操作

入队操作非常简单:我们只需将元素推入栈 s1。

// 将一个元素推入队列
void myQueuePush(MyQueue* obj, int x) 
{STPush(&obj->s1, x); // 将元素推入第一个栈
}

出队操作

出队操作稍微复杂一些。我们需要确保队列的 FIFO 性质,所以当我们想要进行出队操作时,我们首先检查栈 s2。如果栈 s2 为空,我们将栈 s1 中的所有元素逆序转移到栈 s2 中,然后从栈 s2 中弹出元素。

// 如有必要,将元素从第一个栈转移到第二个栈
void TransferIfNeeded(MyQueue* obj) 
{if (STEmpty(&obj->s2)) // 检查第二个栈是否为空{while (!STEmpty(&obj->s1)) // 当第一个栈不为空时{// 将第一个栈的栈顶元素转移到第二个栈STPush(&obj->s2, STTop(&obj->s1));STPop(&obj->s1); // 弹出第一个栈的栈顶元素}}
}// 从队列中弹出一个元素
int myQueuePop(MyQueue* obj) 
{TransferIfNeeded(obj); // 确保所有元素都在第二个栈int Top = STTop(&obj->s2); // 获取第二个栈的栈顶元素STPop(&obj->s2); // 弹出第二个栈的栈顶元素return Top; // 返回弹出的元素
}

查看队列前端元素

查看队列前端元素的实现与出队操作类似,但不移除元素。

// 查看队列的前端元素
int myQueuePeek(MyQueue* obj) 
{TransferIfNeeded(obj); // 确保所有元素都在第二个栈return STTop(&obj->s2); // 返回第二个栈的栈顶元素
}

检查队列是否为空

队列为空的条件是两个栈都为空。

// 检查队列是否为空
bool myQueueEmpty(MyQueue* obj) 
{// 如果两个栈都为空,那么队列为空return STEmpty(&obj->s1) && STEmpty(&obj->s2);   
}

释放队列

最后,我们需要一个函数来释放队列占用的资源。

// 释放队列所占用的资源
void myQueueFree(MyQueue* obj) 
{STDestroy(&obj->s1); // 销毁第一个栈STDestroy(&obj->s2); // 销毁第二个栈free(obj); // 释放队列结构体占用的内存   
}

以下是栈的实现:

typedef int STDataType;
typedef struct Stack
{STDataType* a;STDataType top; STDataType capacity;
}ST;void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst,STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);// 初始化栈
void STInit(ST* pst)
{assert(pst);pst->a = NULL;       // 初始时,数组指针为空pst->top = 0;        // 栈顶指针初始为0,表示栈为空pst->capacity = 0;   // 初始容量为0
}// 销毁栈
void STDestroy(ST* pst)
{assert(pst);free(pst->a);        // 释放栈内部的数组空间pst->a = NULL;       // 将数组指针置为空pst->top = 0;        // 栈顶指针重置为0pst->capacity = 0;   // 容量重置为0
}// 检查并扩展栈的容量
void SLCheckCapacity(ST* pst)
{assert(pst);if (pst->top == pst->capacity){int newCapacity = (pst->capacity == 0) ? 4 : pst->capacity * 2;STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newCapacity);if (tmp == NULL){perror("realloc fail");exit(1); // 如果内存分配失败,则退出程序}pst->a = tmp;pst->capacity = newCapacity;}
}// 向栈中推入一个元素
void STPush(ST* pst, STDataType x)
{assert(pst);SLCheckCapacity(pst); // 检查并扩展容量pst->a[pst->top] = x; // 存放元素pst->top++;           // 栈顶指针增加
}// 从栈中弹出一个元素
void STPop(ST* pst)
{assert(pst);assert(pst->top > 0); // 确保栈不为空pst->top--;           // 栈顶指针减少
}// 获取栈顶元素
STDataType STTop(ST* pst)
{assert(pst);assert(pst->top > 0); // 确保栈不为空return pst->a[pst->top - 1]; // 返回栈顶元素
}// 检查栈是否为空
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0; // 如果栈顶指针为0,则栈为空
}// 获取栈的大小
int STSize(ST* pst)
{assert(pst);return pst->top; // 返回栈顶指针的位置,即栈的大小
}

以下是本题的实现:

   
// 使用两个栈实现的队列结构体定义
typedef struct 
{ST s1; // 第一个栈,用于入队操作ST s2; // 第二个栈,用于出队操作
} MyQueue;// 创建并初始化队列
MyQueue* myQueueCreate() 
{MyQueue* newQu = (MyQueue*)malloc(sizeof(MyQueue));STInit(&newQu->s1); // 初始化第一个栈STInit(&newQu->s2); // 初始化第二个栈    return newQu; // 返回新创建的队列
}// 将一个元素推入队列
void myQueuePush(MyQueue* obj, int x) 
{STPush(&obj->s1, x); // 将元素推入第一个栈
}// 如有必要,将元素从第一个栈转移到第二个栈
void TransferIfNeeded(MyQueue* obj) 
{if (STEmpty(&obj->s2)) // 检查第二个栈是否为空{while (!STEmpty(&obj->s1)) // 当第一个栈不为空时{// 将第一个栈的栈顶元素转移到第二个栈STPush(&obj->s2, STTop(&obj->s1));STPop(&obj->s1); // 弹出第一个栈的栈顶元素}}
}// 从队列中弹出一个元素
int myQueuePop(MyQueue* obj) 
{TransferIfNeeded(obj); // 确保所有元素都在第二个栈int Top = STTop(&obj->s2); // 获取第二个栈的栈顶元素STPop(&obj->s2); // 弹出第二个栈的栈顶元素return Top; // 返回弹出的元素
}// 查看队列的前端元素
int myQueuePeek(MyQueue* obj) 
{TransferIfNeeded(obj); // 确保所有元素都在第二个栈return STTop(&obj->s2); // 返回第二个栈的栈顶元素
}// 检查队列是否为空
bool myQueueEmpty(MyQueue* obj) 
{// 如果两个栈都为空,那么队列为空return STEmpty(&obj->s1) && STEmpty(&obj->s2);   
}// 释放队列所占用的资源
void myQueueFree(MyQueue* obj) 
{STDestroy(&obj->s1); // 销毁第一个栈STDestroy(&obj->s2); // 销毁第二个栈free(obj); // 释放队列结构体占用的内存   
}
/*** Your MyQueue struct will be instantiated and called as such:* MyQueue* obj = myQueueCreate();* myQueuePush(obj, x);* int param_2 = myQueuePop(obj);* int param_3 = myQueuePeek(obj);* bool param_4 = myQueueEmpty(obj);* myQueueFree(obj);
*/

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

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

相关文章

LeetCode刷题---矩阵置零

解题思路&#xff1a; 本题要求原地置换元素 对矩阵进行第一轮遍历&#xff0c;使用第一行第一列来充当该行该列是否要置换为0的标记位&#xff0c;如果第一行或第一列本身就含有零元素&#xff0c;我们使用colZero和rowZero变量来对其标记。如果第i行第j列的那个元素为0&#…

how2heap-2.23-02-fastbin_dup_into_stack

fastbin_dup_into_stack和fastbin_dup没啥区别 https://blog.csdn.net/u014679440/article/details/135383465 仅仅是欲修改的位置&#xff0c;在栈中 #include <stdio.h> #include <stdlib.h>int main() {fprintf(stderr, "This file extends on fastbin_du…

leetcode13 罗马数字转整数

题目描述&#xff1a;罗马数字由七种字符组成&#xff0c;分别为 I、V、X、L、C、D 和 M&#xff0c;对应的数值分别为 1、5、10、50、100、500 和 1000。在一般情况下&#xff0c;小的数字位于大的数字右边&#xff0c;但有特殊情况&#xff0c;如 IV 表示 4&#xff0c;IX 表…

单线圈无刷直流电机驱动芯片选型分析,可应用于笔记本,显卡风散热风扇,变频冷却风扇,打印机风扇等产品上

单线圈无刷直流电机的电机驱动器。 GC1298R/S&#xff0c;GC1262E/S&#xff0c;GC1298R/S&#xff0c;GC1262R/S具有高效的直接PWM控制方式&#xff0c;它可以控制无刷直流电机转速。它集成了最低速度限制模式、可调速度斜率控制模式、软启动模式、风扇转速计、锁保护、自动重…

《剑指offer》数学第一题:数值的整数次方

题目描述&#xff1a; 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 思路&#xff1a; 给定一个浮点数求它的整数次方。要考虑到所有的情况&#xff0c;关于指数&#xff0c;如果是0&#xff0c;则结果是1&#xff1b; 指数是1&#xff0c…

CNN——AlexNet

1.AlexNet概述 论文原文&#xff1a;ImageNet Classification with Deep Convolutional Neural Networks 在LeNet提出后&#xff0c;卷积神经网络在计算机视觉和机器学习领域中很有名气。但卷积神经网络并没有主导这些领域。这是因为虽然LeNet在小数据集上取得了很好的效果&am…

C#: Label、TextBox 鼠标停留时显示提示信息

说明&#xff1a;记录在 Label、TextBox 控件上 鼠标停留时显示提示信息的方法。 1.效果图 2.具体实现步骤 1. 在Form 窗口中先创建 Label 并取名&#xff1a;KEY_label &#xff0c;或 TextBox 取名&#xff1a;KEY_textBox 在 Form1 函数中添加初始化代码&#xff0c;如下&…

ssm基于web的素材网的设计与实现+vue论文

基于web的素材网站的设计与实现 摘要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。传统的素材信息管理模式&#xff0c;采用人工登记的方式保存相关数据&#xff0c;这种以人力为主的管理…

C#中使用 async await TaskCompletionSource<T>实现异步逻辑同步写

Task、async 和 await 是 C# 中用于处理异步编程的关键概念。它们一起构成了异步编程的基础。 Task Task 是表示异步操作的抽象&#xff0c;它属于 System.Threading.Tasks 命名空间。Task 可以表示已经完成的任务、正在运行的任务或者尚未开始的任务。通过 Task&#xff0c;…

你的第一个C/S程序

目录 socket服务端代码客户端代码执行结果 socket socket基础知识 服务端代码 import socket import threading import timeMSG_LENGTH 64 DISCONNECTED !CONNECTION CLOSED connections 0#定义服务器地址 server_ip socket.gethostbyname(socket.gethostname()) server…

【设计模式之美】面向对象分析方法论与实现(二):需求到接口实现的方法论

文章目录 一. 进行面向对象设计1. 划分职责>需要有哪些类2. 定义类及其属性和方法3. 定义类与类之间的交互关系4. 将类组装起来并提供执行入口 二. 如何进行面向对象编程&#xff1f;1. 接口实现2. 辩证思考与灵活应用 【设计模式之美】面向对象分析方法论与实现&#xff08…

教育场景数字化中音视频小程序的发展

教育场景数字化逐步成为刚需 2018年以来&#xff0c;国家对在线教育行业的监管收紧&#xff0c;以及受益于 5G 技术的发展&#xff0c;教育科技逐步走向成熟化和规范化。 教育行业的本质是人与人&#xff08;老师与学生、老师与家长&#xff0c;以及更多角色直接的沟通与互动…

【数据结构和算法】小行星碰撞

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 什么情况会用到栈 2.2 方法一&#xff1a;模拟 栈 三、代码 3.1 方法一&#xff1a;模拟 栈 四…

【LLM+RS】LLM在推荐系统的实践应用(华为诺亚)

note LLM用于推荐主要还是解决推荐系统加入open domain 的知识。可以基于具体推荐场景数据做SFT。学习华为诺亚-技术分享-LLM在推荐系统的实践应用。 文章目录 note一、背景和问题二、推荐系统中哪里使用LLM1. 特征工程2. 特征编码3. 打分排序 三、推荐系统中如何使用LLM四、挑…

共享WiFi贴项目加盟可以解决商家哪些痛点?

近年来&#xff0c;共享WiFi贴项目在共享商业领域引起了广泛关注。作为一种便捷的网络分享工具&#xff0c;共享WiFi贴不仅受到很多人的青睐&#xff0c;更能够为商家带来诸多实际利益。那么&#xff0c;共享WiFi贴项目加盟究竟可以解决商家哪些痛点呢&#xff1f; 共享WiFi贴为…

【C#】知识点实践序列之Lock的锁定代码块

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂之知识点实践序列》文章。 2024年第1篇文章&#xff0c;此篇文章是C#知识点实践序列之Lock知识点&#xff0c;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 本篇验证Lock锁定代…

Navicat(数据库可视化软件)安装教程以及连接MYSQL

Navicat安装教程以及连接MYSQL Navicat&#xff08;数据库可视化软件&#xff09;安装流程安装MySQLnavicat连接mysql数据库 Navicat&#xff08;数据库可视化软件&#xff09; Navicat 是一款专门为 MySQL 设计的可视化数据库 GUI 管理工具&#xff0c;我们可以在自己的计算机…

深入浅出Python日志打印

0.引言 在编程过程中&#xff0c;日志记录是一项非常重要的任务&#xff0c;无论是用于调试代码、记录系统运行状态&#xff0c;还是跟踪可能出现的问题&#xff0c;日志都能发挥重要作用。然而&#xff0c;许多开发者习惯使用简单的print语句来记录信息&#xff0c;这种方法虽…

ensp vlan连接(详细)

1.将需要的设备放置好 2.将设备连接起来 3.启动所有设备 4.备注好每台PC机的信息 5.配置好每台PC机 6.配置交换机1 进入配置视图&#xff0c;关闭信息提示 重命名设备 批量创建VLAN 开始配置接口 更改接口类型为ACCESS 将接口划分到对应的VLANN 配置下一个接口&#xff0c;步…

编译 nccl-tests 项目

1&#xff0c;编译 下载源代码 git clone --recursive https://github.com/NVIDIA/nccl-tests.git 编译源代码 cd nccl-tests/ make -j 2&#xff0c;运行 cd ./build/ ./all_reduce_perf --help ./all_reduce_perf -b 8 -e 256M -f 2 -g 4 效果图&#xff1a; 3&#…