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.mzph.cn/news/601895.shtml

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

相关文章

Python基础入门第八课笔记(自定义函数 lambda)

什么时候用lambda表达式? 当函数有一个返回值,且只有一句代码,可以用lambda简写。 2、lanbda语法 lambda 形参 : 表达式 注意: 1、形参可以省略,函数的参数在lambda中也适用 2、lambda函数能接收任何数量的参数但只能…

MySQL之视图内连接、外连接、子查询案例

目录 一.视图 1.1 含义 1.2 操作 二.案例 三.思维导图 一.视图 1.1 含义 虚拟表,查询方面和普通表一样使用。 1.2 操作 1.创建视图: create or replace view 视图名 as 查询语句; 2.视图的修改: 方式1 create or replace view …

了解长短期记忆 (LSTM) 网络:穿越时间和记忆的旅程

一、说明 在人工智能和机器学习的迷人世界中,长短期记忆 (LSTM) 网络作为一项突破性创新脱颖而出。LSTM 旨在解决传统循环神经网络 (RNN) 的局限性,尤其是在学习长期依赖性方面的局限性,彻底改变了我们在各个领域建模和预测序列的能力。本文深…

Nacos与Eureka

一、前言 在构建和管理微服务架构时,选择适当的服务注册中心至关重要。Nacos和Eureka都是微服务体系结构中常用的服务注册和发现工具。本文将探讨它们之间的区别,帮助开发者在选择适合其项目需求的注册中心时做出明智的决策。 二、架构和适用场景 Nacos …

Java/JDK下载安装与环境配置

Java由Sun Microsystems(现在是Oracle的子公司)于1995年首次发布。它是一种面向对象的编程语言,广泛应用于Web开发、移动应用程序开发、桌面应用程序开发和企业级应用程序开发等领域。 Java语言的主要特点是跨平台、可移植性强、安全性高和具…

【开源】基于JAVA语言的智能教学资源库系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 课程档案模块2.3 课程资源模块2.4 课程作业模块2.5 课程评价模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 课程档案表3.2.2 课程资源表3.2.3 课程作业表3.2.4 课程评价表 四、系统展示五、核心代…

VLM,LLM等大模型如何应用于机器人控制(以强化学习为例)

VLM:视觉语义模型,准确识别图中有什么,处于什么状态,以及不同物体之间的关联。 LLM:语言大模型,可以针对当前的环境,自动生成可执行的任务,或者将人类指令重新分成可执行的子任务。…

[MAUI]在.NET MAUI中调用拨号界面

在.NET MAUI中调用拨号界面 前置要求: Visual Studio 2022 安装包“.NET Multi-platform App UI 开发” 参考文档: 电话拨号程序 新建一个MAUI项目 在解决方案资源管理器窗口中找到Platforms/Android/AndroidManifest.xml在AndroidManifest.xml中添加下文中…块如下:<?xml…

MAC系统安装多版本JDK

文章目录 1.JDK下载与安装2.查看安装过那些版本的jdk3.查看是否存在.bash_profile4.配置环境变量5.实现版本切换6.有些Mac可能版本问题&#xff0c;在关闭终端后&#xff0c;配置会失效&#xff01; 1.JDK下载与安装 官网下载地址: https://www.oracle.com/java/technologies/…

C++补充内容--语法篇

这里写目录标题 语法其他语法函数的存储类函数参数默认值格式默认参数位置重载函数的默认参数 指针名与正常指针的自增自减以及解引用与的优先级问题指针的赋值、加减数字、加减指针二维数组中的一些指针辨析输出调用字符指针时 会将该指针以及之后的元素全部输出二维数组未完全…

[NAND Flash 5.2] SLC、MLC、TLC、QLC、PLC NAND_闪存颗粒类型

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< 前言 闪存最小物理单位是 Cell, 一个Cell 是一个晶体管。 闪存是通过晶体管储存电子来表示信息的。在晶体管上加入了浮动栅贮存电子…

