[Leetcode]用栈实现队列

devtools/2024/9/23 6:37:53/

用栈实现队列:

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

1.题解:

通过两个栈的配合实现队列的基本功能,下面先实现栈的基本功能

栈: (前面文章介绍过栈的实现,这里就不过多阐述)

typedef int StackDataType;
typedef struct Stack {StackDataType* head;int capacity;int size;
}Stack;
//创建栈
Stack* StackCreate() {Stack* tmp = (Stack*)malloc(sizeof(Stack));tmp->head = NULL;tmp->capacity = tmp->size = 0;return tmp;
}
//入栈
void StackPush(Stack*tmp,StackDataType x) {if (tmp->capacity == tmp->size) {int newcapacity = tmp->capacity == 0 ? 4 : 2 * tmp->capacity;StackDataType* cur = (StackDataType*)realloc(tmp->head, newcapacity * sizeof(StackDataType));if (cur == NULL) {perror("StackPush:malloc");exit;}tmp->head = cur;tmp->capacity = newcapacity;}tmp->head[tmp->size] = x;tmp->size++;
}
//出栈
StackDataType StackPop(Stack*tmp) {if (tmp->size == 0) {perror("StackPop:NULL");exit;}StackDataType s = tmp->head[tmp->size - 1];tmp->size--;return s;
}
//栈的销毁
void StackDestroy(Stack*tmp) {free(tmp->head);tmp->head = NULL;tmp->capacity = tmp->size = 0;free(tmp);tmp = NULL;
}

2.基于栈实现队列基本功能:

入队列:

根据上图思路,一个栈(stack1)存储数据,一个栈(stack2)出数据。

void myQueuePush(MyQueue* obj, int x) {assert(obj);StackPush(obj->stack1, x);
}
出队列:

出队列就涉及到判断出数据的那个栈(stack2)是否有数据(栈判空(StackEmpty))

int myQueuePop(MyQueue* obj) {assert(obj);if (obj->stack2->size == 0) {while (obj->stack1->size != 0) {StackPush(obj->stack2, StackPop(obj->stack1));}}return StackPop(obj->stack2);
}
返回队列顶部元素:

同样涉及判空问题,因为该功能仅和出队列少了最后删除元素

int myQueuePeek(MyQueue* obj) {assert(obj);if (obj->stack2->size == 0) {if (obj->stack1->size == 0) {perror("Peek:NULL");exit;}return obj->stack1->head[0];}return obj->stack2->head[obj->stack2->size - 1];
}
 判空:

stack1与stack2均为空

bool myQueueEmpty(MyQueue* obj) {assert(obj);return obj->stack1->size == 0 && obj->stack2->size == 0;
}

 3.完整代码:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int StackDataType;
typedef struct Stack {StackDataType* head;int capacity;int size;
}Stack;
Stack* StackCreate() {Stack* tmp = (Stack*)malloc(sizeof(Stack));tmp->head = NULL;tmp->capacity = tmp->size = 0;return tmp;
}
void StackPush(Stack*tmp,StackDataType x) {if (tmp->capacity == tmp->size) {int newcapacity = tmp->capacity == 0 ? 4 : 2 * tmp->capacity;StackDataType* cur = (StackDataType*)realloc(tmp->head, newcapacity * sizeof(StackDataType));if (cur == NULL) {perror("StackPush:malloc");exit;}tmp->head = cur;tmp->capacity = newcapacity;}tmp->head[tmp->size] = x;tmp->size++;
}
StackDataType StackPop(Stack*tmp) {if (tmp->size == 0) {perror("StackPop:NULL");exit;}StackDataType s = tmp->head[tmp->size - 1];tmp->size--;return s;
}
void StackDestroy(Stack*tmp) {free(tmp->head);tmp->head = NULL;tmp->capacity = tmp->size = 0;free(tmp);tmp = NULL;
}
typedef struct Queue{Stack* stack1;Stack* stack2;
}MyQueue;MyQueue* myQueueCreate() {MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue));queue->stack1 = StackCreate();queue->stack2 = StackCreate();return queue;
}void myQueuePush(MyQueue* obj, int x) {assert(obj);StackPush(obj->stack1, x);
}int myQueuePop(MyQueue* obj) {assert(obj);if (obj->stack2->size == 0) {while (obj->stack1->size != 0) {StackPush(obj->stack2, StackPop(obj->stack1));}}return StackPop(obj->stack2);
}int myQueuePeek(MyQueue* obj) {assert(obj);if (obj->stack2->size == 0) {if (obj->stack1->size == 0) {perror("Peek:NULL");exit;}return obj->stack1->head[0];}return obj->stack2->head[obj->stack2->size - 1];
}bool myQueueEmpty(MyQueue* obj) {assert(obj);return obj->stack1->size == 0 && obj->stack2->size == 0;
}


