Leetcode刷题之用队列实现栈(C语言版)

news2024/11/17 13:55:50

Leetcode刷题之用队列实现栈(C语言版)

  • 一、题目描述
  • 二、题目要求
  • 三、题目示例
  • 四、题目解析
    • Ⅰ、MyStack* myStackCreate
    • Ⅱ、void myStackPush(MyStack* obj, int x)
    • Ⅲ、int myStackPop(MyStack* obj)
    • Ⅳ、int myStackTop(MyStack* obj)
    • Ⅴ、bool myStackEmpty(MyStack* obj)
    • Ⅵ、void myStackFree(MyStack* obj)
  • 五、完整代码

225、用队列实现栈

一、题目描述

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

实现 MyStack 类:

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

二、题目要求

Ⅰ、你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
Ⅱ、你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

三、题目示例

在这里插入图片描述

四、题目解析

首先我们看到本题是用队列实现栈。那么我们便要对栈和队列的相关特性有一定的了解,例如栈是先进后出的,而队列是先进先出的。如果有伙伴对这两种数据结构有些遗忘的话,建议看一下博主之前的两篇文章,分别是《数据结构——栈的详细介绍》和《数据结构——看完这篇保证你学会队列》。
我们想要解决这道题,首先便要实现一个完整的队列,其中的接口包括初始化队列,销毁队列,入队,出队等,其代码如下:
在这里插入图片描述

//定义数据类型
typedef int QueueDataType;
//定义队列结构
typedef struct QueueNode
{
	struct QueueNode* next;
	QueueDataType Data;
}Qnode;


//定义头、尾指针
typedef struct Queue
{
	Qnode* phead;
	Qnode* ptail;
	int size;
}Queue;

