【LeetCode】用队列实现栈和用栈实现队列(C语言)

news2025/7/27 23:02:48

目录

1.用队列实现栈

 增删

 求栈顶元素

 判断栈为空

2.用栈实现队列 

 增删

返回队列开头的数据 

判断队列为空

尾言

源码

队列实现栈

栈实现队列


刚讲完栈和队列,LeetCode上有两题栈与队列的互相实现,简单地讲讲思路和实现吧。

1.用队列实现栈

原题地址:225.用队列实现栈

 题目要求我们用两个队列来实现一个栈,我们知道队列的性质是先进先出,而栈是后进先出,假设随便给我们要的这个栈之中添加几个数,便能画出这样的图

 增删

那这样接下来若要出栈,输出的便是 ,但是队列出队的话只能输出 。所以我们就要用到另一个队列,把队列1最后一个数前面的数据导入到队列2之后再输出队列1的唯一数。这样就完成了出栈的模拟。

之后把队列1第一个数据删除,一定保证一个队列为空 ,即第二次出栈还是要把非空的队列的数据导入空队列里去。

 若是要入栈操作的话就是直接再非空队列队尾插入数据就可以了,最后面的值不会被导入到另一队列里。所以下次出栈就会将其输出。

 求栈顶元素

找栈顶元素其实与出栈的唯一不同就是,出栈要删除栈顶元素,而求栈顶元素不一样,其要求要有返回值。偷懒的话可以先写求栈顶元素,之后出栈只要复用函数就可以完成了。

 判断栈为空

 前面讲过,必定有一个队列为空,因此不能只检查一个队列而是两个队列都要检查,即两个队列都为空则证明栈为空。

2.用栈实现队列 

原题地址:232.用栈实现队列

其实只要熟悉了队列和栈的基本性质,其实这两题也并不会很难,思路正确了剩下的就只需要注意编写程序时的小细节就可以了。 

 增删

仔细分析题目,要求用两个栈实现一个队列,既然题目都这样要求了只用一个栈明显是不可能的,上一题的经验告诉我,要把数据导入到另一个栈里。

 把数据导到另一个栈后我们惊奇的发现,数据恰好就成了我们想要的样子。这段数据就可以直接输出了。

 这下我们就可以让一个栈专门承载输入数据,另一个栈专门输出数据,输出栈为空时再从输入栈把数据导入到输出栈里面。

返回队列开头的数据 

也是跟删除是一个道理,不过只是返回值并不删除数据。即输出栈没有值就导入输入栈的值进去就可以了。

判断队列为空

 两个栈如果都为空,队列就为空,只有其中一个栈为空是不算的。

 

尾言

 好了,这样今天我们两道题的思路与实现到这里就讲完了,说实在的用C语言写确实是麻烦了一点,但是之前写过栈和队列的话直接把代码复制过去,之后用自己之前写的函数写就可以了。有问题的话一定私信或者评论区指出,一定第一时间回复!!!

源码

队列实现栈

typedef int Qdatatype;
typedef struct Qnode
{
	Qdatatype data;
	struct Queue* next;
}Qnode;

typedef struct Queue
{
	Qnode* head;
	Qnode* tail;
	int size;
}Queue;


void Queueinit(Queue* p)
{
	p->head = NULL;
	p->tail = NULL;
	p->size = 0;
}

bool QueueEmpty(Queue* p)
{
	assert(p);
	return p->head == NULL || p->tail == NULL;
}

void Queuepush(Queue* p, Qdatatype x)
{
	assert(p);

	Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));
	if (newnode == NULL)
	{
		perror(malloc);
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (p->head == NULL)
	{
		p->head = p->tail = newnode;
		p->size++;
	}
	else
	{
		p->tail->next = newnode;
		p->tail = newnode;
		p->size++;
	}
}

void Queuepop(Queue* p)
{
	assert(p);
	assert(!QueueEmpty(p));

	Qnode* next = p->head->next;
	free(p->head);
	p->head = next;
	p->size--;
}

Qdatatype Queuefront(Queue* p)
{
	assert(p);
	return p->head->data;
}

void QueueDestroy(Queue* p)
{
	assert(p);

	Qnode* cur = p->head;
	while (cur)
	{
		Qnode* next = cur->next;
		free(cur);
		cur = next;
	}
	p->head = p->tail = NULL;
	p->size = 0;
}

