今日写题work05
题目:用队列实现栈
思路
队列的特点是先进先出,而栈的特点是后进先出。所以想要用队列实现模拟栈,我们可以使用两个队列,一个队列负责压栈,一个队列负责出栈。压栈很简单就是检空再调用队列的push就好,那出栈呢?这里可以利用另外一个空队列,先把一部分数据给空队列,原来的队列只保留最后一个数据就好,这时再对这个队列出栈,再Pop掉。始终保持一个队列有数据,一个队列为空。两个队列相互交换数据,达到模拟实现栈的效果。
这里的结构实际就是一个套娃,栈包含队列,队列里包含链表
具体实现
首先手搓一个队列,如果是其他语言也可以直接调用库,这里是用c语言。接着实现题目给的函数。
myStackCreate
MyStack* myStackCreate() {MyStack* pst=(MyStack*)malloc(sizeof(MyStack));if(pst==NULL){perror("Malloc Failed\n");return NULL;}QueueInit(&pst->q1);QueueInit(&pst->q2);return pst;
}
这里创建栈要想清楚结构,有三层,其中两层你已经再队列里完成。所以,这里我们还需要再创建一个栈,动态开辟一个指针,用这个指针来维护栈和实现各种功能
myStackPush
void myStackPush(MyStack* obj, int x) {if(!(QueueEmpty(&obj->q1))){QueuePush(&obj->q1,x);}else{QueuePush(&obj->q2,x);}
}
这里压栈还是比较简单,首先检查一下队列是否为空,如果为空就入队另一个队列。当然刚开始入队,两个都为空。所以在检查完一个队列为空后,直接就入队到另一个队列就行了。不用再多余判断了。
myStackPop
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 ret=QueueFront(nonempty);QueuePop(nonempty);return ret;
}
这里出栈是有点复杂,设计到两个队列相互转化。所以,为了逻辑清晰。我们直接创建两个新队列,分别命名为empty和nonempty。这样容易区分,不容易逻辑混乱。
这里我们可以直接选择一个队列赋值给empty,另一个队列赋值给nonempty。在进行检空,如果不对,在进行交换就行。接下来就是依次出队,把头部元素依次入队到empty,依次Pop nonempty队列。当只剩一个数据,循环停止。退出循环后,把剩余的数据出队,Pop队列,返回。这样就实现了后进先出的效果。
myStackTop
int myStackTop(MyStack* obj) {if(!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}
}
这里可以检空再调用QueueBack,这里也把这个函数体现的淋漓尽致。虽然,从队列定义看,这个函数是不合理的。但是这个函数,再很多地方都会用到。所以我们不妨写一下。c++STL中就也有这个函数。
myStackEmpty
bool myStackEmpty(MyStack* obj) {return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
这里返回的是两个队列的检空,因为这个栈是由这两两个队列实现的
myStackFree
void myStackFree(MyStack* obj) {QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj);obj=NULL;
}
这里释放,可不能直接free栈。我们这里队列还需要一个一个释放。如果你直接释放掉栈,那就会内存泄漏。所以我们先调用下队列的销毁函数把两个队列释放掉,再free栈,最后记得置空
代码
typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;
typedef struct Queue
{QNode* head;QNode* tail;int size;
}Queue;
void QueueInit(Queue* pq);
//销毁队列
void QueueDestroy(Queue* pq);
//队尾入队列
void QueuePush(Queue* pq, QDataType x);
//队头出队列
void QueuePop(Queue* pq);
//获取队列头部yuansu
QDataType QueueFront(Queue* pq);
//获取队列尾部元素
QDataType QueueBack(Queue* pq);
//获取队列中有效数据个数
int QueueSize(Queue* pq);
//检测队列是否为空(检空)
bool QueueEmpty(Queue* pq);
void QueueInit(Queue* pq)
{pq->head = pq->tail = NULL;pq->size = 0;
}
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->head;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("Malloc Failed\n");return;}newnode->next = NULL;newnode->data = x;if (pq->head == NULL){assert(pq->tail == NULL);pq->head = pq->tail = newnode;}else{pq->tail->next = newnode;pq->tail = newnode;}pq->size++;
}
void QueuePop(Queue* pq)
{assert(pq);assert(pq->head != NULL);/*QNode* next = pq->head->next;free(pq->head);pq->head = next;if (pq->head == NULL){pq->tail = NULL;}*/if (pq->head->next == NULL){free(pq->head);pq->head = pq->tail = NULL;}else{QNode* next = pq->head->next;free(pq->head);pq->head = next;}pq->size--;
}
QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}typedef struct {Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() {MyStack* pst=(MyStack*)malloc(sizeof(MyStack));if(pst==NULL){perror("Malloc Failed\n");return NULL;}QueueInit(&pst->q1);QueueInit(&pst->q2);return pst;
}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 ret=QueueFront(nonempty);QueuePop(nonempty);return ret;
}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) {QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj);obj=NULL;
}/*** 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);
*/
总结
这里复杂的主要是结构,在具体的函数实现上,如果你思路清晰,其实是比较简单的。比较复杂的就是,出栈这个函数,需要多想一下
题目链接:225. 用队列实现栈 - 力扣(LeetCode)
相关文章:

