一文搞定栈和队列的相互实现(内置惊喜)
什么是栈 队列
如何仅用两个栈模拟实现队列
如何仅用两个队列模拟实现栈
循环队列
什么是栈 队列
栈 本质是一种线性表 ,秉持着 “后进先出”原则; 想象不出来的朋友可以类比 “弹匣”
队列 也是一种线性数据结构 它只允许一端进数据(队尾),另一端出数据(队头);
如何仅用两个栈模拟实现队列
在模拟实现过程中 对实现队列的 出列 是最麻烦的
我们将两个栈取名 分别是 pushstack popstack;
入列我们直接压栈pushstack即可 push 1 2 3 4
我们要pop出 1 ;而队列是 先进先出 栈是 后进先出;出列如何实现呢
我们可以用倒数据的方法
如图 即是popstack接收 再依次pop掉 非常方便
下面来看具体的代码实现
typedef struct {//入队栈Stack pushST;//出队栈Stack popST;
} MyQueue;/** Initialize your data structure here. */
MyQueue* myQueueCreate(int maxSize) {MyQueue* pqueue = (MyQueue*)malloc(sizeof(MyQueue));StackInit(&pqueue->pushST, maxSize);StackInit(&pqueue->popST, maxSize);return pqueue;
}/** Push element x to the back of queue. */
void myQueuePush(MyQueue* obj, int x) {//入队栈进行入栈操作StackPush(&obj->pushST, x);
}/** Removes the element from in front of queue and returns that element. */
int myQueuePop(MyQueue* obj) {//如果出队栈为空,导入入队栈的元素if(StackEmpty(&obj->popST) == 0){while(StackEmpty(&obj->pushST) != 0){StackPush(&obj->popST, StackTop(&obj->pushST));StackPop(&obj->pushST);}}int front = StackTop(&obj->popST);//出队栈进行出队操作StackPop(&obj->popST);return front;
}/** Get the front element. */
int myQueuePeek(MyQueue* obj) {//类似于出队操作if(StackEmpty(&obj->popST) == 0){while(StackEmpty(&obj->pushST) != 0){StackPush(&obj->popST, StackTop(&obj->pushST));StackPop(&obj->pushST);}}return StackTop(&obj->popST);
}/** Returns whether the queue is empty. */
bool myQueueEmpty(MyQueue* obj) {return StackEmpty(&obj->pushST) == 0&& StackEmpty(&obj->popST) == 0;
}void myQueueFree(MyQueue* obj) {StackDestroy(&obj->pushST);StackDestroy(&obj->popST);free(obj);
}
如何仅用两个队列模拟实现栈
用队列模拟实现栈 做法和上题类似 还是“倒数据” 但在具体实现中略有不同 会麻烦一些
push 到一个非空队列中即可 (两个都是空 任意即可)
pop功能 需要倒数据
将非空队列中的数据 依次插入到空队列中 只剩下需要pop掉的数据 再pop掉即可
此时 非空队列变成空队列 空队列变成非空队列了
后续要实现 push 和pop 即循环这几个步骤就行
下面我们来看下具体的代码实现
typedef struct {Queue q1;Queue q2;} MyStack;/** Initialize your data structure here. */
MyStack* myStackCreate(int maxSize) {MyStack* pst = (MyStack*)malloc(sizeof(MyStack));QueueInit(&pst->q1);QueueInit(&pst->q2);return pst;
}/** Push element x onto stack. */
void myStackPush(MyStack* obj, int x) {//给非空队列进行入队操作if(QueueEmpty(&obj->q1) != 0){QueuePush(&obj->q1, x);}else{QueuePush(&obj->q2, x);}
}/** Removes the element on top of the stack and returns that element. */
int myStackPop(MyStack* obj) {//把非空队列的除最后一个元素之外的剩余元素全部入队空队列Queue* pEmpty = &obj->q1, *pNonEmpty = &obj->q2;if(QueueEmpty(&obj->q1) != 0){pEmpty = &obj->q2;pNonEmpty = &obj->q1;}while(QueueSize(pNonEmpty) > 1){QueuePush(pEmpty, QueueFront(pNonEmpty));QueuePop(pNonEmpty);}int top = QueueFront(pNonEmpty);//队尾元素出队QueuePop(pNonEmpty);return top;
}/** Get the top element. */
int myStackTop(MyStack* obj) {//获取非空队列的队尾元素Queue* pEmpty = &obj->q1, *pNonEmpty = &obj->q2;if(QueueEmpty(&obj->q1) != 0){pEmpty = &obj->q2;pNonEmpty = &obj->q1;}return QueueBack(pNonEmpty);
}/** Returns whether the stack is empty. */
bool myStackEmpty(MyStack* obj) {return !(QueueEmpty(&obj->q1) | QueueEmpty(&obj->q2));
}void myStackFree(MyStack* obj) {QueueDestory(&obj->q1);QueueDestory(&obj->q2);free(obj);
}
看到这里 我们已经学会了如何仅用两个栈来实现队列 和 如何仅用两个队列来实现栈
接下来 我们来学习一个 循环队列
循环队列 (惊喜 不看阳后悔)
什么是循环队列
一种队列 固定大小 首尾相连 可以利用队列之前用过的空间;一旦队列满了 我们就不能插入下一个元素
那我们应该用什么来实现循环队列呢 数组? 链表?
相信很多人第一眼就 觉得链表紫腚行 确实 但那是双向循环链表 而单链表行不行呢?
我们来分析下
1.如何判断空状态 和 满状态?
在这里我们使用 “添加一个空余节点”的方法,这样的话
可以 用front == rear 来判空
(rear + 1)%(k+1)== front 来判满
2.如何取队尾数据?
总结:单链表要实现这个就十分麻烦 所以我们使用数组
下面来看看代码实现
/*
解题思路:
通过一个定长数组实现循环队列
入队:首先要判断队列是否已满,再进行入队的操作,入队操作需要考虑索引循环的问题,当索引越界,需要让它变成最小值
出队:首先要判断队列是否为空,再进行出队操作,出队也需要考虑索引循环的问题
判空: 队头 == 队尾
判满: 队尾 + 1 == 队头
*/
typedef struct {int* queue;int front;int rear;int k
} MyCircularQueue;/** Initialize your data structure here. Set the size of the queue to be k. */
//创建一个可以存放k个元素的循环队列,实际申请的空间为k + 1
MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* pcq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));pcq->queue = (int*)malloc(sizeof(int)*(k+1));pcq->front = 0;pcq->rear = 0;pcq->k = k;return pcq;
}/** Insert an element into the circular queue. Return true if the operation is successful. */
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//判满if((obj->rear+1)%(obj->k+1) == obj->front){return false;}//队尾入队obj->queue[obj->rear++] = value;//如果队尾越界,更新为最小值if(obj->rear == obj->k+1)obj->rear = 0;return true;
}/** Delete an element from the circular queue. Return true if the operation is successful. */
bool myCircularQueueDeQueue(MyCircularQueue* obj) {//判空if(obj->front == obj->rear)return false;//队头出队++obj->front;//如果队头越界,更新为最小值if(obj->front == obj->k+1)obj->front = 0;return true;
}/** Get the front item from the queue. */
int myCircularQueueFront(MyCircularQueue* obj) {if(obj->front == obj->rear)return -1;elsereturn obj->queue[obj->front];
}/** Get the last item from the queue. */
int myCircularQueueRear(MyCircularQueue* obj) {if(obj->front == obj->rear)return -1;//队尾元素再rear索引的前一个位置,如果rear为0,//则队尾元素在数组的最后一个位置if(obj->rear == 0)return obj->queue[obj->k];elsereturn obj->queue[obj->rear-1];
}/** Checks whether the circular queue is empty or not. */
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {return obj->front == obj->rear;
}/** Checks whether the circular queue is full or not. */
bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->rear+1)%(obj->k+1) == obj->front;
}void myCircularQueueFree(MyCircularQueue* obj) {free(obj->queue);free(obj);
}
循环队列学会了吗 还不快点一键三连 拜托拜托啦!!!
一文搞定栈和队列的相互实现(内置惊喜)相关推荐
- 一文搞定数据结构(图解)
搞定顺序表: https://blog.csdn.net/qq_44443986/article/details/111387150 搞定链表: https://blog.csdn.net/qq_44 ...
- 一文搞定 Spring Data Redis 详解及实战
转载自 一文搞定 Spring Data Redis 详解及实战 SDR - Spring Data Redis的简称. Spring Data Redis提供了从Spring应用程序轻松配置和访问 ...
- 一文搞定面试中的二叉树问题
一文搞定面试中的二叉树问题 版权所有,转载请注明出处,谢谢! http://blog.csdn.net/walkinginthewind/article/details/7518888 树是一种比较重 ...
- php带参数单元测试_一文搞定单元测试核心概念
基础概念 单元测试(unittesting),是指对软件中的最小可测试单元进行检查和验证,这里的最小可测试单元通常是指函数或者类.单元测试是即所谓的白盒测试,一般由开发人员负责测试,因为开发人员知道被 ...
- 【Python基础】一文搞定pandas的数据合并
作者:来源于读者投稿 出品:Python数据之道 一文搞定pandas的数据合并 在实际处理数据业务需求中,我们经常会遇到这样的需求:将多个表连接起来再进行数据的处理和分析,类似SQL中的连接查询功能 ...
- 一文搞定Swing和Qt按钮和文本框的创建
一文搞定Swing和Qt按钮和文本框的创建 Qt的截图 java的 源码 package com.lujun;import java.awt.Container;import javax.swing. ...
- 一文搞定C#关于NPOI类库的使用读写Excel以及io流文件的写出
一文搞定C#关于NPOI类库的使用读写Excel以及io流文件的写出 今天我们使用NPOI类库读写xlsx文件, 最终实现的效果如图所示 从太平洋官网下载相应的类库,大概4~5MB,不要从github ...
- 一文搞定Qt读写excel以及qt读写xml数据
一文搞定Qt读写excel以及qt读写xml数据 最终的实现效果图 RC_ICONS = logo.ico .pro文件同级目录下加入 logo.ico 图标文件,运行文件,文件的图标就被写入软件 u ...
- 【全网最全】一文搞定 Linux 压缩、解压哪些事儿
一文搞定 Linux 压缩.解压哪些事儿 Linux 常用的解压和压缩命令如下: 1..tar # 解包 tar xvf FileName.tar # 打包 tar cvf FileName.tar ...
最新文章
- python处理声音
- 成员函数的const究竟修饰的是谁
- Wireshark使用学习
- Python基础知识(第四天)
- caffe学习(六):使用python调用训练好的模型来分类(Ubuntu)
- 6-3 逆序数据建立链表
- 【白话科普】10s 从零看懂 H5
- java抓取图片_java 抓取网页的图片
- js_!和!!的使用
- Java笔记-Log4j在Spring Boot中的使用
- bs模式Java web,基于BS模式的即时通讯系统的设计与实现(MyEclipse)
- Axure 经典实例高保真原型下载(Axure高保真酒店管理交互组件连锁酒店erp酒店企业web端后台管理财务管理会员管理网销管理报表管理))
- 用python快速将excel(含多sheet)导入MySQL(兼容中文)
- python控制窗口_Python : Turtle窗口控制
- mac上安装搭建Appium环境
- myeclipse 创建和访问 servlet 项目
- Windows系统镜像下载
- PhpStorm Unhandled exceptions错误解决
- Linux笔记之Docker安装,基于Debian 11(bullseye)
- apmserv 5.2.6 升级php,Windows + APMServ5.2.6/PHP5以上
热门文章
- UITextField shouldChangeCharactersInRange获取实时数据并执行联想搜索和搜索
- ETL常用的三种工具介绍及对比Datastage,Informatica
- vue 使用quill富文本编辑 增加表格功能
- 我的网站被攻击了,运维大佬给了我自动封禁ip的脚本。
- C语言实现PTA6-3 求集合数据的均方差
- 百度云服务器win系统,windows10系统下百度云无法打开如何解决
- bp神经网络的应用领域,BP神经网络能够做什么
- 72家品牌上榜,联诚发“LCF”获评第十九届深圳知名品牌!
- android vold文件夹,android vold
- 天梯赛刷题1:Prime Path