用栈实现队列——leetcode刷题

embedded/2024/10/18 18:27:16/

        题目要求我们只用栈的基本操作 push to top 入栈,peek from top 返回栈顶元素,pop from top 移除并返回栈顶元素,size 栈的大小,is_empty 判断栈是否为空,这几个函数来实现队列,也就是说,我们在队列函数push pop peek empty函数中要调用栈的函数实现。

        首先栈的特点是先进后出,队列的特点是先进先出,如何用两个栈来实现先进先出,我们想到可以把一个栈压入另外一个栈,此时第二个栈的顺序相对第一个就是一个倒序,此时在出栈就是相当于首元素出栈,就相当于队列的逻辑。如图所示,我们还要做的就是把 栈2 的剩余元素重新入栈更新 栈1 。

        我们可以把 栈1 理解为队列的真实情况,栈2 只是出队列时寻找队头的工具(负责逆序栈),每次出队列之后都要重新更新 栈1 ,更新队列。

接下来就是代码实现:

typedef struct {struct Stacklist* p1;struct Stacklist* p2;
} MyQueue;
struct Stacklist* Stackcreat() {struct Stacklist* p = (struct Stacklist*)malloc(sizeof(struct Stacklist));return p;
}
void StackInit(struct Stacklist* stack) {stack->cap = 0;stack->size = 0;stack->val = NULL;
}
MyQueue* myQueueCreate() {MyQueue* list = (MyQueue*)malloc(sizeof(MyQueue));list->p1 = Stackcreat();list->p2 = Stackcreat();StackInit(list->p1);StackInit(list->p2);return list;
}

        首先是Queue队列结构体的成员,两个指向栈的指针:栈1 p1,栈2 p2 。其次是创建队列指针,创建队列中两个栈的指针,对他们进行初始化。(这里使用了题目要求之外的函数,个人感觉不妥,当然可以自己写一下)

接着是入队列函数:

void myQueuePush(MyQueue* obj, int x) {StackPush(obj->p1, x);
}

        直接就是入栈函数,因为进入第一个栈就相当于是入队列了。

然后是出队列函数 Pop(移除元素):

int myQueuePop(MyQueue* obj) {while (!is_empty(obj->p1)) {StackPush(obj->p2, StackPop(obj->p1));}int val = StackPop(obj->p2);while (!is_empty(obj->p2)) {StackPush(obj->p1, StackPop(obj->p2));}return val;
}

        我们先把 栈1 的元素压入 栈2 中去,即StackPush(obj->p2, StackPop(obj->p1)); 条件是 栈1 不为空,当条件不满足则说明 栈1 中元素已经全部拷贝到 栈2 中去,接着让 栈2 出栈,记录出栈的数值,然后再把 栈2 拷贝回 栈1 。这一流程就是刚才的图的流程。

然后是查看队头数值函数 Peek(不移除元素,仅查看):

int myQueuePeek(MyQueue* obj) {while (!is_empty(obj->p1)) {StackPush(obj->p2, StackPop(obj->p1));}int val = StackPeek(obj->p2);while (!is_empty(obj->p2)) {StackPush(obj->p1, StackPop(obj->p2));}return val;
}

        逻辑和出队列函数一样,只不过val赋值时使用的是StackPeek函数,也就是只查看不删除的"出栈"函数。

最后是判断队列是否为空的函数:

bool myQueueEmpty(MyQueue* obj) {if (is_empty(obj->p1)) {return true;}else {return false;}
}

        直接根据 栈1 是否为空来判断队列是否为空即可,因为我们每次都会拷贝回 栈1 保证 栈1 是队列的真实元素。

最后补充一下销毁函数:

void myQueueFree(MyQueue* obj) {StackDes(obj->p1);StackDes(obj->p2);free(obj);obj = NULL;
}
void StackDes(struct Stacklist* stack) {free(stack->val);stack->val = NULL;
}

        这里我我同样使用了外部函数,可以整合一下。

这就是文章的全部内容了,希望对你有所帮助,如有错误欢迎评论。


http://www.ppmy.cn/embedded/28314.html

相关文章

ClickHouse安装(成功安装)

1.下载安装包 下面通过阿里镜像(https://mirrors.aliyun.com/clickhouse/rpm/lts/)进行下载,下载哪里,自行指定。 # deb包下载使用如下4行 wget https://mirrors.aliyun.com/clickhouse/deb/pool/stable/clickhouse-client_22.8…

Python项目开发实战:怎么基于Keras的深度学习来预测房价

注意:本文的下载教程,与以下文章的思路有相同点,也有不同点,最终目标只是让读者从多维度去熟练掌握本知识点。 下载教程:深度学习-基于Keras的Python项目开发实战_波士顿房价预测_编程案例实例教程.pdf 一、引言 在当今信息化社会,房价预测已成为金融、房地产及相关领域…

一加Ace3/12/Ace2pro手机ColorOS14刷KernelSU内核ROOT-解决无限重启变砖

一加Ace3/一加12/一加11等手机升级了安卓14底层,并且ColorOS版本也更新到了14版本界面和功能都比之前的系统表现更加优秀,但刷机方面,相对之前存在一些差异,特别是KernelSU内核级别root权限,不再支持一键刷入KernelSU通…

Android13锁屏或灭屏状态下,快速按两次音量下键实现打开闪光灯功能

实现思路: 1、发送广播 WindowManagerService循环读取下面按键消息并分发给窗口,在消息分发前会在PhoneWindowManager.interceptKeyBeforeQueueing方法中进行消息的过滤。因此该实现方式为在消息分发前的interceptKeyBeforeQueueing方法中监听当前按键为…

【ARM Cache 系列文章 11.1 -- ARM Cache 全相连 详细介绍】

请阅读【ARM Cache 系列文章专栏导读】 文章目录 Cache 全相连(Fully Associative)全相联映射示例全相联映射原理紧接文章:【ARM Cache 系列文章 11 – ARM Cache 组织形式详细介绍】 Cache 全相连(Fully Associative) 介绍: 在全相连缓存中,任何内存地址都可以缓存在 …

ssm项目后端如何导出war及前端如何导出静态资源

后端如何导出war包 后端工具:IDEA 2020.1.3 运行我们编写工具maven里面的package 运行成功的日志 我们运行完,会生成一个target文件夹,在这个文件夹里面找到war包即可 前端如何导出静态资源 使用工具:WebStorm 2020.1.3 打开左…

PyCharm 2024新版图文安装教程(python环境搭建+PyCharm安装+运行测试+汉化+背景图设置)

名人说:一点浩然气,千里快哉风。—— 苏轼《水调歌头》 创作者:Code_流苏(CSDN) 目录 一、Python环境搭建二、PyCharm下载及安装三、解释器配置及项目测试四、PyCharm汉化五、背景图设置 很高兴你打开了这篇博客,如有疑问&#x…

配置及使用OpenCV(Python)

python配置OpenCV相对于c的配置方法容易的多,但建议在Anaconda中的Python虚拟环境中使用,这样更方便进行包管理和环境管理: 先激活Anaconda的python虚拟环境: conda activate GGBoy 随后下载 opencv 包: conda ins…