[数据结构]OJ用队列实现栈

225. 用队列实现栈 - 力扣(LeetCode)

官方题解:https://leetcode.cn/problems/implement-stack-using-queues/solutions/432204/yong-dui-lie-shi-xian-zhan-by-leetcode-solution/

首先我们要知道

栈是一种后进先出的数据结构,元素从顶端入栈,然后从顶端出栈。

队列是一种先进先出的数据结构,元素从后端入队,然后从前端出队。

这题要求:

typedef struct {} MyStack;MyStack* myStackCreate() {}void myStackPush(MyStack* obj, int x) {}int myStackPop(MyStack* obj) {}int myStackTop(MyStack* obj) {}bool myStackEmpty(MyStack* obj) {}void myStackFree(MyStack* obj) {}/*** Your MyStack struct will be instantiated and called as such:* MyStack* obj = myStackCreate();* myStackPush(obj, x);* int param_2 = myStackPop(obj);* int param_3 = myStackTop(obj);* bool param_4 = myStackEmpty(obj);* myStackFree(obj);
*/

这里我们将用两种方法来完成这个问题:
 

方法一:两个队列

这个思路类似我们前面的用栈实现队列

我们的思路如下:

我们先创建两个队列,命名为queue1和queue2,queue1用于存储栈内的元素,queue2作为入栈操作的辅助队列。

入栈操作时,首先将元素入队到 queue2,然后将 queue1的全部元素依次出队并入队到 queue2,此时 queue2的前端的元素即为新入栈的元素,再将queue1和queue2互换,则queue1的元素即为栈内的元素,queue1的前端和后端分别对应栈顶和栈底。

假设此时push入队列一个2:

然后我们再push一个3入队列:

这样我们使用队列的pop就能达成和栈的pop一样的效果

接下来是代码演示:

#define LEN 20
typedef struct queue {int *data;int head;int rear;int size;
} Queue;typedef struct {Queue *queue1, *queue2;
} MyStack;Queue *initQueue(int k) {Queue *obj = (Queue *)malloc(sizeof(Queue));obj->data = (int *)malloc(k * sizeof(int));obj->head = -1;obj->rear = -1;obj->size = k;return obj;
}void enQueue(Queue *obj, int e) {if (obj->head == -1) {obj->head = 0;}obj->rear = (obj->rear + 1) % obj->size;obj->data[obj->rear] = e;
}int deQueue(Queue *obj) {int a = obj->data[obj->head];if (obj->head == obj->rear) {obj->rear = -1;obj->head = -1;return a;}obj->head = (obj->head + 1) % obj->size;return a;
}int isEmpty(Queue *obj) {return obj->head == -1;
}MyStack *myStackCreate() {MyStack *obj = (MyStack *)malloc(sizeof(MyStack));obj->queue1 = initQueue(LEN);obj->queue2 = initQueue(LEN);return obj;
}void myStackPush(MyStack *obj, int x) {if (isEmpty(obj->queue1)) {enQueue(obj->queue2, x);} else {enQueue(obj->queue1, x);}
}int myStackPop(MyStack *obj) {if (isEmpty(obj->queue1)) {while (obj->queue2->head != obj->queue2->rear) {enQueue(obj->queue1, deQueue(obj->queue2));}return deQueue(obj->queue2);}while (obj->queue1->head != obj->queue1->rear) {enQueue(obj->queue2, deQueue(obj->queue1));}return deQueue(obj->queue1);
}int myStackTop(MyStack *obj) {if (isEmpty(obj->queue1)) {return obj->queue2->data[obj->queue2->rear];}return obj->queue1->data[obj->queue1->rear];
}bool myStackEmpty(MyStack *obj) {if (obj->queue1->head == -1 && obj->queue2->head == -1) {return true;}return false;
}void myStackFree(MyStack *obj) {free(obj->queue1->data);obj->queue1->data = NULL;free(obj->queue1);obj->queue1 = NULL;free(obj->queue2->data);obj->queue2->data = NULL;free(obj->queue2);obj->queue2 = NULL;free(obj);obj = NULL;
}

方法二、一个队列

这个思路整体和方法一差不多

使用一个队列时,为了满足栈的特性,即最后入栈的元素最先出栈,同样需要满足队列前端的元素是最后入栈的元素。入栈操作时,首先获得入栈前的元素个数 n,然后将元素入队到队列,再将队列中的前 n 个元素(即除了新入栈的元素之外的全部元素)依次出队并入队到队列,此时队列的前端的元素即为新入栈的元素,且队列的前端和后端分别对应栈顶和栈底。

先push一个2

再push一个3,记录星插入之前的所有数据

pop出之前的数据

把数据从队列后面入队列

由于每次入栈操作都确保队列的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除队列的前端元素并返回即可

简单来说就是把队列当成一个环用,每次都把除了队列末端的元素都出队然后依次加到原本末端元素的后端,这样原本最后的元素就被推到了队列最前端,实现了 Last In First Out

