LeetCode 232: 用栈实现队列

news2025/3/16 7:33:36

LeetCode 232: 用栈实现队列

题目描述

使用栈实现队列的操作。支持以下操作:

  1. MyQueue():初始化队列。
  2. push(x):将元素 x 推入队列。
  3. pop():从队列中移除元素。
  4. peek():返回队列头部的元素。
  5. empty():检查队列是否为空。

队列的先进先出(FIFO)原则可以通过两个栈来模拟。栈 A 用于入队操作,栈 B 用于出队操作。

C 语言实现

#include <stdio.h>
#include <stdlib.h>

// 定义栈结构体
typedef struct {
    int* data;
    int top;
    int capacity;
} Stack;

// 初始化栈
Stack* stackCreate(int capacity) {
    Stack* stack = (Stack*)malloc(sizeof(Stack));
    stack->data = (int*)malloc(sizeof(int) * capacity);
    stack->top = -1;
    stack->capacity = capacity;
    return stack;
}

// 检查栈是否为空
int stackIsEmpty(Stack* stack) {
    return stack->top == -1;
}

// 入栈操作
void stackPush(Stack* stack, int x) {
    stack->data[++stack->top] = x;
}

// 出栈操作
int stackPop(Stack* stack) {
    return stack->data[stack->top--];
}

// 获取栈顶元素
int stackTop(Stack* stack) {
    return stack->data[stack->top];
}

// 释放栈内存
void stackFree(Stack* stack) {
    free(stack->data);
    free(stack);
}

// 定义队列结构体
typedef struct {
    Stack* stackA;
    Stack* stackB;
} MyQueue;

// 初始化队列
MyQueue* myQueueCreate() {
    MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue));
    queue->stackA = stackCreate(100); // 栈 A 的初始容量
    queue->stackB = stackCreate(100); // 栈 B 的初始容量
    return queue;
}

// 入队操作
void myQueuePush(MyQueue* obj, int x) {
    stackPush(obj->stackA, x);  // 将元素推入栈 A
}

// 出队操作
int myQueuePop(MyQueue* obj) {
    if (stackIsEmpty(obj->stackB)) {  // 如果栈 B 为空
        while (!stackIsEmpty(obj->stackA)) {  // 将栈 A 中的元素全部移到栈 B
            stackPush(obj->stackB, stackPop(obj->stackA));
        }
    }
    return stackPop(obj->stackB);  // 从栈 B 出栈
}

// 获取队列头部元素
int myQueuePeek(MyQueue* obj) {
    if (stackIsEmpty(obj->stackB)) {  // 如果栈 B 为空
        while (!stackIsEmpty(obj->stackA)) {  // 将栈 A 中的元素全部移到栈 B
            stackPush(obj->stackB, stackPop(obj->stackA));
        }
    }
    return stackTop(obj->stackB);  // 返回栈 B 顶部元素
}

// 检查队列是否为空
int myQueueEmpty(MyQueue* obj) {
    return stackIsEmpty(obj->stackA) && stackIsEmpty(obj->stackB);  // 栈 A 和栈 B 都为空时队列为空
}

// 释放队列内存
void myQueueFree(MyQueue* obj) {
    stackFree(obj->stackA);
    stackFree(obj->stackB);
    free(obj);
}

// 测试主函数
int main() {
    MyQueue* queue = myQueueCreate();
    
    myQueuePush(queue, 1);
    myQueuePush(queue, 2);
    printf("peek: %d\n", myQueuePeek(queue));  // 应输出 1
    printf("pop: %d\n", myQueuePop(queue));   // 应输出 1
    printf("empty: %d\n", myQueueEmpty(queue));  // 应输出 0

    myQueuePush(queue, 3);
    printf("peek: %d\n", myQueuePeek(queue));  // 应输出 2
    printf("pop: %d\n", myQueuePop(queue));   // 应输出 2
    printf("pop: %d\n", myQueuePop(queue));   // 应输出 3
    printf("empty: %d\n", myQueueEmpty(queue));  // 应输出 1

    myQueueFree(queue);
    return 0;
}

代码逐行解释

栈的实现

typedef struct {
    int* data;
    int top;
    int capacity;
} Stack;

我们首先定义了一个 Stack 结构体,包含了三个成员:

  • data:存储栈元素的数组。
  • top:栈顶元素的索引。
  • capacity:栈的最大容量。
Stack* stackCreate(int capacity) {
    Stack* stack = (Stack*)malloc(sizeof(Stack));
    stack->data = (int*)malloc(sizeof(int) * capacity);
    stack->top = -1;
    stack->capacity = capacity;
    return stack;
}

stackCreate 用来初始化一个栈,分配内存并设置初始值。

int stackIsEmpty(Stack* stack) {
    return stack->top == -1;
}

stackIsEmpty 用于检查栈是否为空,栈空时返回 1

void stackPush(Stack* stack, int x) {
    stack->data[++stack->top] = x;
}

stackPush 用于将元素推入栈中,top 先自增再将元素存入。

int stackPop(Stack* stack) {
    return stack->data[stack->top--];
}