Qdatatype Queueback(Queue* p)
{
	assert(p);
	assert(!QueueEmpty(p));

	return p->tail->data;
}

int Queuesize(Queue* p)
{
	assert(p);

	return p->size;
}


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


MyStack* myStackCreate() {
	MyStack* stack = (MyStack*)malloc(sizeof(MyStack));     //开辟栈的空间,动态开辟才不是局部变量
	Queueinit(&stack->q1);                                  //两个队列的初始化
	Queueinit(&stack->q2);
	return stack;
}

void myStackPush(MyStack* obj, int x) {
	assert(obj);
	if (!QueueEmpty(&obj->q1))                      //在非空队列里插入数据,两个都为空则默认插入在第一个里面
	{
		return Queuepush(&obj->q1, x);
	}
	else
	{
		return Queuepush(&obj->q2, x);
	}
}

int myStackPop(MyStack* obj) {
	assert(obj);
	Queue* emptyqueue = &obj->q1;    //一定有一个空队列
	Queue* queue = &obj->q2;         //一个是有数据的队列
	if (QueueEmpty(&obj->q2))        //判断为空的队列
	{
		emptyqueue = &obj->q2;
		queue = &obj->q1;
	}
	while (Queuesize(queue) > 1)
	{
		Queuepush(emptyqueue, Queuefront(queue));    //导入后删除原队列里的数据
		Queuepop(queue);
	}
	int ret = Queuefront(queue);
	Queuepop(queue);
	return ret;
}

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

bool myStackEmpty(MyStack* obj) {
	assert(obj);

	return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

栈实现队列

 

typedef int STdatatype;
typedef struct Stack
{
	STdatatype* data;
	int top;
	int capacity;
}Stack;

void checkcapacity(Stack* p)
{
	STdatatype* newp;
	if (p->top == p->capacity)
	{
		newp = (STdatatype*)realloc(p->data, sizeof(Stack) * p->capacity * 2);
		if (newp == NULL)
		{
			perror(realloc);
			exit(-1);
		}
		p->data = newp;
		p->capacity *= 2;
	}
	if (p == NULL)
	{
		perror(realloc);
		exit(-1);
	}
}
void StackInit(Stack* p)
{
	STdatatype* np = (STdatatype*)malloc(sizeof(STdatatype) * 4);
	if (np)
	{
		p->data = np;
	}
	p->top = 0;
	p->capacity = 4;
}

void StackPush(Stack* p, STdatatype x)
{
	assert(p);
	checkcapacity(p);
	(p->data)[p->top] = x;
	p->top++;
}

void Stackprint(Stack* p)
{
	int i = p->top - 1;
	while (i >= 0)
	{
		printf("%d ", (p->data)[i--]);
	}
	printf("\n");
}

void StackPop(Stack* p)
{
	assert(p);
	assert(p->top);
	p->top--;
}


STdatatype StackTop(Stack* p)
{
	assert(p);
	int top = p->top - 1;
	return (p->data)[top];
}

int StackEmpty(Stack* p)
{
	assert(p);
	if (p->top != 0)
	{
		return 0;
	}
	return 1;
}

void StackDestroy(Stack* p)
{
	assert(p);
	assert(p->data);
	free(p->data);
	p->data = NULL;
	p->top = 0;
	p->capacity = 0;
}


typedef struct          //两个队列一个输出一个输入,输出栈里没数据了之后就从输入里面倒数据过去
{
	Stack S;                //输入
	Stack nullS;            //输出
} MyQueue;

bool myQueueEmpty(MyQueue* obj);
int myQueuePeek(MyQueue* obj);

MyQueue* myQueueCreate()                    //创建队列
{
	MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue));  //开辟队列空间
	StackInit(&queue->S);								//对两个栈初始化
	StackInit(&queue->nullS);
	return queue;										//返回开辟的队列
}

void myQueuePush(MyQueue* obj, int x) {
	assert(obj);
	StackPush(&obj->S, x);                         //直接在插入的队列里插入数据
}

int myQueuePop(MyQueue* obj) {
	assert(obj); 
	assert(!myQueueEmpty(obj));						//判断队列不为空

	int ret = myQueuePeek(obj);                     //取最上面的值返回
	StackPop(&obj->nullS);                          //pop在peek的基础上增加数据的删除
	return ret;
}

