栈和队列——用队列实现栈

news2024/9/19 10:33:57

题目中给出,让我们应用两个队列实现栈,首先我们先来想一下,栈是先进后出,队列是先进先出。所以我们就需要应用两个队列来回导才能实现栈的特点。因为这道题是基于队列来实现的,所以在下方若有看不懂的函数名称可以去栈和队列(二)中找到。

1.MyStrack

首先我们需要在结构体中存储我们的两个队列,后续方便通过结构体来调用两个队列。

typedef struct 
{
    Queue q1;
    Queue q2;
} MyStack;

2.myStackCreate()

对其进行初始化,首先我们需要先开辟一块空间用来存储两个队列。然后我们调用QueueInit()函数来对两个队列进行初始化。

MyStack* myStackCreate() 
{
    MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&(obj->q1));
    QueueInit(&(obj->q2));
    return obj;
}

3.myStackPush()

对栈进行插入,首先我们需要调用QueueEmpty()函数判断两个队列哪个不为空,再调用QueuePush()函数将数据直接插入到不为空的那个队列里就可以了。

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&(obj->q1)))
    {
        QueuePush(&(obj->q1),x);
    }
    else
    {
        QueuePush(&(obj->q2),x);
    }
}

4.myStackPop()

因为我们已经知道栈的删除是删除后进的数据,队列的删除是删除先进的数据。其删除的位置不同,所以不能混为一谈。所以我们需要把非空的队列中的前size-1个数据都挪到空的队列中。首先我们就需要先判断那个队列是空的。所以,依据我们之前做过的题,我们可以使用假设法,先假设q1为空,若q1不为空,再将空的改为q2。现在我们就用empty和nonempty来代表空队列和非空队列了。然后我们应用QueuePush()函数和QueueFront()函数来将非空队列中的头数据插入到空队列中,直到非空链表中的数据个数为1时停止,取出非空队列中的数据,就是我们需要的数据。

int myStackPop(MyStack* obj) 
{
    Queue*empty=&(obj->q1);
    Queue*nonempty=&(obj->q2);
    if(!QueueEmpty(&(obj->q1)))
    {
        empty=&(obj->q2);
        nonempty=&(obj->q1);
    }
    while(QueueSize(nonempty)>1)
    {
        QueuePush(empty,QueueFront(nonempty));
        QueuePop(nonempty);
    }
    int top=QueueFront(nonempty);
    QueuePop(nonempty);
    return top;
}

5.myStackTop()

由于栈是先进后出,队列是先进先出,所以栈的Top就是队列中后进的那个数据。所以我们首先需要判断哪个队列为非空队列,再调用QueueBack()函数返回非空队列中的尾数据就可以了。

int myStackTop(MyStack* obj) 
{
   if(!QueueEmpty(&(obj->q1)))
   {
    return QueueBack(&(obj->q1));
   }
   else
   {
    return QueueBack(&(obj->q2));
   }
}

6.myStackEmpty()

判断队列是否为空,需要两个队列同时为空,所以只需要调用QueueEmpty()函数,并返回两个队列进行与运算的值就可以了。

bool myStackEmpty(MyStack* obj) 
{
    return QueueEmpty(&(obj->q1))&&QueueEmpty(&(obj->q2));   
}

7.myStackFree()

由于我们刚刚将两个队列存储在了一个结构体中,所以在销毁时不能直接将结构体销毁,而是应该先销毁两个队列,再销毁结构体。

void myStackFree(MyStack* obj) 
{
    QueueDestory(&(obj->q1));
    QueueDestory(&(obj->q2));
    free(obj);
}

总结

整道题的基本思路与代码就讲解完毕了,下面附上本题的完整代码,如果大家感兴趣的话可以自行尝试哦~

typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;


typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

//队列的初始化
void QueueInit(Queue* pq);
//队列的插入
void QueuePush(Queue* pq, QDataType x);
//队列的删除
void QueuePop(Queue* pq);
//统计队列内的数据个数
int QueueSize(Queue* pq);
//获取队列的头数据
QDataType QueueFront(Queue* pq);
//获取队列的尾数据
QDataType QueueBack(Queue* pq);
//队列的判空
bool QueueEmpty(Queue* pq);
//队列的销毁
void QueueDestory(Queue* pq);

//队列的初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
//队列的插入
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(1);
	}
	newnode->next = NULL;
	newnode->val = x;
	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