http://www.ppmy.cn/devtools/7117.html

相关文章

数据结构与算法:常用的启发式算法

在数据结构的领域中&#xff0c;启发式算法是一类用于解决优化问题的算法&#xff0c;它们在每一步选择中都做出当前看来最好的选择&#xff0c;但并不保证总能找到全局最优解。这类算法广泛应用于资源分配、路径规划、存储分配等问题。以下是一些常用的启发式算法及其区别&…

ardunio中自定义的库文件

1、Arduino的扩展库都是放在 libraries目录下的。完整路径为&#xff1a;C:\Users\41861\AppData\Local\Arduino15\libraries 所以我们需要在这个目录下创建一个文件夹&#xff0c;比如上面的例子是esp32上led灯控制程序&#xff0c;于是我创建了 m_led文件夹&#xff08;前面加…

Lua脚本使用手册(Redis篇)

Lua脚本 **简介&#xff1a;**Lua是一种功能强大的&#xff0c;高效&#xff0c;轻量级&#xff0c;可嵌入的脚本语言。它是动态类型语言&#xff0c;通过使用基于寄存器的虚拟机解释字节码运行&#xff0c;并具有增量垃圾收集的自动内存管理&#xff0c;是配置&#xff0c;脚…

HEF4046BT功能参数及避免使用的场景、应用前置放大器

制造商:NXP 产品种类:锁相环 PLL 类型:PLL 电路数量:1 电源电压 最大:15 V 电源电压 最小:3 V 最大工作温度: 85 C 安装风格:SMD/SMT 封装:SO-16 封装:Bulk 商标:NXP Semiconductors 最小工作温度:- 40 C 工作电源电压:3.3 V, 5 V, 9 V, 12 V HEF4046BT 是一种 CMO…

SpringCloud之LoadBalancer负载均衡器的简单使用

SpringCloud之LoadBalancer负载均衡器的简单使用 loadbalancer用于对提供服务的集群做一个节点的选取规则。 如图所示&#xff0c;load balancer集成在调用方 示例 创建loadbalance-base模块,并引入相关依赖 <dependencies><dependency><groupId>org.spr…

免费泛域名SSL如何申请,和通配符有什么区别

-----让我们明确什么是泛域名。所谓泛域名&#xff0c;是指使用星号&#xff08;*&#xff09;作为子域名的占位符&#xff0c;它可以匹配任意子域名。-----而通配符在域名中&#xff0c;它可以出现在主域名的任何位置&#xff0c;它可以用于主域名和子域名的保护。 主要应用场…

OpenHarmony 网络管理-Socket连接

介绍 本示例主要演示了Socket在网络通信方面的应用&#xff0c;展示了Socket在两端设备的连接验证、聊天通信方面的应用。 效果预览 使用说明 1.搭建服务器环境&#xff1a;修改服务器脚本中的服务端IP地址&#xff0c;与本机IP地址保持一致&#xff0c;修改完成后双击运行脚…

Spring MVC 国际化

文章目录 国际化基本概念指明&#xff08;并加载&#xff09;资源文件获得 Locale 对象AcceptHeaderLocaleResolverSessionLocaleResolverCookieLocaleResolver 修改 Locale 信息非常规办法常规办法&#xff1a; LocaleChangeInterceptor 拦截器 国际化 基本概念 国际化 是开…