[C/C++] 数据结构 LeetCode:用队列实现栈

news2024/12/23 22:53:37

题目描述:

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

实现 MyStack 类:

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

注意:

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

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

功能实现思路:

在实现这个题目之前得先完成队列的基本操作,可以参考文章:http://t.csdnimg.cn/3v2IZ

1. 出栈 

现在我们有两个队列,假设在第一个队列里依次入了1 2 3 4 5,另一个队列为空队列

现在要出栈的话,应该把5出去,但是数据目前在队列里,出数据只能从队头出,所以可以把1 2 3 4依次出队列,并入到第二个队列中,此时就可以把5出去了,此时又是一个队列为空,另一个存着剩余的数据,再出栈的话,还按照这个方法即可

int myStackPop(MyStack* obj) {
    //由于不知道哪个队列为空队列,可以采用假设法
    Queue* empty = &obj->queue1;
    Queue* nonempty=&obj->queue2;
    if(!QueueEmpty(&obj->queue1))
    {
        empty=&obj->queue2;
        nonempty=&obj->queue1;
    }
    
    while(QueueSize(nonempty)>1)
    {
        QueuePush(empty,QueueFront(nonempty));
        QueuePop(nonempty);
    }
    int top=QueueFront(nonempty);
    QueuePop(nonempty);
    return top;
}

总结:

出栈操作相当于非空队列的队尾元素出队,此时需要把非空队列除最后一个元素之外的其他元素入队到空队列,然后出队最后一个队尾元素

2.入栈

入栈操作相当于在非空队列进行入队操作


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

3.判空

只要两个队列都没有元素就表示栈空

bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->queue1)&&QueueEmpty(&obj->queue2);
}

4.返回栈顶元素

即返回非空队列队尾元素

int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&obj->queue1))
    {
        return QueueTail(&obj->queue1);
    }
    else
    {
        return QueueTail(&obj->queue2);
    }
}
typedef int QDataType;
typedef struct QueueNode {
	QDataType x;
	struct QueueNode* next;
}Node;

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

void QueueInit(Queue* ps);
void QueuePush(Queue* ps,QDataType x);
void QueuePop(Queue* ps);
bool QueueEmpty(Queue* ps);
QDataType QueueFront(Queue* ps);
QDataType QueueTail(Queue* ps);
int QueueSize(Queue* ps);
void QueueDestory(Queue* ps);

void QueueInit(Queue* ps)
{
	assert(ps);

	ps->head = ps->tail = NULL;
	ps->size = 0;
}

void QueuePush(Queue* ps, QDataType x)
{
	assert(ps);
	//创建新节点
	Node* newnode = (Node*)malloc(sizeof(Node));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}
	newnode->next = NULL;
	newnode->x = x;

	//尾插
	if (ps->tail == NULL)
	{
		ps->head = ps->tail = newnode;
	}
	else
	{
		ps->tail->next = newnode;
		ps->tail = ps->tail->next;
	}
	ps->size++;
}

void QueuePop(Queue* ps)
{
	assert(ps);
	assert(ps->head);

	if (ps->head->next == NULL)
	{
		ps->head = ps->tail = NULL;
	}
	else
	{
		Node* next = ps->head->next;
		free(ps->head);
		ps->head = next;
	}
	
	ps->size--;
}

bool QueueEmpty(Queue* ps)
{
	assert(ps);

	return ps->tail == NULL;
}

QDataType QueueFront(Queue* ps)
{
	assert(ps);
	assert(ps->head);

	return ps->head->x;
}

QDataType QueueTail(Queue* ps)
{
	assert(ps);
	assert(ps->tail);

	return ps->tail->x;
}

int QueueSize(Queue* ps)
{
	assert(ps);
	return ps->size;
}

void QueueDestory(Queue* ps)
{
	assert(ps);

	Node* cur = ps->head;
	while (cur)
	{
		Node* next = cur->next;
		free(cur);
		cur = next;
	}

	ps->head=ps->tail = NULL;
    ps->size=0;
}