stackPop 用于从栈中弹出元素,并返回弹出的元素。

int stackTop(Stack* stack) {
    return stack->data[stack->top];
}

stackTop 用于获取栈顶元素,但不删除它。

队列的实现

typedef struct {
    Stack* stackA;
    Stack* stackB;
} MyQueue;

我们定义了一个 MyQueue 结构体,它包含两个栈:

  • stackA 用于存储入队元素。
  • stackB 用于存储出队元素。
MyQueue* myQueueCreate() {
    MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue));
    queue->stackA = stackCreate(100); 
    queue->stackB = stackCreate(100); 
    return queue;
}

myQueueCreate 用于创建一个队列并初始化其中的两个栈。

void myQueuePush(MyQueue* obj, int x) {
    stackPush(obj->stackA, x);  
}

myQueuePush 将元素压入 stackA

int myQueuePop(MyQueue* obj) {
    if (stackIsEmpty(obj->stackB)) {
        while (!stackIsEmpty(obj->stackA)) {
            stackPush(obj->stackB, stackPop(obj->stackA));
        }
    }
    return stackPop(obj->stackB);
}

myQueuePop 用于从队列中弹出元素。首先检查 stackB 是否为空,如果为空,则将 stackA 中的所有元素转移到 stackB 中。然后从 stackB 弹出栈顶元素。

int myQueuePeek(MyQueue* obj) {
    if (stackIsEmpty(obj->stackB)) {
        while (!stackIsEmpty(obj->stackA)) {
            stackPush(obj->stackB, stackPop(obj->stackA));
        }
    }
    return stackTop(obj->stackB);
}

myQueuePeek 用于获取队列头部的元素,逻辑与 myQueuePop 相同,只不过不移除元素。

int myQueueEmpty(MyQueue* obj) {
    return stackIsEmpty(obj->stackA) && stackIsEmpty(obj->stackB);
}

myQueueEmpty 检查队列是否为空,只有当 stackAstackB 都为空时,队列才为空。

void myQueueFree(MyQueue* obj) {
    stackFree(obj->stackA);
    stackFree(obj->stackB);
    free(obj);
}

myQueueFree 用于释放队列及其内部栈的内存。

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

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

相关文章

从ARM官方获取自己想要的gcc交叉编译工具链接(Arm GNU Toolchain),并在Ubuntu系统中进行配置

前言 本文是博文 https://blog.csdn.net/wenhao_ir/article/details/145547974 的分支博文。 在本博文中我们完成gcc交叉编译工具gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf.tar.xz的下载、配置、测试。 下载自己想要的gcc交叉编译工具的源码 目标文件的名字及说…

【系统架构设计师】虚拟机体系结构风格

目录 1. 说明2. 解释器体系结构风格3. 规则系统体系结构风格4. 例题4.1 例题1 1. 说明 1.p263。2.虚拟机体系结构风格的基本思想是人为构建一个运行环境&#xff0c;在这个环境之上&#xff0c;可以解析与运行自定义的一些语言&#xff0c;这样来增加架构的灵活性。3.虚拟机体…

Python 字典思维导图

在本章中&#xff0c;你将学习能够将相关信息关联起来的Python字典。你将学习如何访问和修改字典中的信息。鉴于字典可存储的信息量几乎不受限制&#xff0c;因此我们会演示如何遍 历字典中的数据。另外&#xff0c;你还将学习存储字典的列表、存储列表的字典和存储字典的字典。…

前台、后台、守护进程对比,进程组的相关函数

前台进程&#xff0c;后台进程&#xff0c;守护进程的对比 在前面我们已经了解了前台进程&#xff0c;后台进程&#xff0c;守护进程。 直接在终端中输入命令&#xff1a; 这是最常见的启动前台进程的方式。例如&#xff0c;在终端中输入 ./myprogram 就可以启动 myprogram 程…

openAI最新o1模型 推理能力上表现出色 准确性方面提升 API如何接入?

OpenAI o1模型在回答问题前会进行深入思考&#xff0c;并生成一条内部推理链&#xff0c;使其在尝试解决问题时可以识别并纠正错误&#xff0c;将复杂的步骤分解为更简单的部分&#xff0c;并在当前方法无效时尝试不同的途径。据悉&#xff0c;o1不仅数学水平与美国奥林匹克竞赛…

跨平台键鼠共享免费方案--Deskflow!流畅体验用MacBook高效控制Windows设备

在混合办公场景中&#xff0c;多设备协同已成为提升效率的关键需求。对于同时使用Mac与Windows设备的用户&#xff0c;如何通过一套键盘和触控板实现无缝切换&#xff0c;避免桌面空间浪费与操作冗余&#xff1f;本文将基于开源工具Deskflow&#xff0c;提供一套专业级解决方案…

CAS单点登录(第7版)27.开发人员

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 开发人员 Javadocs文档 group org.apereo.cas has published 42 artifact(s) with total 8210 version(s) org.apereo.cas org apereo.cas 小组已出版 42 件作品&#xff0c;共 8210 个版…

算法与数据结构(多数元素)

