用队列实现栈

问题描述:

请你仅用两个队列实现一个后入先出(LIFO)的栈,并支持普通队列的全部四种操作(push、top、pop和empty)。

实现MyStack类:

  • void push(int x) 将元素x压入栈顶。
  • int pop()移除并返回栈顶元素。
  • int top()返回栈顶元素。
  • boolean empty()如果栈是空的,返回true;否则,返回false。

解题思路: 

 

1. 入数据,往不为空的队列入

2. 出数据,把不为空的队列数据导入为空,直至只剩最后一个

解决本题之前,要先将队列的各类接口函数准备好,队列的接口函数我上一篇中提到了喔:

#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;//删除数据和插入数据需要记录头结点和尾结点
typedef struct Queue
{QNode* head;QNode* tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
//队尾入
void QueuePush(Queue* pq, QDataType x);
//队头出
void QueuePop(Queue* pq);
//取队头的数据
QDataType QueueFront(Queue* pq);
//取队尾的数据
QDataType QueueBack(Queue* pq);
//取数据的个数
int QueueSize(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);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;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);//断言队列是否为空,为空就不可删除,会有野指针if (pq->head->next == NULL)//当只有一个节点时,tail可能为野指针,tail指向已释放的空间pq->tail = NULL;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;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()
{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);
}

整体代码:

#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;//删除数据和插入数据需要记录头结点和尾结点
typedef struct Queue
{QNode* head;QNode* tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
//队尾入
void QueuePush(Queue* pq, QDataType x);
//队头出
void QueuePop(Queue* pq);
//取队头的数据
QDataType QueueFront(Queue* pq);
//取队尾的数据
QDataType QueueBack(Queue* pq);
//取数据的个数
int QueueSize(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);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;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);//断言队列是否为空,为空就不可删除,会有野指针if (pq->head->next == NULL)//当只有一个节点时,tail可能为野指针,tail指向已释放的空间pq->tail = NULL;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;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()
{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/208863.shtml

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

相关文章

手写 Promise:深入理解异步编程的基石

手写 Promise&#xff1a;深入理解异步编程的基石 本文将带您逐步实现一个简单的 Promise&#xff0c;以帮助您深入理解异步编程的基本概念。通过自己动手编写 Promise 的过程&#xff0c;您将更好地理解 Promise 的工作原理和常见用法&#xff0c;并能够应用于实际项目中。 …

什么是网站劫持

网站劫持是一种网络安全威胁&#xff0c;它通过非法访问或篡改网站的内容来获取机密信息或者破坏计算机系统。如果您遇到了网站劫持问题&#xff0c;建议您立即联系相关的安全机构或者技术支持团队&#xff0c;以获得更专业的帮助和解决方案。

Angular 进阶之四:SSR 应用场景与局限

应用场景 内容丰富&#xff0c;复杂交互的动态网页&#xff0c;对首屏加载有要求的项目&#xff0c;对 seo 有要求的项目&#xff08;因为服务端第一次渲染的时候&#xff0c;已经把关键字和标题渲染到响应的 html 中了&#xff0c;爬虫能够抓取到此静态内容&#xff0c;因此更…

【面试专题】MySQL篇①

1.MySQL中&#xff0c;如何定位慢查询? ①介绍一下当时产生问题的场景&#xff08;我们当时的一个接口测试的时候非常的慢&#xff0c;压测的结果大概5秒钟&#xff09; ②我们系统中当时采用了运维工具&#xff08; Skywalking &#xff09;&#xff0c;可以监测出哪个接口…

PostgreSQL从小白到高手教程 - 第38讲:数据库备份

PostgreSQL从小白到专家&#xff0c;是从入门逐渐能力提升的一个系列教程&#xff0c;内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容&#xff0c;希望对热爱PG、学习PG的同学们有帮助&#xff0c;欢迎持续关注CUUG PG技术大讲堂。 第38讲&#…

running小程序重要技术流程文档

一、项目文件说明&#xff1a; &#xff08;注&#xff1a;getMyMoney无用已删除&#xff09; 二、重要文件介绍 1.reinfo.js&#xff1a;位于utils文件下&#xff0c;该文件封装有统一的请求URL&#xff0c;和请求API同意封装供页面调用&#xff1b;调用时候需要在页面上先…

【C语言】操作符详解(一):进制转换,原码,反码,补码

目录 操作符分类 2进制和进制转换 2进制转10进制 10进制转2进制 2进制转8进制和16进制 2进制转8进制 2进制转16进制 原码、反码、补码 操作符分类 操作符中有一些操作符和二进制有关系&#xff0c;我们先铺垫一下二进制的和进制转换的知识。 2进制和进制转换 其实我们经…

vertica主键列能插入重复值的处理办法

问题描述 开发同事反馈在vertica中创建含主键列的表中插入重复数据时没有进行校验&#xff0c;插入重复值成功。经过测试着实可以插入重复值&#xff0c;这个坑有些不一样。 创建表和插入语句如下&#xff1a; --创建表 CREATE TABLE dhhtest(ID VARCHAR(64) PRIMARY KEY );…

使用Microsoft Dynamics AX 2012 - 5. 生产控制

生产控制的主要职责是生产成品。为了完成这项任务&#xff0c;制造业需要消耗物品和资源能力&#xff08;人员和机械&#xff09;。制造过程可能包括半成品的生产和库存。半成品是指物品包括在成品材料清单中。 制造业的业务流程 根据公司的要求&#xff0c;您可以选择申请Dy…

某马点评——day04

达人探店 发布探店笔记 改一下&#xff0c;图片保存路径就可以直接运行测试了。 查看探店笔记 Service public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {Resourceprivate IUserService userService;Overridepublic Resu…

OpenCL学习笔记(二)手动编译开发库(win10+vs2019)

前言 有时需求比较特别&#xff0c;可能需要重新编译opencl的sdk库。本文档简单记录下win10下&#xff0c;使用vs2019编译的过程&#xff0c;有需要的小伙伴可以参考下 一、获取源码 项目地址&#xff1a;GitHub - KhronosGroup/OpenCL-SDK: OpenCL SDK 可以直接使用git命令…

一篇文章了解指针变量

字符指针变量 在指针的类型中我们知道有一种指针叫做字符指针 它的使用情况如下&#xff1a; #include<stdio.h> int main() {char pa w;char*p1&pa;*p1 a;printf("%c\n", *p1);return 0; } 在这段代码当中&#xff0c;我们将‘w’字符的地址传到了p…

vue3 自己写一个月的日历

效果图 代码 <template><div class"monthPage"><div class"calendar" v-loading"loading"><!-- 星期 --><div class"weekBox"><div v-for"(item, index) in dayArr" :key"index&q…

2.修改列名与列的数据类型

修改字段名与字段数据类型 1.修改字段名 有时&#xff0c;在我们建好一张表后会突然发现&#xff0c;哎呀&#xff01;字段名貌似写错了&#xff01;怎么办&#xff1f;要删了表再重新建一个新表吗&#xff1f;还是要删了这个字段再新建一个新的字段&#xff1f; 都不用&…

AIGC专题报告:生成式人工智能人人可用的新时代

今天分享的AIGC系列深度研究报告&#xff1a;《AIGC专题报告&#xff1a;生成式人工智能人人可用的新时代》。 &#xff08;报告出品方&#xff1a;埃森哲&#xff09; 报告共计&#xff1a;21页 人工智能发展迎来新拐点 ChatGPT 正在唤醒全球对人工智能&#xff08;AI&…

在pom.xml中添加maven依赖,但是类里面import导入的时候报错

问题&#xff1a; Error:(27, 8) java: 类TestKuDo是公共的, 应在名为 TestKuDo.java 的文件中声明 Error:(7, 23) java: 程序包org.apache.kudu不存在 Error:(8, 23) java: 程序包org.apache.kudu不存在 Error:(9, 23) java: 程序包org.apache.kudu不存在 Error:(10, 30) jav…

【Java探索之旅】我与Java的初相识(一):Java的特性与优点及其发展史

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java入门到精通 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 一. Java语言概述与优势1.1 Java的概述1.2 Java语言的优势 二. Java领域与发展史2.1 Java的使用领域2.…

面试多线程八股文十问十答第二期

面试多线程八股文十问十答第二期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1.进程和线程的区别 概念不同&#xff1a;进程是操作系统中的一个独立执行单元&a…

目标检测mAP计算以及coco评价标准

这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 讲一下目标检测中的一些常见的指标 在我们使用目标检测网络训练时 最后在验证集上会得到一个coco的评价列表 就像我们图中给的这一系列参数列表一样 我们再进一步引入两个概念 第一个叫做precisi…

P1 Qt的认识及环境配置

目录 前言 01 下载Qt Creator windows下载安装包拷贝到Linux Linux直接下载 02 Linux 安装Qt 前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《Linux C应用编程&#xff08;概念类…