//初始化
void InitQueue(Queue* pq);
//销毁
void DestoryQueue(Queue* pq);
//入队
void PushQueue(Queue* pq, QueueDataType x);
//出队
void PopQueue(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//获取SIze
int SizeQueue(Queue* pq);
//获取队头元素
QueueDataType QueueFront(Queue* pq);
//获取队尾元素
QueueDataType QueueBack(Queue* pq);

void InitQueue(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
//销毁
void DestoryQueue(Queue* pq)
{
	assert(pq);
	Qnode* cur = pq->phead;
	while (cur)
	{
		Qnode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//入队
void PushQueue(Queue* pq, QueueDataType x)
{
	assert(pq);
	Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	//赋值
	newnode->Data = x;
	newnode->next = NULL;
	//分情况讨论
	if (pq->ptail == NULL)
	{
		assert(pq->phead == NULL);
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
//出队
void PopQueue(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	//一个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	//多个节点
	else
	{
		//头删
		Qnode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;

}
//判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}
//获取SIze
int SizeQueue(Queue* pq)
{
	assert(pq);
	return pq->size;
}
//获取队头元素
QueueDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->phead->Data;
}
//获取队尾元素
QueueDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->ptail->Data;
}

构建好队列的各种接口之后,我们需要在Mystack的结构体中创建两个队列变量。代码如下:

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

Ⅰ、MyStack* myStackCreate

该接口,需要我们在内存中开辟空间,利用malloc函数,并且将q1和q2进行初始化。

MyStack* myStackCreate() 
{
  MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
  if(obj==NULL)
  {
      perror("malloc fail");
      return NULL;
  }
  InitQueue(&obj->q1);
  InitQueue(&obj->q2);
  return obj;
    
}

Ⅱ、void myStackPush(MyStack* obj, int x)

如果两个队列都为空,那么任选一个进行入队操作即可,后续入队往有数据的队列进行入队操作即可。

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

Ⅲ、int myStackPop(MyStack* obj)

最为复杂的便是出栈了,我们的大体思路便是假定q1为空,q2不为空:如果结果相反,则调换一下二者的顺序,我们将不为空的队列进行出队操作,并将其数据压入为空的队列,直到为空的队列中只剩下一个数据,我们将这个数据定义为top,并对其进行出队操作,最后将其进行返回。

 Queue*EmptyQ=&obj->q1;
       Queue*NonEmptyq=&obj->q2;
       if(!QueueEmpty(&obj->q1))
       {
           EmptyQ=&obj->q2;
           NonEmptyq=&obj->q1;
       }
       while(SizeQueue(NonEmptyq)>1)
       {
           PushQueue(EmptyQ,QueueFront(NonEmptyq));
           PopQueue(NonEmptyq);
       }
       int top=QueueFront(NonEmptyq);
       PopQueue(NonEmptyq);
       return top;

Ⅳ、int myStackTop(MyStack* obj)

解决这个接口,我们首先需要找到不为空的那个队列,然后调用其获取队尾数据的函数,最后将这个函数返回的结果返回即可。

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

Ⅴ、bool myStackEmpty(MyStack* obj)

我们需要保证我们的两个队列都为空,这样才能够保证我们创建的队列为空。

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

Ⅵ、void myStackFree(MyStack* obj)

需要先对我们所创建的q1和q2队列进行销毁,然后再对ob进行free操作,以防止内存的泄漏。

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

五、完整代码

//定义数据类型
typedef int QueueDataType;
//定义队列结构
typedef struct QueueNode
{
	struct QueueNode* next;
	QueueDataType Data;
}Qnode;


//定义头、尾指针
typedef struct Queue
{
	Qnode* phead;
	Qnode* ptail;
	int size;
}Queue;

//初始化
void InitQueue(Queue* pq);
//销毁
void DestoryQueue(Queue* pq);
//入队
void PushQueue(Queue* pq, QueueDataType x);
//出队
void PopQueue(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//获取SIze
int SizeQueue(Queue* pq);
//获取队头元素
QueueDataType QueueFront(Queue* pq);
//获取队尾元素
QueueDataType QueueBack(Queue* pq);

void InitQueue(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
//销毁
void DestoryQueue(Queue* pq)
{
	assert(pq);
	Qnode* cur = pq->phead;
	while (cur)
	{
		Qnode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}
//入队
void PushQueue(Queue* pq, QueueDataType x)
{
	assert(pq);
	Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	//赋值
	newnode->Data = x;
	newnode->next = NULL;
	//分情况讨论
	if (pq->ptail == NULL)
	{
		assert(pq->phead == NULL);
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
//出队
void PopQueue(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	//一个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	//多个节点
	else
	{
		//头删
		Qnode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;

}
//判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}
//获取SIze
int SizeQueue(Queue* pq)
{
	assert(pq);
	return pq->size;
}
//获取队头元素
QueueDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->phead->Data;
}
//获取队尾元素
QueueDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->ptail->Data;
}


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


MyStack* myStackCreate() 
{
  MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
  if(obj==NULL)
  {
      perror("malloc fail");
      return NULL;
  }
  InitQueue(&obj->q1);
  InitQueue(&obj->q2);
  return obj;
    
}

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&obj->q1))
    {
        PushQueue(&obj->q1,x);
    }
    else
    {
       PushQueue(&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(SizeQueue(NonEmptyq)>1)
       {
           PushQueue(EmptyQ,QueueFront(NonEmptyq));
           PopQueue(NonEmptyq);
       }
       int top=QueueFront(NonEmptyq);
       PopQueue(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) 
{
  DestoryQueue(&obj->q1);
  DestoryQueue(&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/1247274.html

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

相关文章

你知道,葡萄酒不同的酿造工艺也能分类吗?

一串长在藤上的葡萄变成一杯美酒,是多么神奇的事情。而背后的魔法师就是葡萄酒的酿造工艺。经过数千年的酿酒经验累积,目前葡萄酒的种类繁多,酿造工艺也越来越多样化,不同的细节和工艺决定了不同形态的葡萄酒。所以,葡…

openEuler 22.03 LTS x86_64 cephadm 部署ceph16.2.14 【2】添加mon

接上篇 openEuler 22.03 LTS x86_64 cephadm 部署ceph18.2.0 未完成 笔记-CSDN博客 故障 /usr/libexec/podman/catatonit: no such file or directory [rootnode-1 ~]# cephadm bootstrap --mon-ip 10.47.76.94 --skip-pull Verifying podman|docker is present... Verifyin…

设置定时自动请求测试_自动定时循环发送http_post请求---postman工作笔记001

其实就是创建接口文件夹的时候,有个monitor collection 用来监听接口执行情况,这里就可以设置 可以看到多久执行一次对吧,这里可以设置每几分钟执行一次,一共执行多少次等等 但是这里要说明一下,如果需要使用monitor功能,必须需要登录, 所以如果这里点击monitor collection…

医保线上购药系统:代码驱动的医疗创新

医保线上购药系统,这是一个融合技术和医疗的创新典范。本文将通过简单的技术代码示例,为您揭示这一系统是如何通过技术驱动医疗创新,为用户提供更智能、便捷的健康管理体验的。 1. 前端界面开发 使用React框架,我们可以轻松构建…

工业以太网交换机的特点

交换机的使用范围非常广泛,可以说只有需要进行网络连接的地方,基本上都会与交换机有关。但是工业以太网交换机的适用范围相对较小,主要用于工业控制领域的以太网交换设备。工业以太网交换机拥有电信级的性能特征,能够适应苛刻的工…

【亚太杯B题论文已更新】2023年第十三届APMCM亚太地区大学生数学建模竞赛——(文末领取方式)

2023年第十三届APMCM亚太地区大学生数学建模竞赛——论文无偿分享!!! B题第一问论文代码已出,其他赛题及后续论文代码会持续更新。 祝各位小伙伴都能在比赛中发挥出色,取得心仪的成绩呦!一起加油&#xff…

java编程:使用递归 循环和位运算实现将10进制转为2进制

1 递归 /*** 递归&#xff1a;十进制转二进制* param decimal 待转换的十进制数* param binary 转换后的二进制数*/public static void decimalToBinaryByRecursion(int decimal,StringBuilder binary){if(decimal < 0){return;}decimalToBinaryByRecursion(decimal/2,bina…

用 VirtualBox 安装 OpenWrt 等 Linux 系统,无法启动的解决办法

用 VirtualBox 安装 OpenWrt 等 Linux 系统&#xff0c;无法启动的解决办法 最近新买了台联想小新 Pro 14 2023 锐龙版&#xff0c;因为有 32GB 的运行内存&#xff0c;所以想安装虚拟机以充分发挥。一开始使用 Hyper-V 来安装可以正常使用&#xff0c;但是后面想使用 Virtual…

数据库表结构导出成Excel或Word格式

前言 该工具主要用于导出excel、word&#xff0c;方便快速编写《数据库设计文档》&#xff0c;同时可以快速查看表的结构和相关信息。 本博客仅作记录&#xff0c;最新源码已经支持多种数据库多种格式导出&#xff0c;有兴趣的可移步源码作者地址&#xff1a;https://gitee.co…

基于LiteFlow构建实时会员权益体系

知识简介&#xff1a;通过LiteFlow规则引擎构建会员权益体系&#xff0c;实现权益节点可插拔&#xff0c;可编排&#xff0c;可复用的特性。完成会员权益数据底盘建设&#xff0c;将分散的权益数据集中&#xff0c;提升权益查询及管理水平。 历史痛点 1&#xff09;不同等级权…

Grafana 如何实现雷达图

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

「德州仪器嵌入式技术创新发展研讨会」落幕,飞凌嵌入式携手TI推动技术创新

11月22日&#xff0c;德州仪器嵌入式技术创新发展研讨会&#xff08;北京站&#xff09;顺利举行&#xff0c;本次研讨会邀请了众多业界领先的企业和专家到场&#xff0c;飞凌嵌入式作为TI生态伙伴受邀参加&#xff0c;与众多业内伙伴共话嵌入式技术的未来发展趋势。 在本次研…

Pix2Pix 使用指南:从原理到项目应用

Pix2Pix Pix2Pix 介绍&#xff1a;使用条件 GAN 进行图像到图像的转换Pix2Pix 原理Pix2Pix 模型结构生成器&#xff1a;Unet结构判别器&#xff1a;PatchGAN目标函数 Pix2Pix 项目使用 Pix2Pix 介绍&#xff1a;使用条件 GAN 进行图像到图像的转换 Pix2Pix 论文&#xff1a;ht…

安防系统智能视频监控中出现画面异常该如何自检?

大家都知道&#xff0c;在当今社会&#xff0c;摄像头无处不在&#xff0c;除了常见的生活与工作场景中&#xff0c;在一些无法人员无法长期驻点场景&#xff0c;如野生动物监测、高空作业监控、高压电缆监控等场景&#xff0c;在这些地方安装摄像头就是为方便日常监控。但是由…

leaflet对线设置渐变色

效果展示: 引用leaflet-polycolor组件 npm install leaflet-polycolor .vue文件中使用 import leafletPolycolor from leaflet-polycolor; leafletPolycolor(L); const latLngs = [[37.03, 111.92], [37.53444, 111.98555], [36.88, 112.12], [37.53444, 112.24], [36.88, 1…

node-red - 节点实战总结1

node-red - 节点实战总结1 二、功能2.1 循环(for\while) 三、网络四、序列五、解析六、存储七、协议7.1 modbus协议7.2 opcua 八、formats8.1 时间格式化与时区转换 二、功能 2.1 循环(for\while) 安装节点node-red-contrib-loop-processing,该节点支持三种方式的循环&#xf…

Linux:配置Ubuntu系统的镜像软件下载地址

一、原理介绍 好处&#xff1a;从国内服务器下载APT软件&#xff0c;速度快。 二、配置 我这里配置的是清华大学的镜像服务器地址 https://mirrors.tuna.tsinghua.edu.cn/ 1、备份文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak2、清空sources.list ec…

openEuler 22.03 LTS x86_64 cephadm 部署ceph 16.2.14 未完成 笔记

环境 准备三台虚拟机 10.47.76.94 node-1 10.47.76.95 node-2 10.47.76.96 node-3 下载cephadm [rootnode-1 ~]# yum install cephadm Last metadata expiration check: 0:11:31 ago on Tue 21 Nov 2023 10:00:20 AM CST. Dependencies resolved. Package …

【python入门篇】函数(6)

这一节将详细介绍Python中函数的用法&#xff0c;包括函数的定义、调用、参数、返回值、作用域等。 函数的概述&#xff1a; Python函数是一种封装了特定任务的可重用代码块。通过将程序分解为更小、更具体的任务&#xff0c;函数提供了一种有效的方式来组织和管理代码&#xf…