在vscode中创建任务编译module源文件

接昨天的文章 [创建并使用自己的C模块&#xff08;Windows10MSVC&#xff09;-CSDN博客]&#xff0c;觉得每次编译转到命令行下paste命令过于麻烦&#xff0c;于是研究了一下在vscode中创建自动编译任务。 经过尝试&#xff0c;在task.json中增加如下代码&#xff1a; {"…

【LMM 011】MiniGPT-5:通过 Generative Vokens 进行交错视觉语言生成的多模态大模型

论文标题&#xff1a;MiniGPT-5: Interleaved Vision-and-Language Generation via Generative Vokens 论文作者&#xff1a;Kaizhi Zheng* , Xuehai He* , Xin Eric Wang 作者单位&#xff1a;University of California, Santa Cruz 论文原文&#xff1a;https://arxiv.org/ab…

UI5与后端的文件交互(一)

文章目录 前言一、RAP的开发1. 创建表格2. 创建CDS Entity3. 创建BDEF4. 创建implementation class5. 创建Service Definition和Binding6. 测试API 二、创建UI5 Project1. 使用Basic模板创建2. 创建View3. 测试页面及绑定的oData数据是否正确4. 创建Controller5. 导入外部包&am…

java中使用redis

1、redis数据类型 1.1、5种数据类型 redis存储的是key-value结构的数据&#xff0c;其中key是字符串类型&#xff0c;value有5种常用的数据类型&#xff1a;字符串 string、哈希 hash、列表 list、集合 set、有序集合 sorted set / zset。 字符串(string)&#xff1a;普通字符…

如何把硬盘(分区)一分为二?重装系统的小伙伴不可不看

注意事项&#xff1a;本教程操作不当会导致数据丢失 请谨慎操作 请谨慎操作 请谨慎操作 前言 相信各位小伙伴都会切土豆吧&#xff0c;本教程就是教大家如何切土豆切得好的教程。 啊哈哈哈&#xff0c;开玩笑的。 比如你有一个D盘是200GB&#xff0c;想要把它变成两个100G…

【详解】求解迷宫所有路径(递归实现)----直接打穿迷宫

目录 递归的模型&#xff1a; 栈帧&#xff1a; 递归调用深度&#xff1a; ​编辑 用递归算法求解迷宫问题&#xff1a; 小结&#xff1a; 结语&#xff1a; 递归的小小总结&#xff0c;朋友们可以看看&#xff0c;有助于理解后面的递归程序。 递归的模型&#xff1a; …

【漏洞复现】冰峰VPN存在敏感信息泄露漏洞

漏洞描述 冰峰VPN log/system.log模块日志信息泄露漏洞 免责声明 技术文章仅供参考&#xff0c;任何个人和组织使用网络应当遵守宪法法律&#xff0c;遵守公共秩序&#xff0c;尊重社会公德&#xff0c;不得利用网络从事危害国家安全、荣誉和利益&#xff0c;未经授权请勿利…

网络优化篇(一)---------TCP重传性能优化

本文通过一个TCP重传优化的实际问题,详细讲解问题的分析、定位、优化过程。 通过本文你将学到: 如何通过linux命令和/proc文件系统分析TCP性能数据如何通过linux命令和netlink api分析某个具体的TCP连接的性能数据如何通过bcc工具分析TCP性能数据如何通过调整系统参数优化TCP重…

近屿智能OJAC带您从0到1全方位深度学习AI大模型,星辰大海和你开创!

Look&#xff01;&#x1f440;我们的大模型商业化落地产品&#x1f4d6;更多AI资讯请&#x1f449;&#x1f3fe;关注Free三天集训营助教在线为您火热答疑&#x1f469;&#x1f3fc;‍&#x1f3eb; 在这个信息爆炸的数字时代&#xff0c;你是否也想掌握那种像魔法一样的AI技…