代码实现:

typedef struct tagListNode {struct tagListNode* next;int val;
} ListNode;typedef struct {ListNode* top;
} MyStack;MyStack* myStackCreate() {MyStack* stk = calloc(1, sizeof(MyStack));return stk;
}void myStackPush(MyStack* obj, int x) {ListNode* node = malloc(sizeof(ListNode));node->val = x;node->next = obj->top;obj->top = node;
}int myStackPop(MyStack* obj) {ListNode* node = obj->top;int val = node->val;obj->top = node->next;free(node);return val;
}int myStackTop(MyStack* obj) {return obj->top->val;
}bool myStackEmpty(MyStack* obj) {return (obj->top == NULL);
}void myStackFree(MyStack* obj) {while (obj->top != NULL) {ListNode* node = obj->top;obj->top = obj->top->next;free(node);}free(obj);
}

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

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

相关文章

【大模型】Hugging Face下载大模型的相关文件说明

Hugging Face下载大模型文件说明 1.前言 ​ 上图是毛毛张在HuggingFace的官网上的ChatGLM-6B大模型的所有文件,对于初学者来说,对于上面的文件是干什么的很多小伙伴是很迷糊的,根本不知道是干什么的,毛毛张接下来将简单讲述一下上面的每个文件的作用。 2.文件说明 在Hug…

开发利器——C语言必备实用第三方库

​ 对于广大C语言开发者来说,缺乏类似C STL和Boost的库会让开发受制于基础库的匮乏,也因此导致了开发效率的骤降。这也使得例如libevent这类事件库(基础组件库)一时间大红大紫。 今天,码哥给大家带来一款基础库&#…

Python Tkinter GUI 基本概念

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝如果停止,就是低谷&#xf…

ACM题解Day10|总结篇|进制转化,GCD ,LCM ,二分答案

🔥博客介绍: 27dCnc [Cstring中find_first_not_of()函数和find_last_not_of()函数-CSDN博客] 方差,期望 概率 今日打卡: 算法周总结 ACM题解Day3| To Crash or not To Crash,Integer Prefix ,I don’t want to pay for the Late Jar-CSDN博客 第3题:…

【C语言】终の指针(前篇)

个人主页点这里~ 指针初阶点这里~ 指针初阶2.0点这里~ 指针进阶点这里~ 终の指针 一、回调函数二、qsort函数1、整形比较2、结构数据比较①结构体②-> 的使用③结构数据比较 一、回调函数 回调函数就是⼀个通过函数指针调用的函数。 把一个函数的指针作为参数传递给另一…

【JavaEE初阶】 JVM 运行时数据区简介

文章目录 🍃前言🌲堆(线程共享)🎄Java虚拟机栈(线程私有)🎋本地方法栈(线程私有)🌳程序计数器(线程私有)🌴方法…

20个Python函数程序实例

前面介绍的函数太简单了: 以下是 20 个不同的 Python 函数实例 下面深入一点点: 以下是20个稍微深入一点的,使用Python语言定义并调用函数的示例程序: 20个函数实例 简单函数调用 def greet():print("Hello!")greet…

2025张宇考研数学,百度网盘视频课+36讲PDF讲义+真题

张宇老师的课属于幽默生动,会让一个文科生爱上数学,但是有的同学不知道在哪看,可以看一下:2025张宇考研数学全程网盘 docs.qq.com/doc/DTmtOa0Fzc0V3WElI 可以粘贴在浏览器 张宇30讲作为一本基础讲义:和教材…

unity学习(50)——服务器三次注册限制以及数据库化角色信息5--角色信息数据库化收尾

上一节内容结束后确实可以写入文件了,但还有两个问题: 1.一个是players.txt中,每次重启服务器,当注册新账号创建角色时,players.txt之前内容都会清空。 2.players.txt之前已经注册3次的账号,新注册的角色…

BUUCTF-Misc2

wireshark1 1.打开附件 发现是流量包,放到Wireshark中分析 2.过滤 根据题目的提示寻找管理员登录的网站,从中获取密码 用http.request.methodPOST,过滤当前的 HTTP 请求为 POST 方法 3.查找 双击过滤后的流量包,查找管理员密码…

C# 高阶语法 —— Winfrom链接SQL数据库的存储过程

存储过程在应用程序端的使用的优点 1 如果sql语句直接写在客户端,以一个字符串的形式体现的,提示不友好,会导致效率降低 2 sql语句写在客户端,可以利用sql注入进行攻击,为了安全性,可以把sql封装在…

基于cnn卷积神经网络的车辆颜色检测识别-图像去雾-图像去雨(改进yolo目标检测-附代码)

– 引言: 开篇简述图像处理在智能交通监控、自动驾驶等领域的关键作用,并强调随着深度学习尤其是卷积神经网络(CNN)的发展,在复杂环境下的车辆颜色精确识别、图像恢复(如去雾和去雨)等难题得以…