今日写题work05
题目:用队列实现栈 思路 队列的特点是先进先出,而栈的特点是后进先出。所以想要用队列实现模拟栈,我们可以使用两个队列,一个队列负责压栈,一个队列负责出栈。压栈很简单就是检空再调用队列的push就好,那出…...
[C++语法基础与基本概念] std::function与可调用对象
std::function与可调用对象 函数指针lambda表达式std::function与std::bind仿函数总结std::thread与可调用对象std::async与可调用对象回调函数 可调用对象是指那些像函数一样可以直接被调用的对象,他们广泛用于C的算法,回调,事件处理等机制。…...

两个实用且热门的 Python 爬虫案例,结合动态/静态网页抓取和反爬策略,附带详细代码和实现说明
在这个瞬息万变的世界里,保持一颗探索的心,永远怀揣梦想前行。即使有时会迷失方向,也不要忘记内心深处那盏指引你前进的明灯。它代表着你的希望、你的信念以及对未来的无限憧憬。每一个不曾起舞的日子,都是对生命的辜负࿱…...
华象新闻 | 2月20日前谨慎升级 PostgreSQL 版本
各位 PostgreSQL 用户,建议近期进行升级 PostgreSQL 版本。 2月20日计划进行非周期性版本发布 PostgreSQL全球开发团队计划于2025年2月20日进行一次非周期性发布,以解决2025年2月13日更新版本中引入的一个回归问题。 2月13日的更新版本包括了17.3、16.7、…...
跳跃游戏 II - 贪心算法解法
问题描述: 给定一个长度为 n 的 0 索引整数数组 nums,我们从数组的第一个元素 nums[0] 开始。每个元素 nums[i] 表示从索引 i 可以跳跃的最大长度,换句话说,从位置 i,你可以跳到位置 i j,其中 0 < j &…...

图像质量评价指标-UCIQE-UIQM
一、评价指标UCIQE 在文章《An underwater color image quality evaluation metric》中,提到的了评价指标UCIQE(Underwater Colour Image Quality Evaluation),是一种无参考图像质量评价指标,主要用于评估水下图像的质…...

