队列实现栈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…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