typedef struct {
    Queue queue1;
    Queue queue2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* mystack=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&mystack->queue1);
    QueueInit(&mystack->queue2);
    return mystack;
}

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

int myStackPop(MyStack* obj) {
    Queue* empty = &obj->queue1;
    Queue* nonempty=&obj->queue2;

    if(!QueueEmpty(&obj->queue1))
    {
        empty=&obj->queue2;
        nonempty=&obj->queue1;
    }
    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->queue1))
    {
        return QueueTail(&obj->queue1);
    }
    else
    {
        return QueueTail(&obj->queue2);
    }
}

bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->queue1)&&QueueEmpty(&obj->queue2);
}

void myStackFree(MyStack* obj) {

    QueueDestory(&obj->queue1);
    QueueDestory(&obj->queue2);

    free(obj);
}

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

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

相关文章

【半监督学习】CNN与Transformer的结合

本文介绍了几篇结合使用CNN和Transformer进行半监督学习的论文,CNN&Trans(MIDL2022),Semi-ViT(ECCV2022),Semiformer(ECCV2022). Semi-Supervised Medical Image Seg…

ComText让机器人有了情节记忆

为了让人类与机器人更好地交流,MIT 计算机科学与人工智能实验室的研究员开发了一个名为 ComText 的程序。这款程序给机器人增加了情节记忆,让它们能够接受更加复杂的命令。目前,他们已经在机器人 Baxter 上测试了程序。 机器人没有情景化的记…

.babyk勒索病毒解析:恶意更新如何威胁您的数据安全

导言: 在数字时代,威胁不断进化,其中之一就是.babyk勒索病毒。这种病毒采用高级加密算法,将用户文件锁定,并要求支付赎金以获取解密密钥。本文91数据恢复将深入介绍.babyk勒索病毒的特点、如何应对被加密的数据&#…

Spring Framework IOC依赖查找 - 按名称查找解析

IoC按名称查找共分为三类: 按名称按类型按集合 按名称查找 在Spring Framework中,实时加载和延迟加载是指在容器启动时是否立即实例化bean的不同策略。下面我们将分别介绍这两种加载方式及其应用场景。 tips: 当涉及到懒加载和延时加载时&#xff0…

vue3的Watch使用详解

vue官网提到: watch 的第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组: 1.监听单个Ref 2.监听一个getter函数 当然只修x或者y其中一个的值,…

阿里AoneFlow分支管理

分支模式 1.TrunkBased模式 工作方式 TrunkBased 模式是持续集成思想所崇尚的工作方式,它由单个主干分支和许多发布分支组成,每个发布分支在特定版本的提交点上从主干创建出来,用来进行上线部署和 Hotfix(补丁)。 …

类和对象(8):explicit,static成员,友元,内部类