题目 思路 方法一&#xff1a;哈希表 因为要求出现次数最多的元素&#xff0c;所以我们可以使用哈希映射存储每个元素及其出现的次数。每次记录出现的次数若比最大次数大&#xff0c;则替换。 方法二&#xff1a;摩尔算法 摩尔的核心算法就是对抗&#xff0c;因为存在次数多…

【2.10-2.16学习周报】

文章目录 摘要Abstract一、理论方法介绍1.模糊类增量学习2.Rainbow Memory(RM)2.1多样性感知内存更新2.2通过数据增强增强样本多样性(DA) 二、实验1.实验概况2.RM核心代码3.实验结果 总结 摘要 本博客概述了文章《Rainbow Memory: Continual Learning with a Memory of Divers…

python包的管理

管理python包 python能跻身最欢迎编程语言前列的一个主要原因是python有着活跃的社区提供丰富的包&#xff0c;诸如numpy&#xff0c;pandas&#xff0c;scikit-learn等等。 python的包都存放PyPI中&#xff0c;PyPI即Python Package Index&#xff0c;是python的软件仓库。所…

我用 Cursor 开发了一款个人小记系统

https://note.iiter.cn 项目背景 在日常工作和学习中,我们经常需要快速记录一些想法、收藏一些有用的链接或者保存一些重要的文本、图片内容。虽然市面上已经有很多笔记软件,但我想要一个更轻量、更简单的工具,专注于快速记录和智能检索。于是我开发了这款个人小记系统。 系统…

安全测试中的身份认证与访问控制深度解析

第一部分:基本概念与核心问题 1. 身份认证与访问控制基础 1.1 身份认证三要素 知识因素(密码、PIN码)持有因素(硬件令牌、手机)生物因素(指纹、面部识别)1.2 访问控制模型 DAC(自主访问控制)MAC(强制访问控制)RBAC(基于角色的访问控制)2. 关键安全机制 2.1 会话…

代码随想录-训练营-day30

今天我们要进入动态规划的背包问题&#xff0c;背包问题也是一类经典问题了。总的来说可以分为&#xff1a; 今天让我们先来复习0-1背包的题目&#xff0c;这也是所有背包问题的基础。所谓的0-1背包问题一般来说就是给一个背包带有最大容量&#xff0c;然后给一个物体对应的需要…

全平台搭载旭日5!科沃斯GOAT智能割草机器人全新系列正式开售

要闻 近日&#xff0c;科沃斯全新发布的GOAT A Series 和 GOAT O Series割草机器人&#xff0c;将在多国市场正式上市发售。作为业界最强的割草机器人产品之一&#xff0c;GOAT致力为割草机带来基于机器人视觉的专业定位解决方案。科沃斯GOAT全新系列产品全平台搭载地瓜机器人…

自定义组件数据监听器案例,纯数据字段,自定义组件生命周期,页面的生命周期,插槽

1.自定义组件数据监听器案例 1.1基础案例模板 1.2定义button事件的处理函数 1.3监听对象中属性的变化&#xff0c;并且为fullColor赋值 使用通配符监听所有属性变化 2.自定义组件的纯数据字段 、 3.自定义组件的生命周期 4.组件所在页面的生命周期 5.自定义组件插槽 5.1单个插…

mybatis-lombok工具包介绍

Lombok是一个实用的]ava类库&#xff0c;能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法&#xff0c;并可以自动化生成日志变量&#xff0c;简化java开发、提高效率。 使用前要加入Lombok依赖

LDO技术:线性调整率与负载调整率全解析

LDO(Low Dropout Regulator)低压差线性稳压器&#xff0c;其结构比较简单、纹波和噪声比DCDC小、成本也优于DCDC&#xff0c;缺点是在输入电压和输出电压的压差比较大时&#xff0c;效率低些&#xff0c;但在小电流电源电路上被广泛使用。现在输入电压和输出电压的压差可做到10…

SpringBoot 集成 Caffeine 实现本地缓存

目录 1、Caffeine 简介 1.1、Caffeine 简介1.2、对比 Guava cache 的性能主要优化项1.3、常见的缓存淘汰算法1.4、SpringBoot 集成 Caffeine 两种方式 2、SpringBoot 集成 Caffeine 方式一 2.1、缓存加载策略 2.1.1、手动加载2.1.2、自动加载【Loading Cache】2.1.3、异步加载…

使用EVE-NE-锐捷实现NAT+ACL服务限制

一、项目拓扑 二、项目实现 1.NET配置 点击左侧的NetWorks,设置与图相同的配置&#xff0c;实现实验环境桥接到物理网络 2.GW配置 进入特权模式 enable进入全局模式 configure terminal 更改名称为GW hostname GW进入g0/0接口 interface g0/0将g0/0接口IP地址配置为192.168.…

大模型训练为什么依赖GPU

近年来&#xff0c;随着人工智能技术的飞速发展&#xff0c;特别是深度学习领域的进步&#xff0c;大模型的训练逐渐成为研究和工业界的热点。作为大模型训练中的核心硬件&#xff0c;GPU&#xff08;图形处理单元&#xff09;扮演了至关重要的角色。那么&#xff0c;为什么大模…