CentOS上安装WordPress
在CentOS上安装WordPress是一个相对直接的过程,可以通过多种方法完成,包括使用LAMP(Linux, Apache, MySQL, PHP)栈或使用更现代的LEMP(Linux, Nginx, MySQL, PHP)栈。 我选择的是(Linux, Nginx…...

Spring Boot 原理分析
spring-boot.version:2.4.3.RELEASE Spring Boot 依赖管理 spring-boot-starter-parent 配置文件管理 <resources> <resource> <directory>${basedir}/src/main/resources</directory> <filtering>true&l…...

Git 本地项目上传 GitHub 全指南(SSH Token 两种上传方式详细讲解)
前言:Git 与 GitHub 的区别与联系 在学习如何将本地项目上传到 GitHub 之前,先来弄清楚 Git 和 GitHub 的区别以及它们之间的联系。 对比项GitGitHub定义分布式版本控制系统(DVCS),用于本地和远程管理代码版本托管 G…...

jenkins服务启动-排错
服务状态为active (exited) 且进程不在 查看/etc/rc.d/init.d/jenkins配置 获取配置参数 [rootfy-jenkins-prod jenkins]# cat /etc/rc.d/init.d/jenkins | grep -v #JENKINS_WAR"/usr/lib/jenkins/jenkins.war" test -r "$JENKINS_WAR" || { echo "…...

CF 144A.Arrival of the General(Java实现)
题目分析 一个n个身高数据,问最高的到最前面,最矮的到最后面的最短交换次数 思路分析 首先,如果数据有重复项,例如示例二中,最矮的数据就是最后一个出现的数据位置,最高的数据就是最先出现的数据位置&…...
SAP-ABAP:SAP中REPORT程序和online程序的区别对比
在SAP中,REPORT程序和Online程序(通常指Dialog程序)是两种常见的ABAP程序类型,它们在用途、结构和用户交互方式上有显著区别。以下是它们的详细对比: 1. 用途 REPORT程序Online程序主要用于数据查询、报表生成和批量数…...

Java发展史
JavaEE的由来 语言的诞生 Java的前身是Oak语言,其目的是搞嵌入式开发开发智能面包机 叮~~~🍞🍞🍞 产品以失败告终 巅峰 网景公司需要网景浏览器打开网页,Oak->Java,进行前端开发(相关技…...

vue3--SVG图标的封装与使用
流程 终端输入- -安装下面这个包 npm install vite-plugin-svg-icons -Dvite.config.ts文件中引入 import {createSvgIconsPlugin} from vite-plugin-svg-iconsvite.config.ts文件中配置plugins选项 将下面代码 createSvgIconsPlugin({//用于指定包含 SVG 图标的文件夹路径…...

Datawhale Ollama教程笔记3
小白的看课思路: Ollama REST API 是什么? 想象一下,你有一个智能的“盒子”(Ollama),里面装了很多聪明的“小助手”(语言模型)。如果你想让这些“小助手”帮你完成一些任务&#…...

学习数据结构(10)栈和队列下+二叉树(堆)上
1.关于栈和队列的算法题 (1)用队列实现栈 解法一:(参考代码) 题目要求实现六个函数,分别是栈初始化,入栈,移除并返回栈顶元素,返回栈顶元素,判空࿰…...

洛谷 P3660 USACO17FEB Why Did the Cow Cross the Road III 题解
题意 有一个圆,圆周上按顺时针方向给出 2 n 2n 2n个点。第 i i i个点的颜色是 c o l o r i color_i colori,其中数据保证 1 ≤ c o l o r i ≤ n 1\le color_i\le n 1≤colori≤n,而且每种不同的颜色有且只有两个点。不存在位置重叠的点…...

【数据结构】(9) 优先级队列(堆)
一、优先级队列 优先级队列不同于队列,队列是先进先出,优先级队列是优先级最高的先出。一般有两种操作:返回最高优先级对象,添加一个新对象。 二、堆 2.1、什么是堆 堆也是一种数据结构,是一棵完全二叉树,…...
如何提升爬虫获取数据的准确性?
提升爬虫获取数据的准确性是确保数据分析和后续应用有效性的关键。以下是一些经过验证的方法和最佳实践,可以帮助提高爬虫数据的准确性: 1. 数据清洗 数据清洗是提升数据准确性的重要步骤,主要包括去除重复数据、处理缺失值和异常值。 去除…...
Obsidian及Zotero常用的插件
Obsidian插件 Minimal Theme Settings(Life,zotero)【必需】 界面样式设置所需插件 Style Settings(Life,zotero)【必需】界面样式设置所需插件 Recent Files(Life,zotero…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...