队列实现栈VS栈实现队列
目录
【1】用队列实现栈
思路分析
易错总结
Queue.c&Queue.h手撕队列
声明栈MyStack
创建&初始化栈myStackCreate
压栈myStackPush
出栈&返回栈顶元素myStackPop
返回栈顶元素myStackTop
判断栈空否myStackEmpty
释放空间myStackFree
MyStack总代码
【2】用栈实现队列
思路分析
易错总结
Stack.h&Stack.c手撕栈
声明队列MyQueue
创建&初始化队列myQueueCreate
入队列myQueuePush
返回队头元素myQueuePeek
出队列&返回队头元素myQueuePop
判断队列空否myQueueEmpty
释放空间myQueueFree
MyQueue总代码
昨天导游考试考完啦!!希望明年是导游小唐!!🙂当然,代码我们不能忘敲代码!!
【1】用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(
push、top、pop和empty)。实现
MyStack类:
void push(int x)将元素 x 压入栈顶。int pop()移除并返回栈顶元素。int top()返回栈顶元素。boolean empty()如果栈是空的,返回true;否则,返回false。

思路分析 
- 压栈:把元素放到不为空的队列里面。(两者若都为空随便放一个)
- 出栈:把不为空的队列里面元素>1,全部导入另外一个为空队列里面,Pop最后元素。
易错总结
- 创建的临时变量出了作用域就销毁了,所以需要malloc才可。
- 类型匹配的问题
- 假设法的使用
- 销毁的时候要先销毁队列开辟的空间,不然会造成野指针。
- 匿名结构体
- 耦合性
- -> 优先级高于&

Queue.c&Queue.h手撕队列
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int QDataType;
//创建队列节点
typedef struct QueueNode
{QDataType val;struct QueueNode* next;
}QNode;
//两个指针维护链表队列
typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;
//接口的实现
void QueueInit(Queue* pq);//初始化
void QueueDestroy(Queue* pq);//空间释放
void QueuePush(Queue* pq, QDataType x);//放元素到队列尾
void QueuePop(Queue* pq);//出元素到队头
QDataType QueueFront(Queue* pq);//队列头的元素
QDataType QueueBack(Queue* pq);//队列尾的元素
bool QueueEmpty(Queue* pq);//判断队列是否是否为NULL
int QueueSize(Queue* pq);//队列里面的元素个数
//不需要头节点,初始化
void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
QNode* Createnode(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));newnode->val = x;newnode->next = NULL;return newnode;
}
//Push元素
void QueuePush(Queue* pq, QDataType x)
{assert(pq);//创建节点QNode* newnode = Createnode(pq,x);if (pq->phead == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}
//Pop元素
void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);//为NULL的判断QNode* cur = pq->phead;pq->phead = pq->phead->next;free(cur);cur = NULL;//为一个节点的判断if (pq->phead == NULL){pq->ptail = NULL;}pq->size--;
}
//队头元素
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}
//队尾元素
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}
//判断是否为NULL
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;//return pq->size == 0
}
//队员元素个数
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}
//空间释放
void QueueDestroy(Queue* pq)
{assert(pq);while (pq->phead){QNode* cur = pq->phead;pq->phead = pq->phead->next;free(cur);cur = NULL;}pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
在之前的博文里面,我们详细的阐述了单链表实现【队列】的实现。这里就不在过多解释了。这里我们来用【两个队列】实现一个【栈】🆗!
声明栈MyStack
//匿名结构体
typedef struct {Queue Q1;Queue Q2;
} MyStack;//结构体类型
//一级指针修改结构体变量
struct {Queue Q1;Queue Q2;
} MyStack;//结构体变量
创建&初始化栈myStackCreate
//初始化
MyStack* myStackCreate() {//MyStack mystack;出了作用域就销毁了MyStack*obj=(MyStack*)malloc(sizeof(MyStack));QueueInit(&obj->Q1);QueueInit(&obj->Q2);return obj;
}
压栈myStackPush
//放元素
void myStackPush(MyStack* obj, int x) {assert(obj);//找不为NULL的队列依次插入if(!QueueEmpty(&obj->Q1))//!=0{QueuePush(&obj->Q1, x);//尾插}else//== 0{QueuePush(&obj->Q2, x);}//两个==0 随便进一个
}
出栈&返回栈顶元素myStackPop
//出元素
int myStackPop(MyStack* obj) {assert(obj);//判断为空/非空------假设法Queue*nonempty=&obj->Q1;Queue*empty=&obj->Q2;if(QueueEmpty(&obj->Q1))//==0true与上面逻辑相反//出了作用域就销毁了姐姐❌{nonempty=&obj->Q2;empty=&obj->Q1;//创建}while(QueueSize(nonempty)>1)//队列里面的元素个数 > 1{int x = QueueFront(nonempty);//队列头的元素QueuePush(empty, x);//放元素到队列尾QueuePop(nonempty);//出元素到队头}int Back=QueueFront(nonempty);//队列尾的元素QueuePop(nonempty);return Back;
}
返回栈顶元素myStackTop
//栈顶元素
int myStackTop(MyStack* obj) {if(!QueueEmpty(&obj->Q1)) {return QueueBack(&obj->Q1);}else{return QueueBack(&obj->Q2);}
}
判断栈空否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;
}
MyStack总代码
typedef struct {Queue Q1;Queue Q2;
} MyStack;
//一级指针修改结构体变量//初始化
MyStack* myStackCreate() {//MyStack mystack;出了作用域就销毁了MyStack*obj=(MyStack*)malloc(sizeof(MyStack));QueueInit(&obj->Q1);QueueInit(&obj->Q2);return obj;
}//放元素
void myStackPush(MyStack* obj, int x) {assert(obj);//找不为NULL的队列依次插入if(!QueueEmpty(&obj->Q1))//!=0{QueuePush(&obj->Q1, x);//尾插}else//== 0{QueuePush(&obj->Q2, x);}//两个==0 随便进一个
}//出元素
int myStackPop(MyStack* obj) {assert(obj);//判断为空/非空------假设法Queue*nonempty=&obj->Q1;Queue*empty=&obj->Q2;if(QueueEmpty(&obj->Q1){nonempty=&obj->Q2;empty=&obj->Q1;//创建}while(QueueSize(nonempty)>1)//队列里面的元素个数 > 1{int x = QueueFront(nonempty);//队列头的元素QueuePush(empty, x);//放元素到队列尾QueuePop(nonempty);//出元素到队头}int Back=QueueFront(nonempty);//队列尾的元素QueuePop(nonempty);return Back;
}//栈顶元素
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;
}
【2】用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
push、pop、peek、empty):实现
MyQueue类:
void push(int x)将元素 x 推到队列的末尾int pop()从队列的开头移除并返回元素int peek()返回队列开头的元素boolean empty()如果队列为空,返回true;否则,返回false