一、explicit class Date { public:Date(int year 2023, int month 1, int day 1):_year(year),_month(month),_day(day){}private:int _year;int _month;int _day; };int main() {// Date d1(1); // 这是正常初始化Date d1 1;return 0; }不妨猜测一下,d1的初始…

算法设计与分析复习--动态规划

文章目录 上一篇动态规划性质矩阵连乘问题凸多边形最优三角部分最长公共子序列0-1背包问题下一篇 上一篇 算法设计与分析复习–递归与分治(二) 动态规划性质 与分析法类似:将原问题分解为子问题 不同点:不是通过递归的方式&…

pytest测试框架介绍(1)

又来每天进步一点点啦~~~ 一、Pytest介绍: pytest 是一个非常成熟的全功能的Python测试框架; pytest 简单、灵活、易上手; 支持参数化 能够支持简单的单元测试和复杂的功能测试,可以做接口自动化测试(pytestrequests&…

【Qt开发流程之】窗口部件

qt类关系图 创建Qt项目时,发现提供的窗体默认 基类有:QMainWindow、QDialog、QWidget这三种。 之后,你会发现,这3中窗体在UI交互中,用的也是最多的。 以下是Qt类关系图: 基础窗口控件QWidget 由上图可以…

分享禁止Win10更新的两种方法

深恶痛绝 Windows更新简直就是毒瘤,总是在某些不需要的时候提示更新,而且关闭服务后总有办法重启。老是关不掉。 如果每次都是正常更新,好像也没啥所谓,但是总有那么一两次会蓝屏、黑屏、开不了机…… 52出品 下面是吾爱社区找…

设计模式(二)-创建者模式(2-0)-简单工厂模式

一、简单工厂模式定义 客户端不需要关注创建实例的过程。于是需要通过工厂模式,要把创建对象过程和使用对象进行分离。所以客户端只要使用对象即可,而创建对象过程由一种类来负责,该类称为工厂类。 由于创建实例的方式是在静态方法里实现的…

数睿通2.0数据接入、数据开发、系统权限、集群监控全面升级

引言 数睿通 2.0 数据中台迎来了11月份的更新,感谢大家的支持,本次更新主要包括以下内容: 数据库支持 MongoDB数据接入支持 MongoDB,支持自定义 SQL 采集,支持停止运行中的任务数据生产支持 FlinkJar 任务&#xff0…

线性变换功能块S_RTI工程上的主要应用

西门子S_RTI模拟量转换功能块算法公式和代码介绍请参考下面文章链接: PLC模拟量输出 模拟量转换FC S_RTI-CSDN博客文章浏览阅读5.3k次,点赞2次,收藏11次。1、本文主要展示西门子博途模拟量输出转换的几种方法, 方法1:先展示下自编FC:计算公式如下:intput intput Real IS…

OS 进程同步

基本概念 定义:把异步环境下的一组并发进程因直接制约而相互发送消息、相互合作、相互等待,使得各进程按一定的速度执行的过程,称为进程同步 协作进程:具有同步关系的一组并发进程 进程同步机制的主要任务:在执行次…

Linux调试器:gdb的使用

我们知道在Visual Studio2022中,我们可以对编好的代码进行调试来分析dug的位置,那Linux环境下如何进行程序的调试呢?那就是使用Linux调试器:gdb。 目录 1.背景 2. 开始使用 1.背景 程序的发布方式有两种,debug模式…

mysql的行列互转

mysql的行列互转 多行转多列思路实现代码 多列转多行思路代码 多行转多列 多行转多列,就是数据库中存在的多条具有一定相同值的行数据,通过提取相同值在列头展示来实现行数据转为列数据,一般提取的值为枚举值。 思路 转换前表样式 -> 转…

从 0 开始手写一个 Mybatis 框架,三步搞定!

MyBatis框架的核心功能其实不难,无非就是动态代理和jdbc的操作,难的是写出来可扩展,高内聚,低耦合的规范的代码。本文完成的Mybatis功能比较简单,代码还有许多需要改进的地方,大家可以结合Mybatis源码去动手…

打开游戏提示xapofx1_5.dll丢失如何修复?xapofx1_5.dll缺失的修复教程分享

xapofx1_5.dll是一个重要的Windows系统文件,它主要负责处理图形渲染和多媒体功能。如果在计算机中找不到xapofx1_5.dll,可能会导致程序无法正常运行。下面是关于xapofx1_5.dll丢失的4个修复方法以及xapofx1_5.dll的作用和丢失原因的介绍。 一、xapofx1_…

MySQL 教程 1.2

上期教程网友笔记整理 MySQL 重置密码 如果你忘记 MySQL 密码,可以通过修改 my.cnf 文件添加 skip-grant-tables 来重置密码,步骤如下: 1、打开 my.cnf 配置文件,找到 [mysqld] ,然后在该行下面添加以下参数&#x…