int myQueuePeek(MyQueue* obj) {						//拿最前面的数据
	assert(obj);
	assert(!myQueueEmpty(obj));                     //队列不为空

	if (StackEmpty(&obj->nullS))                    //输出栈为空则倒入数据
	{
		while (!StackEmpty(&obj->S))                //直到输入栈为空,必定一个栈为空
		{
			StackPush(&obj->nullS, StackTop(&obj->S));   //取输入栈最上面导入到输出栈的最下面
			StackPop(&obj->S);                           //清除输入栈的数据
		}
	}
	return StackTop(&obj->nullS);                        //返回最上面的值
}

bool myQueueEmpty(MyQueue* obj) {
	assert(obj);
	return StackEmpty(&obj->nullS) && StackEmpty(&obj->S);  //两个栈都为空则队列为空
}

void myQueueFree(MyQueue* obj) {
	assert(obj);
	StackDestroy(&obj->nullS);								//销毁两个栈
	StackDestroy(&obj->S);
	free(obj);												//销毁队列
}

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

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

相关文章

婴幼儿蛋白质过敏怎么回事

很多孩子吃了含蛋白质的食物后会出现瘙痒或痱子等过敏症状,甚至全身发红。这是因为一些过敏体质的孩子儿童会对蛋白质过敏。婴儿蛋白质过敏会导致一些严重的问题,那么当婴儿蛋白质过敏发生时,该怎么以下是一个详细的介绍!目录蛋白…

[Spring Boot]08 IDEA接入MyBatisCodeHelper代码自动生成器

目录前言一、插件市场安装插件二、使用插件自动生成代码前言 上次介绍了,原生mybatis的方法: 06 Spring Boot接入mybatis通用mapper插件自动生成器。 这次,再介绍下插件MyBatisCodeHelper-Pro的用法,使用此方法更加简单和方便。 …

老照片修复工具哪个好?这几个修复软件你快看看

相信我们很多小伙伴的爷爷奶奶家里都会有很多老照片,这些照片由于年代久远,或多或少都会有些损坏,不是泛黄就是有些褶皱,如果我们想将照片进行流传下去,肯定就是将其修复并重新洗出来啦。要是不想出门找专业的摄影师修…

Spring Boot 整合 MyBatis Plus实现多数据源的两种方式

第一种&#xff1a;使用配置类的方式&#xff1a; 项目结构 xml依赖&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-ins…

hadoop 3.3大数据集群搭建系列3-安装Hive

文章目录一. 下载hive二. 解压三. 添加Hive核心配置&#xff0c;选择远程MySQL模式四. 下载连接MySQL的驱动包到hive的lib目录下五. MySQL下创建hive数据库六. 执行Hive的初始化工作七. 验证初始化是否成功八. 使用hive参考:一. 下载hive cd /home/software wget https://mirr…

简单搭建redis哨兵集群

文章目录简单搭建redis哨兵集群配置参数说明配置部署哨兵集群检查哨兵状态其他配置踩坑记录简单搭建redis哨兵集群 配置参数说明 sentinel monitor mymaster 10.0.0.4 6379 指定对一个 master 的监控&#xff0c;给监控的 master 指定的一个名称。 sentinel down-after-mill…

Ubuntu配置NFS服务器(Linux挂载Linux)

Ubuntu配置NFS服务器 服务器端的配置 Ubuntu安装NFS服务器端 sudo apt-get install nfs-kernel-server服务端查看版本 nfsstat -s在桌面上创建共享目录 mkdir share修改/etc/export配置文件&#xff0c;在后面添加如下语句 /home/xxx/桌面/share *(rw,sync,no_root_squas…

Java异常处理机制