//队列的删除
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

	//方法一:后判是否为只剩一个节点
	//QNode* next = pq->phead->next;
	//free(pq->phead);
	//pq->phead = next;
	//if (pq->phead == NULL)
	//{
	//	pq->ptail = NULL;
	//}
	//pq->size--;


	//方法二:先判是否为只剩一个节点
	if (pq->phead->next == NULL)
	{
		pq->phead = pq->ptail = NULL;
		pq->size = 0;
	}
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
		pq->size--;
	}
}


//统计队列内的数据个数
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

//获取队列的头数据
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->val;
}
//获取队列的尾数据
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->val;
}


//队列的判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;

}


//队列的销毁
void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* pcur = pq->phead;
	while (pcur)
	{
		QNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

typedef struct 
{
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() 
{
    MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&(obj->q1));
    QueueInit(&(obj->q2));
    return obj;
}

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&(obj->q1)))
    {
        QueuePush(&(obj->q1),x);
    }
    else
    {
        QueuePush(&(obj->q2),x);
    }
}

int myStackPop(MyStack* obj) 
{
    Queue*empty=&(obj->q1);
    Queue*nonempty=&(obj->q2);
    if(!QueueEmpty(&(obj->q1)))
    {
        empty=&(obj->q2);
        nonempty=&(obj->q1);
    }
    while(QueueSize(nonempty)>1)
    {
        QueuePush(empty,QueueFront(nonempty));
        QueuePop(nonempty);
    }
    int top=QueueFront(nonempty);
    QueuePop(nonempty);
    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);
}

/**
 * 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);
*/

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

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

相关文章

Java 入门指南:Java 并发编程 —— Synchronized 实现悲观锁(Pessimistic Locking)

悲观锁 悲观锁(Pessimistic Locking)是一种悲观的并发控制机制,它基于悲观的假设,即并发冲突会时常发生,因此在访问共享资源(如数据库记录或共享变量)之前,会先获取独占性的锁&…

数组结构第一周做题总结_基础练习

错误的原因是写了无参构造函数但是没有实现 id:8 A. 月份查询(指针数组) 题目描述 已知每个月份的英文单词如下,要求创建一个指针数组,数组中的每个指针指向一个月份的英文字符串,要求根据输入的月份数字输出相应的…

盘点java8 stream中隐藏的函数式接口

shigen坚持更新文章的博客写手,记录成长,分享认知,留住感动。个人IP:shigen 提到函数式接口,最常见的就是lambda表达式,IDEA也有智能的提示: 最后改成这样的就是最简洁的、IDEA希望的风格&#…

机器学习:基于机器学习的中文评论情感分析

通过机器学习技术对中文评论进行情感分析。我们使用了jieba进行中文分词,移除了停用词,并利用词袋模型(Bag of Words)和多项式朴素贝叶斯分类器对评论进行了情感分类。实验结果表明,该模型在测试集上达到了较高的准确率…

如何构建高效的中药材进存销管理系统?——运用Java SpringBoot和Vue实现库存实时监控,简化销售流程,提升药材管理效率。

🍊作者:计算机毕设匠心工作室 🍊简介:毕业后就一直专业从事计算机软件程序开发,至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长:按照需求定制化开发项目…

前端宝典二十一:前端异步编程规范手写Promise、async、await