思路分析


- 一个栈S1用来专门入数据Push
- 另外一个栈S2用来专门出数据Pop(S2为空的时候才能把S1的数据导入S2 直到S1为空)
- S2不为空的时候直接出数据即可
- 队列出数据的顺序性质 == 栈导入另外一个栈出数据的顺序
易错总结
- 创建的临时变量出了作用域就销毁了,所以需要malloc才可。
- 类型匹配的问题
- 销毁的时候要先销毁队列开辟的空间,不然会造成野指针。
- 匿名结构体
- 耦合性
- -> 优先级高于&
- !STempty(&obj->stackpush))//!=0 flase---true开始导 直到==0 true
- 结构体和结构体指针

Stack.h&Stack.c手撕栈
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef int STDatatype;
typedef struct Stack
{STDatatype* a;int top;int capacity;
}ST;void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst, STDatatype x);
void STPop(ST* pst);
STDatatype STTop(ST* pst);
bool STempty(ST* pst);
int STSize(ST* pst);void STInit(ST* pst)
{assert(pst);pst->a = 0;pst->top = 0;pst->capacity = 0;
}void Createcapacity(ST* pst)
{if (pst->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;STDatatype* tmp = (STDatatype*)realloc(pst->a, sizeof(ST) * newcapacity);if (tmp == NULL){perror("realloc fail");return;}pst->a = tmp;pst->capacity = newcapacity;}
}void STPush(ST* pst, STDatatype x)
{assert(pst);Createcapacity(pst);pst->a[pst->top] = x;pst->top++;
}void STPop(ST* pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}STDatatype STTop(ST* pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top-1];
}bool STempty(ST* pst)
{assert(pst);return pst->top == 0;
}int STSize(ST* pst)
{assert(pst);return pst->top;
}void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = 0;pst->capacity = 0;
}
同样我们之前用数组实现了【栈】,这里我们在来用两个栈实现【队列】 。
声明队列MyQueue
typedef struct {ST stackpush;ST stackpop;
} MyQueue;
创建&初始化队列myQueueCreate
MyQueue* myQueueCreate() {MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));STInit(&obj->stackpush);STInit(&obj->stackpop);return obj;
}
入队列myQueuePush
//入队列
void myQueuePush(MyQueue* obj, int x) {STPush(&obj->stackpush, x);
}
返回队头元素myQueuePeek
//取出队列的数据 --所以可以先实现这个
int myQueuePeek(MyQueue* obj) {if(STempty(&obj->stackpop))//==0 true为空导数据{while(!STempty(&obj->stackpush))//!=0//!=0 flase---true开始导 直到==0 true ---false{int x=STTop(&obj->stackpush);STPush(&obj->stackpop,x);STPop(&obj->stackpush);}}return STTop(&obj->stackpop);
}
出队列&返回队头元素myQueuePop
//出队列 为NULL就导数据/出队列 不为NULL出队列
int myQueuePop(MyQueue* obj) {int back=myQueuePeek(obj);STPop(&obj->stackpop);return back;
}
判断队列空否myQueueEmpty
bool myQueueEmpty(MyQueue* obj) {return STempty(&obj->stackpush) && STempty(&obj->stackpop);
}
释放空间myQueueFree
void myQueueFree(MyQueue* obj) {STDestroy(&obj->stackpush);STDestroy(&obj->stackpop);free(obj);obj=NULL;
}
MyQueue总代码
typedef struct {ST stackpush;ST stackpop;
} MyQueue;MyQueue* myQueueCreate() {MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));STInit(&obj->stackpush);STInit(&obj->stackpop);return obj;
}
//入队列
void myQueuePush(MyQueue* obj, int x) {STPush(&obj->stackpush, x);
}//取出队列的数据 --所以可以先实现这个
int myQueuePeek(MyQueue* obj) {if(STempty(&obj->stackpop))//==0 true为空导数据{while(!STempty(&obj->stackpush))//!=0//!=0 flase---true开始导 直到==0 true ---false{int x=STTop(&obj->stackpush);STPush(&obj->stackpop,x);STPop(&obj->stackpush);}}return STTop(&obj->stackpop);
}//出队列 为NULL就导数据/出队列 不为NULL出队列
int myQueuePop(MyQueue* obj) {int back=myQueuePeek(obj);STPop(&obj->stackpop);return back;
}//
bool myQueueEmpty(MyQueue* obj) {return STempty(&obj->stackpush) && STempty(&obj->stackpop);
}void myQueueFree(MyQueue* obj) {STDestroy(&obj->stackpush);STDestroy(&obj->stackpop);free(obj);obj=NULL;
}
- 不要对比代码!怎么想怎么写!
- 调试很重要!调式:按照自己预期的去走读代码(最后上编译器)
- 编译出错:运行的问题
- 执行错误:逻辑的问题
✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!
【数组栈】实现-CSDN博客
单链表实现【队列】-CSDN博客
相关文章:
队列实现栈VS栈实现队列
目录 【1】用队列实现栈 思路分析 易错总结 Queue.c&Queue.h手撕队列 声明栈MyStack 创建&初始化栈myStackCreate 压栈myStackPush 出栈&返回栈顶元素myStackPop 返回栈顶元素myStackTop 判断栈空否myStackEmpty 释放空间myStackFree MyStack总代码…...
C/C++: 统计整数
【问题描述】 输入若干个整数,统计出现次数最多的那个整数。如果出现最多的整数有两个以上,打印最早输入的那个整数。 【输入形式】 从标准输入读取输入。第一行只有一个数字N(1≤N≤10000),代表整数的个数。以后的N行…...
docker容器生成镜像并上传个人账户
登录到 Docker Hub 账户: docker login这将提示你输入你的 Docker Hub 账户名和密码。 为容器创建镜像 docker commit <容器名或容器ID> <你的用户名>/<镜像名:标签>例子 docker commit my_container yourusername/my_image:latest推送镜像到…...
hdlbits系列verilog解答(exams/m2014_q4g)-48
文章目录 一、问题描述二、verilog源码三、仿真结果一、问题描述 本次我们将一次创建多个逻辑门,对两个输入a和b通过组合逻辑实现七种不同的输出: out_and: a and bout_or: a or bout_xor: a xor bout_nand: a nand bout_nor: a nor bout_xnor: a xnor bout_anotb: a and-no…...
在vue或者react或angular中,模板表达式中的箭头函数是无效的吗?为什么无效?
出现此问题的背景: 我在Angular项目中对一个标签属性绑定了一个箭头函数,编译报错。 在vue或者react或angular中,模板表达式中的箭头函数是无效的吗? 在 Vue、React 或 Angular 中,模板表达式中的箭头函数是无效的。…...
C++11『lambda表达式 ‖ 线程库 ‖ 包装器』
✨个人主页: 北 海 🎉所属专栏: C修行之路 🎃操作环境: Visual Studio 2022 版本 17.6.5 文章目录 🌇前言🏙️正文1.lambda表达式1.1.仿函数的使用1.2.lambda表达式的语法1.3.lambda表达式的使用…...
MATLAB算法实战应用案例精讲-【数模应用】漫谈机器学习(四)(附实战案例及代码实现)
目录 机器学习学习路线 学习编写抽象类 固定随机数种子 先加载少量数据...
JavaScript 中松散类型的理解
JavaScript 是一种动态类型语言,它的松散类型是其独特的特性之一。本文将深入探讨 JavaScript 中松散类型的概念以及如何在代码中应用。 引言 JavaScript 是一种强大而灵活的语言,它的松散类型使得变量的类型可以在运行时动态改变。这为开发人员带来了…...
java基于springboot公益帮学网站 新闻发布系统的设计与实现vue
以Java为开发平台,综合利用Java Web开发技术、数据库技术等,开发出公益帮学网站。用户使用版块:可以选择注册并登录,可以浏览信息、可以网上互动、发布文章、内容推荐等。后台管理员管理版块:以管理员身份登录网站后台…...
VMware 安装 Centos7 超详细过程
VMware 安装 Centos7 超详细过程 分类 编程技术 1.软硬件准备 软件:推荐使用 VMware,我用的是 VMware 12 镜像:CentOS6 ,如果没有镜像可以在阿里云下载 centos安装包下载_开源镜像站-阿里云 硬件:因为是在宿主机上运行虚拟化软…...
03:2440--UART
目录 一:UART 1:概念 2:工作模式 3:逻辑电平 4:串口结构图 5:时间的计算 二:寄存器 1:简单的UART传输数据 A:GPHCON--配置引脚 B:GPHUP----使能内部上拉编辑 C: UCON0---设置频率115200 D: ULCON0----数据格式8n1 E:发送数据 A:UTRSTAT0 B:UTXHO--发送数据输…...
Vatee万腾的科技冒险:Vatee独特探索力量的数字化征程
在数字化时代的激流中,Vatee万腾以其独特的科技冒险精神,引领着一场前所未有的数字化征程。这不仅仅是一次冒险,更是对未知的深度探索,将科技的力量推向新的高度。 Vatee万腾在科技领域敢于挑战传统,积极探索未知的可能…...
物联网后端个人第十二周总结
学习工作进度 物联网方面 1.模拟设备通过规则引擎将数据通过mqtt进行转发 在物联网平台上实现模拟设备通过规则引擎将数据通过mqtt进行转发已经全部完成了,所使用的物联网平台在这方面有不少的问题和bug,也可能是没有按照开发者的想法对平台进行使用才导…...
Linux C语言 26-可变参数
Linux C语言 26-可变参数 本节关键字:可变参数、va_list、va_arg、va_end 相关C库函数:va_list、va_arg、va_end 什么是可变参数? C语言中的可变参数是指函数能够接受不定数量的参数。在不确定函数参数时,使用“char *format, …...
Gin 学习笔记02-参数获取
Gin 参数获取 1、获取url 参数2、获取动态 url 参数3、获取 form 表单数据 1、获取url 参数 Query()GetQuery()QueryMap()DefaultQuery() package mainimport ("fmt""github.com/gin-gonic/gin""net/http" )func _query(c *gin.Context) {// 1…...
Uniapp Vue3 基础知识点附带实例
包括数据绑定和计算属性、条件渲染和列表渲染、事件处理、表单输入处理、生命周期钩子、自定义指令和过滤器、路由和导航以及状态管理(如Vuex): <template><div><!-- 条件渲染 --><div v-if"showMessage">…...
【迅搜03】全文检索、文档、倒排索引与分词
全文检索、文档、倒排索引与分词 今天还是概念性的内容,但是这些概念却是整个搜索引擎中最重要的概念。可以说,所有的搜索引擎就是实现了类似的概念才能称之为搜索引擎。而且今天的内容其实都是相关联的,所以不要以为标题上有四个名词就感觉好…...
MySql之索引,视图,事务以及存储过程举例详解
一.数据准备 数据准备可参考下面的链接中的数据准备步骤 MySql之内连接,外连接,左连接,右连接以及子查询举例详解-CSDN博客 (如有问题可在评论区留言) 二.存储过程 1.定义 存储过程 PROCEDURE ,也翻译…...
AR眼镜双目光波导/主板硬件方案
AR(增强现实)技术的发展离不开光学元件,而在其中,光波导和Micro OLED被视为AR眼镜光学方案的黄金搭档。光学元件在AR行业中扮演着核心角色,其成本高昂且直接影响用户体验的亮度、清晰度和大小等因素。AR眼镜的硬件成本中,光机部分…...
单片机调试技巧--修改bin文件实现断点
fromelf --text -a -c --outputall.dis F103_Moduel\F103_Moduel.axffromelf --bin --outputtest.bin F103_Moduel\F103_Moduel.axf 在启动文件中,修改UsageFault_Handler UsageFault_Handler\PROC; get current contextTST lr, #0x04 ; if(!EXC_RETURN[2])ITE…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