文章目录异常的概念引入的小例子基本概念异常体系图常见异常分类常见的运行时异常编译异常异常处理try-catch-finallythrows小练习自定义异常自定义异常的步骤throw与throws练习题异常的概念 引入的小例子 public class Exception01 {public static void main(String[] args)…

如何在图片上添加水印?快把这些方法收好

相信有些小伙伴经常会在网络上&#xff0c;分享自己拍摄的图片吧。那大家是否有遇到过发布的图片&#xff0c;被其他人盗用&#xff0c;并在其它平台上发布的情况呢&#xff1f;其实我们可以在图片上添加上个人水印&#xff0c;这样子就可以有效减少图片被人盗用的情况。那你们…

【springboot】20、Spring Boot 整合 MyBatis

文章目录基本介绍1、引入相关依赖2、数据库基本配置3、编写mapper接口和映射文件4、指定Mapper文件的位置5、测试总结基本介绍 MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果…

英伟达RTX 4080正式发布!这一波是谁赢麻了?

在RTX40系列发布之前&#xff0c;我一直以为今年经济不行&#xff0c;直到看到大家抢购4090的样子&#xff0c;才发现只有我的经济不行。 距离英伟达 RTX 4090显卡的发布已经过去了一个月&#xff0c;40系列家族又出一员大将——英伟达 RTX 4080&#xff0c;公版定价9499在上市…

什么是RC低通滤波电路

滤波电路顾名思义就是滤除不需要的信号&#xff0c;保留需要的信号&#xff0c; 其中无源RC滤波电路要数最简单的滤波电路了。 电路图的话大家加可以看下&#xff0c;包含一个电阻和电容。 低通的话就是频率低的信号可以无衰减的通过&#xff0c;频率高得信号会产生衰减&#…

主成分分析(机器学习)

目录 主成分分析&#xff08;PCA&#xff09;是最常用的线性降维方法 设有m条n维数据&#xff0c;PCA的一般步骤如下 主成分分析&#xff08;PCA&#xff09;是最常用的线性降维方法 它的目标是通过某种线性投影&#xff0c;将高维的数据映射到低维的空间中 并期望在所投影的…

如何使用Docker搭建ES集群

1、配置虚拟机 1.1、设置内存 将虚拟机内存设置为4G&#xff0c;内存太小可能导致某个ES节点无法正常运行&#xff1b; 1.2、修改limits.conf limits.conf文件可以设置用户最大可创建文件的数量 a、执行vi /etc/security/limits.conf命令—>文件末尾添加如下内容&#…

计算机毕业设计ssm+vue+elementUI 基于vue的消防物资存储系统

项目介绍 无论是什么行业物资存储都是一个非常重要的内容&#xff0c;只有有了这些良好的物资存储&#xff0c;才能够为后续的工作开展提供便利。消防是一个关系到人民群众安全的工作&#xff0c;所以在消防相关方面的物资存储也是非常重要的内容。为了能够更好的管理好消防相…

电压放大器如何选择型号规格(电压放大器选型标准)

电压放大器是搭配信号发生器来组合使用的电子仪器&#xff0c;使用时通过简单的设备连接&#xff0c;就能拓展信号源的输入电压幅度范围。高电压放大器的快速响应不仅是表现在功率放大器的宽带和压摆率等参数上&#xff0c;同时还和最大输出电流以及负载的电容特性有关系。下面…

48-安装软件并管理服务

48-安装软件并管理服务RPM的概念和操作命令RPM软件包管理RPM软件包管理优缺点RPM命令常用参数DNF的该您概念和操作命令DNF工具的产生DNF工具概述DNF管理软件包DNF-软件源服务DNF配置文件-/etc/dnf/dnf.conf配置DNF-修改配置参数创建本地软件源仓库添加软件源启用和禁用软件源管…

BFS广度优先

题目描述如下&#xff1a; 使用邻接矩阵实现BFS&#xff1a; 输入 8,10 1 2 3 4 5 6 7 8 1,2 1,5 2,6 3,6 3,4 3,7 4,7 4,8 6,7 7,8 2 输出 请输入顶点数和边数:请输入顶点本身的数据: 请输入边的数据: 0 1 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 1 1 1 0 0…

Winsoft Office Component Suite

Winsoft Office Component Suite Winsoft Office组件套件是由Winsoft发布的海豚和CBuilder公司的集合。这些计算机可用于在microsoft office集合中实现自动化和自动操作。从2010年到2019年&#xff0c;这些活动几乎支持了Office的所有现代版本&#xff0c;并提供了两种软件和氧…

掌控安全学院SOL注入靶场

掌控安全学院SOL注入靶场靶场地址Pass-01 显错注入Pass-02Pass-03Pass-04Pass-05 POST注入Pass-06Pass-07 Head注入Pass-08Pass-09Pass-10 布尔盲注Pass-11Pass-12Pass-13 延时注入Pass-14Pass-15 宽字节注入Pass-16Pass-17总结靶场地址 http://inject2.lab.aqlab.cn Pass-01…