LeetCode 225.用队列实现栈(详解) ૮꒰ ˶• ༝ •˶꒱ა

题目详情:

思路:1.定义两个队列用于存储栈的数据,其中一个为空。

          2.对我们定义的栈进行入数据,就相当于对不为空的队列进行入数据。

          3.对我们定义的栈进行删除,相当于取出不为空的队列中的数据放到为空的队列中,直到此时只剩下一个数据;对剩下的数据进行取出后删除。也就相当于对当前的栈进行删除。(对于栈的顶删相当于对队列的尾删)

        3.返回栈的顶部元素

        4.销毁栈

 注意:用c语言实现队列,没法直接引用,这里需要自己创建一个队列,再完成上述操作。如果还不会队列的小伙伴可以看看我的这篇博客数据结构--队列【详解】~(˶‾᷄ꈊ‾᷅˵)~-CSDN博客

 

 队列的实现:

typedef int QDataType;
typedef struct QueueNode
{//队列的定义与声明struct QueueNode* next;QDataType data;
}QNode;
//创建一个结构体用于存储队列头尾指针
typedef struct Queue
{QNode* head;QNode* tail;
}Queue;
//初始化队列
void QueueInit(Queue* pq)
{assert(pq);pq->head = pq->tail = NULL;
}
//摧毁队列
void QueueDestory(Queue* pq)
{assert(pq);QNode* cur = pq->head;while (cur){//存储下一个节点的指针,防止找不到和野指针的出现QNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;
}// 队尾入
void QueuePush(Queue* pq, QDataType x)
{assert(pq);//为队列开辟一个新节点QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;newnode->next = NULL;
//若第一个节点为空,则head和tail指向第一个节点if (pq->tail == NULL){pq->head = pq->tail = newnode;}//如果不是空,就让尾指针指向新节点,并移动尾指针方便下一次插入else{pq->tail->next = newnode;pq->tail = newnode;}
}// 队头出
void QueuePop(Queue* pq)
{assert(pq);assert(pq->head);// 1、一个,直接释放第一个节点的内存// 2、多个,要记得保存第一个节点的下一个节点的位置,防止找不到if (pq->head->next == NULL){free(pq->head);pq->head = pq->tail = NULL;}else{QNode* next = pq->head->next;free(pq->head);pq->head = next;}
}//返回队头节点的数据
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->head);return pq->head->data;
}
//返回队尾节点的数据
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->head);return pq->tail->data;
}
//返回队列的大小
int QueueSize(Queue* pq)
{assert(pq);int size = 0;//这里用cur记录节点的个数QNode* cur = pq->head;while (cur){++size;cur = cur->next;}return size;
}
//判断节点是否为空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

 

 用队列实现栈的函数实现:

//定义一个结构体用于存放两个队列
typedef struct {Queue q1;Queue q2;
} MyStack;
//用队列创造栈
MyStack* myStackCreate() {//用ps开辟空间,作为栈存储数据MyStack* ps=(MyStack*)malloc(sizeof(MyStack));if(ps==NULL){printf("malloc fail\n");exit(-1);}QueueInit(&ps->q1);QueueInit(&ps->q2);return ps;
}
//用队列入栈
void myStackPush(MyStack* obj, int x) {if(!QueueEmpty(&obj->q1))//选择不为空的那个队列入{QueuePush(&obj->q1,x);}else{QueuePush(&obj->q2,x);}
}
//用队列进行出栈操作
int myStackPop(MyStack* obj) {Queue* emptyQ=&obj->q1;//将不为空的队列的数据转移到为空的队列,直到只剩一个Queue* nonemptyQ=&obj->q2;if(!QueueEmpty(&obj->q1)){emptyQ=&obj->q2;nonemptyQ=&obj->q1;}while(QueueSize(nonemptyQ)>1){QueuePush(emptyQ,QueueFront(nonemptyQ));QueuePop(nonemptyQ);}int top=QueueFront(nonemptyQ);QueuePop(nonemptyQ);return top;
}
//返回栈顶的元素,即返回不为空的队列的尾元素
int myStackTop(MyStack* obj) {if(!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}
}
//判断栈是否为空
bool myStackEmpty(MyStack* obj) {return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
//摧毁创建的栈
void myStackFree(MyStack* obj) {QueueDestory(&obj->q1);QueueDestory(&obj->q2);free(obj);
}

 注意:摧毁栈时要先摧毁obj下所对应的队列,再进行free(obj)。如果先free(obj),就无法找到对应的队列了

完整代码: 

typedef int QDataType;
typedef struct QueueNode
{//队列的定义与声明struct QueueNode* next;QDataType data;
}QNode;
//创建一个结构体用于存储队列头尾指针
typedef struct Queue
{QNode* head;QNode* tail;
}Queue;
//初始化队列
void QueueInit(Queue* pq)
{assert(pq);pq->head = pq->tail = NULL;
}
//摧毁队列
void QueueDestory(Queue* pq)
{assert(pq);QNode* cur = pq->head;while (cur){//存储下一个节点的指针,防止找不到和野指针的出现QNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;
}// 队尾入
void QueuePush(Queue* pq, QDataType x)
{assert(pq);//为队列开辟一个新节点QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;newnode->next = NULL;
//若第一个节点为空,则head和tail指向第一个节点if (pq->tail == NULL){pq->head = pq->tail = newnode;}//如果不是空,就让尾指针指向新节点,并移动尾指针方便下一次插入else{pq->tail->next = newnode;pq->tail = newnode;}
}// 队头出
void QueuePop(Queue* pq)
{assert(pq);assert(pq->head);// 1、一个,直接释放第一个节点的内存// 2、多个,要记得保存第一个节点的下一个节点的位置,防止找不到if (pq->head->next == NULL){free(pq->head);pq->head = pq->tail = NULL;}else{QNode* next = pq->head->next;free(pq->head);pq->head = next;}
}//返回队头节点的数据
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->head);return pq->head->data;
}
//返回队尾节点的数据
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->head);return pq->tail->data;
}
//返回队列的大小
int QueueSize(Queue* pq)
{assert(pq);int size = 0;//这里用cur记录节点的个数QNode* cur = pq->head;while (cur){++size;cur = cur->next;}return size;
}
//判断节点是否为空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}
//定义一个结构体用于存放两个队列
typedef struct {Queue q1;Queue q2;
} MyStack;
//用队列创造栈
MyStack* myStackCreate() {//用ps开辟空间,作为栈存储数据MyStack* ps=(MyStack*)malloc(sizeof(MyStack));if(ps==NULL){printf("malloc fail\n");exit(-1);}QueueInit(&ps->q1);QueueInit(&ps->q2);return ps;
}
//用队列入栈
void myStackPush(MyStack* obj, int x) {if(!QueueEmpty(&obj->q1))//选择不为空的那个队列入{QueuePush(&obj->q1,x);}else{QueuePush(&obj->q2,x);}
}
//用队列进行出栈操作
int myStackPop(MyStack* obj) {Queue* emptyQ=&obj->q1;//将不为空的队列的数据转移到为空的队列,直到只剩一个Queue* nonemptyQ=&obj->q2;if(!QueueEmpty(&obj->q1)){emptyQ=&obj->q2;nonemptyQ=&obj->q1;}while(QueueSize(nonemptyQ)>1){QueuePush(emptyQ,QueueFront(nonemptyQ));QueuePop(nonemptyQ);}int top=QueueFront(nonemptyQ);QueuePop(nonemptyQ);return top;
}
//返回栈顶的元素,即返回不为空的队列的尾元素
int myStackTop(MyStack* obj) {if(!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}
}
//判断栈是否为空
bool myStackEmpty(MyStack* obj) {return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
//摧毁创建的栈
void myStackFree(MyStack* obj) {QueueDestory(&obj->q1);QueueDestory(&obj->q2);free(obj);
}

博客到这里也是结束了,喜欢的小伙伴可以点赞加关注支持下博主,这对我真的很重要~~

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

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

相关文章

Android - CrashHandler 全局异常捕获器

官网介绍如下:Thread.UncaughtExceptionHandler (Java Platform SE 8 ) 用于线程因未捕获异常而突然终止时调用的处理程序接口。当线程由于未捕获异常而即将终止时,Java虚拟机将使用thread . getuncaughtexceptionhandler()查询该线程的UncaughtExceptio…

路由黑洞和黑洞路由的区别

路由黑洞: 路由黑洞是一种现象,一般是在网络边界做汇总回程路由的时候产生的一种不太愿意出现的现象,就是汇总的时候有时会有一些不在内网中存在的网段,但是又包含在汇总后的网段中,如果在这个汇总的边界设备上同时还配…

Java面试之并发篇(一)

1、前言 本篇主要总结JAVA面试中关于并发相关的高频面试题。本篇的面试题基于网络整理,和自己编辑。在不断的完善补充哦。 2、简述程序、进程、线程、的基本概念? 2.1、程序 程序,是含有指令和数据的文件,被存储在磁盘或其他的…

变压器

一、变压器的作用 电压变换:变压器可以改变交流电压的大小,从而满足不同设备的需要。通过变压器的降压和升压功能,可以将电压升高或降低到合适的范围,实现远距离输电、电能分配和设备安全运行的目的。 电流变换:变压器…

解决 rasa 中 slot 不能为中文的问题

解决 rasa 中 slot 不能为中文的问题 定位问题解决办法 定位问题 slots:姓名:type: textmappings:- type: custom如上的 slot 配置,在 rasa train 时会报以下错误: YamlValidationException: Failed to validate D:\project\python\rasa_test\y\domain…

Python爬取哈尔滨旅游爆火视频数据并进行可视化分析

前言 哈尔滨作为中国北方的重要城市,独特的冰雪风情和丰富的文化底蕴而受到游客的青睐。随着抖音等短视频平台的兴起,越来越多关于哈尔滨旅游的视频在网络上出现文章旨在利用Python编程语言,从音视频网站上抓取哈尔滨旅游抖音相关视频数据&a…

java基础之异常练习题

异常 1.Java 中所有的错误/异常都继承自 Throwable类;在该类的子类中, Error 类表示严重的底层错误, 对于这类错误一般处理的方式是 直接报告并终止程序 ; Exception 类表示异常。 2.查阅API,完成以下填空:…

RK3568驱动指南|第十篇 热插拔-第112章 热插拔简介

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…

window mysql5.7 搭建主从同步环境

window 搭建mysql5.7数据库 主从同步 主节点 配置文件my3308.cnf [mysql] # 设置mysql客户端默认字符集 default-character-setutf8mb4[mysqld] server-id8 #server-uuidbc701be9-ac71-11ee-9e35-b06ebf511956 log-binD:\mysql_5.7.19\mysql-5.7.19-winx64\mysql-bin binlog-…

22nxxz

难度简单,适合练手! 期末考试前最后一篇博客,还是很感谢范老师,范老师帮我突破了后台的思路mua! 一、请检查窝点中的手机检材,回答以下问题 直接分析不行,sd卡需要解压缩 该OPPO手机的IMEI是:860370043989014,860370049389006860370049389014,8603700493890068603700…

安卓 APK 如何查看公钥与签名 MD5 值、JadxGUI 工具的使用。

下载地址 https://gitcode.com/skylot/jadx/overview?utm_sourcecsdn_github_accelerator&isLogin1 也可以在这里下载 https://download.csdn.net/download/u010843503/88725345

Web缓存代理

目录 前瞻 web缓存代理的工作机制 web缓存代理的作用 常见的Web缓存代理应用 squid、Varinsh和Nginx有什么区别,工作中你怎么选择? 数据库缓存代理应用 Nginx 缓存代理 CDN缓存代理 简介 原理 CDN对网络的优化作用主要体现在如下几个方面 CDN…