本文主要探讨前端异步编程的处理方式、处理场景,并且手写Promise的全家桶,介绍async、await方法使用 一、异步处理方式有: 1. 回调函数 function fetchDate(callback) {setTimeout(() > {const date new Date();callback(date);}, 100…

SpringSecurity Oauth2 - 密码模式完成身份认证获取令牌 [自定义UserDetailsService]

文章目录 1. 授权服务器2. 授权类型1. Password (密码模式)2. Refresh Token(刷新令牌)3. Client Credentials(客户端凭证模式) 3. AuthorizationServerConfigurerAdapter4. 自定义 TokenStore 管理令牌1. TokenStore 的作用2. Cu…

嵌入式Linux C应用编程指南-高级I/O(速记版)

第十三章 高级I/O 13.1 非阻塞I/O 阻塞其实就是进入了休眠状态,交出了 CPU 控制权。比如 wait()、pause()、sleep()等函数都会进入阻塞。 阻塞式 I/O 顾名思义就是对文件的 I/O 操作(读写操作)是阻塞式的,非阻塞式 I/O 同理就是对…

SpringSecurity Oauth2 - 访问令牌续期

文章目录 1. 访问令牌的续期2. CustomUserDetailsService3. 配置 AuthorizationServerEndpointsConfigurer4. 测试项目 1. 访问令牌的续期 在Spring Security OAuth2中,访问令牌的续期通常是通过使用**刷新令牌(Refresh Token)**来实现的。当…

走进酒厂,探寻白酒酿造的奥秘

在华夏大地深处,隐藏着一座座充满神秘色彩的酒厂,它们是白酒酿造的地方,也是中华酒文化的摇篮。今天,就让我们一起走进这些酒厂,探寻白酒酿造的奥秘,感受豪迈白酒(HOMANLISM)的不同魅…

当网络适配器的Wireless出现感叹号

1.出现如下情况 链接: :一招搞定Intel(R) Wireless-AC 9560显示感叹号,无法打开wifi模块!_intel(r)wireless-ac9560感叹号-CSDN博客z 重点: 原因是因为电脑静电的问题。

昇腾AI处理器的计算核心 - AI Core即DaVinci Core

昇腾AI处理器的计算核心 - AI Core即DaVinci Core flyfish 从一段代码的解释开始 template <typename T> class GlobalTensor { public:void setGlobalBuffer(T* buffer, uint32_t buffersize) {// 在这里实现设置全局缓冲区的逻辑} };语法的说明&#xff0c;主要用于…

封装_私有类字段和方法

前言 在 JavaScript 中&#xff0c;封装、私有类字段和方法是面向对象编程的一种重要特性。它们允许你将数据&#xff08;属性&#xff09;和对数据的操作&#xff08;方法&#xff09;组合在一起&#xff0c;并控制访问权限&#xff0c;从而提高代码的安全性和可维护性。私有…

异步编程详解

1.什么是async std::async:是一个函数模板,用于启动一个异步任务。它接受一个可调用的对象(如函数、Lambda表达式、函数对象)作为参数,并在一个单独的线程上异步执行对象。std::async自动管理异步任务的生命周期,并返回一个std::future对象,该对象用于获取异步操作的结果。 2.什…

【Java】—— Java面向对象进阶:继承小练习-Java中实现圆柱体类及其体积计算

目录 1. 定义圆类&#xff08;Circle&#xff09; 2. 定义圆柱体类&#xff08;Cylinder&#xff09; 3. 测试圆柱体类 4. 总结 在Java中&#xff0c;我们可以通过面向对象的方式来模拟现实世界中的物体&#xff0c;比如圆柱体。本篇文章将通过一个简单的示例来展示如何定义…

全国大学生数学建模竞赛系统使用手册

注意&#xff01;国赛是学校统一报名&#xff0c;所以如果在操作上有任何不清楚的地方&#xff0c;一定要在赛前即使询问自己学校组织数模的老师&#xff01;并详细阅读本文和官网通知&#xff0c;以及&#xff1a;数模国赛提交MD5码和论文的坑&#xff01; 数模比赛的建模手、…

【Python报错已解决】“ModuleNotFoundError: No module named ‘timm‘”

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言&#xff1a;一、问题描述1.1 报错示例&#xff1a;当我们尝试导入timm库时&#xff0c;可能会看到以下错误信息。…

颠覆传统:基于全文索引驱动下的高效一对多表结构设计!

首发公众号&#xff1a;赵侠客 引言 在数据库表结构设计中&#xff0c;一对多&#xff08;1:N&#xff09;关系的处理是非常常见需求&#xff0c;如一个用户有多个分类或角色。传统关系型数据库表设计方式通常要包括三张表&#xff1a;用户表、分类表、以及用户与分类之间的关…

LC开源电路的学习(一)

TI的升压芯片&#xff0c;电压虽然能升高&#xff0c;但是带来的问题就是最大电流大幅降低&#xff1a; CC1和CC2芯片接快充芯片之后&#xff0c;直接接到单片机的下载口&#xff1a; 这个有点意思&#xff0c;用导线换电阻&#xff1a; 、 PD快充芯片CH224K需要连接typeC的D…

华为云征文|基于Flexus云服务器X实例的应用场景-部署脚手架开源项目若依

&#x1f534;大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 先看这里 写在前面**Flexus X实例**的云服务器简介环境准备若依项目拉取导入数据库启动本地项目&#xff08;后端&#xff09;启动本地项目&#xff08;前端&#xff09;打包后…