用队列实现栈 用栈实现队列 设计循环队列

用队列实现栈 

思路

栈的特点:后进先出   

队列的特点:先进先出

 使用两个队列实现栈:

 

我们可以使用两个队列,一个队列为:空队列,一个队列为:非空队列

当我们要出队列时:

将 size - 1个数据移动到空队列中,再将最后一个数据出队列,如此往复就可以完成4 3 2 1的出队列顺序

代码(c语言): 

队列的各种功能:

typedef int QDataType;
// 链式结构:表示队列 
typedef struct QListNode
{struct QListNode* _next;QDataType _data;
}QNode;// 队列的结构 
typedef struct Queue
{QNode* _front;QNode* _rear;int size;
}Queue;
// 初始化队列 
void QueueInit(Queue* q) {assert(q);q->size = 0;q->_front = NULL;q->_rear = NULL;
}
// 队尾入队列 
void QueuePush(Queue* q, QDataType data) {assert(q);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("QueuePush()::malloc()");return;}newnode->_data = data;newnode->_next = NULL;//队列为NULLif (q->_front == NULL){q->_front = q->_rear = newnode;}else{q->_rear->_next = newnode;q->_rear = q->_rear->_next;}q->size++;
}
// 队头出队列 
void QueuePop(Queue* q) {assert(q);assert(q->size != 0);//单个节点if (q->_front == q->_rear){free(q->_front);q->_front = q->_rear = NULL;}//多个节点else{QNode* next = q->_front->_next;free(q->_front);q->_front = next;}q->size--;
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q) {assert(q);assert(q->_front);//队头不能为NULLreturn q->_front->_data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q) {assert(q);assert(q->_rear);//队尾不能为NULLreturn q->_rear->_data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q) {return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q) {assert(q);return q->size == 0;
}
// 销毁队列 
void QueueDestroy(Queue* q) {assert(q);QNode* cur = q->_front;while (cur){QNode* next = cur->_next;free(cur);cur = next;}q->_front = q->_rear = NULL;q->size = 0;}

具体实现:

//使用两个队列实现栈
typedef struct {Queue q1;Queue q2;} MyStack;//初始化栈
MyStack* myStackCreate() {//创建一个栈MyStack* newStk = (MyStack*)malloc(sizeof(MyStack));//初始化栈(即初始化两个队列)QueueInit(&(newStk->q1));QueueInit(&(newStk->q2));return newStk;
}//入栈
void myStackPush(MyStack* obj, int x) {//假设法找不为NULL的队列Queue* noempty = &obj->q1;if(QueueSize(noempty) == 0){noempty = &obj->q2;}//往不为NULL队列中插入QueuePush(noempty,x);
}//出栈
int myStackPop(MyStack* obj) {//假设法判断NULL队列,非NULL队列Queue* empty = &obj->q1;Queue* noempty = &obj->q2;if(QueueSize(noempty) == 0){noempty = &obj->q1;empty = &obj->q2;}//将size - 1个数据移动到NULL队列中while(QueueSize(noempty) > 1){QueuePush(empty,QueueFront(noempty));QueuePop(noempty);}//出栈int pop = QueueBack(noempty);QueuePop(noempty);return pop;}//获取栈顶元素
int myStackTop(MyStack* obj) {Queue* noempty = &obj->q1;if(QueueSize(noempty) == 0){noempty = &obj->q2;}//获取栈顶数据,也就是队尾的数据return QueueBack(noempty);}//判NULL
bool myStackEmpty(MyStack* obj) {return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);}//销毁栈
void myStackFree(MyStack* obj) {QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj);}

用栈实现队列

思路

使用两个栈实现队列

固定两个栈,1. 存数据栈(pushst) 2. 出数据栈(popst)

当我们要出数据时,把存数据栈(pushst)导入到 出数据栈(popst)中,在对栈顶取数据,如此往复就可以实现 4 3 2 1 的出栈顺序

代码(c语言):

栈的各种功能:

typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;// 初始化和销毁
void STInit(ST* pst)
{assert(pst);pst->a = NULL;// top指向栈顶数据的下一个位置pst->top = 0;// top指向栈顶数据//pst->top = -1;pst->capacity = 0;
}void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}// 入栈  出栈
void STPush(ST* pst, STDataType x)
{assert(pst);// 扩容if (pst->top == pst->capacity){int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}pst->a = tmp;pst->capacity = newcapacity;}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;
}
typedef struct {ST pushst;//用来存储数据ST popst;//用来导出数据} MyQueue;

具体实现

//用两个栈实现队列
MyQueue* myQueueCreate() {MyQueue* new = (MyQueue*)malloc(sizeof(MyQueue));STInit(&new->pushst);STInit(&new->popst);return new;
}//入队列
void myQueuePush(MyQueue* obj, int x) {STPush(&obj->pushst,x);//插入至数据栈(pushst)中}//查看队头元素
int myQueuePeek(MyQueue* obj) {//查看出数据栈(popst),中是否有数据,有则直接查看栈顶数据,没有就把存数据栈(pushst)导入到 出数据栈(popst)中if(STEmpty(&obj->popst)){//把pushst数据全部导入popstwhile(!STEmpty(&obj->pushst)){STPush(&obj->popst,STTop(&obj->pushst));STPop(&obj->pushst);}}//返回出数据栈(popst)栈顶数据return STTop(&obj->popst);}//出队列
int myQueuePop(MyQueue* obj) {//它会帮我们导数据到popst中,popst栈顶的数据就是我们要删除的数据int pop = myQueuePeek(obj);STPop(&obj->popst);return pop;
}//判空
bool myQueueEmpty(MyQueue* obj) {return STEmpty(&obj->pushst) && STEmpty(&obj->popst);//两个栈为NULL则队列为NULL}//销毁队列
void myQueueFree(MyQueue* obj) {STDestroy(&obj->pushst);STDestroy(&obj->popst);free(obj);
}

设计循环队列

        

 思路

利用数组来创建循环队列

代码:

typedef struct {int* a;int head;int rear;//指向最后一个数据的下一个空间int k;
} MyCircularQueue;//初始化循环队列
MyCircularQueue* myCircularQueueCreate(int k) {MyCircularQueue* new = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//多开一个空间,用来解决数据为满与空的矛盾问题,当然也可以在结构体多加个size解决new->a = (int*)malloc(sizeof(int) * (k + 1));new->head = 0;new->rear = 0;//尾数据的下一个位置new->k = k;return new;
}//插入队列
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {//判断循环队列满没有,满则不能继续插入if((obj->rear + 1) % (obj->k + 1) == obj->head)//当尾数据指针 + 1 = 头指针时,队列满return false;obj->a[obj->rear] = value;obj->rear++;obj->rear %= obj->k + 1;//循环return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj) {//判断队列是否为空,为空则不能继续删除if(obj->head == obj->rear)//当尾指针 = 头指针时,队列为空return false;obj->head++;obj->head %= obj->k + 1; //循环return true;
}//返回队列头数据
int myCircularQueueFront(MyCircularQueue* obj) {if(obj->head == obj->rear)return -1;return obj->a[obj->head];
}//返回队列尾数据,即找尾指针指向的上一个地方
int myCircularQueueRear(MyCircularQueue* obj) {if(obj->head == obj->rear)return -1;return obj->a[(obj->k + obj->rear) % (obj->k + 1)];//往前绕k-1去找rear之前的一个数据}//判空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {//空return obj->head == obj->rear;
}//判满
bool myCircularQueueIsFull(MyCircularQueue* obj) {return (obj->rear + 1) % (obj->k + 1) == obj->head;}//销毁队列
void myCircularQueueFree(MyCircularQueue* obj) {free(obj->a);free(obj);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/842533.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多线程JUC 第2季 BlockingQueue 阻塞队列

一 阻塞队列 1.1 阻塞队列介绍 阻塞队列(BlockingQueue)是一个在队列基础上又支持了两个附加操作的队列: put方法:当队列装满时,添加的线程则被阻塞,直到队列不满,则可用。 take方法&#x…

力扣2028. 找出缺失的观测数据

题目: 现有一份 n m 次投掷单个 六面 骰子的观测数据,骰子的每个面从 1 到 6 编号。观测数据中缺失了 n 份,你手上只拿到剩余 m 次投掷的数据。幸好你有之前计算过的这 n m 次投掷数据的 平均值 。 给你一个长度为 m 的整数数组 rolls &a…

【Linux 网络】网络基础(三)(数据链路层协议:以太网协议、ARP 协议)

一、以太网 两个不同局域网的主机传递数据并不是直接传递的,而是通过路由器 “一跳一跳” 的传递过去。 跨网络传输的本质:由无数个局域网(子网)转发的结果。 所以,要理解数据跨网络转发原理就要先理解一个局域网中数…

安全厂商第一站!OASA 走进绿盟科技圆满结束

近日,龙蜥社区安全联盟(OASA)走进联盟成员单位绿盟科技集团股份有限公司(以下简称“绿盟科技”),就未来合作方向,双方进行了一次深入的合作交流。该会议共有 11 位人员出席,有来自绿…

视频监控平台AS-V1000产品介绍:账户或用户数据的导入和导出功能介绍

目录 一、功能描述 (一)导入功能定义 (二)导出功能定义 二、用户数据的导入导出的作用 三、AS-V1000新版本的导出和导入功能介绍 (一)功能主界面 (二)导出功能 1、导出操作 …

从零开始构建 Vision Transformer(ViT) 模型

Transformer 模型最早由 Vaswani 等人在 2017 年论文 Attention Is All You Need 中提出,并已广泛应用于自然语言处理。 2021年,Dosovitsky 等人在论文An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale中提出将 Transforme…

第十二届蓝桥杯物联网试题(国赛)

不得不说国赛相比较省赛而言确实,功能变得更加复杂,更加繁琐,特别是串口LORA通信相结合的更加频繁,且对收取的字符处理要求要更加复杂,处理判别起来会更加复杂。 对于收发数据本身来说,收发的数据本身是以…

每日一题——Python实现PAT甲级1029 Median(举一反三+思想解读+逐步优化)

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的方法 代码功能和结构点评 时间复杂度分析 空间复杂度分析 优化建议 我要更强…

深度学习环境安装教程-anaconda-python-pytorch

首先是anaconda的安装,可以从下面地址下载安装包 Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 尽量选择最新的日期的anaconda进行安装,我这里是windows电脑,因此选择了windos-x86_64.exe&#xf…

如何在anaconda的环境下安装langchain

1、安装anaconda; 2、在终端上,输入: conda install langchain -c conda-forge Proceed ([y]/n)? y 输入:Y 3、安装完成后,输入: python -c "import langchain; print(langchain.__version__)&…

Redisson集成SpringBoot

前言:Redisson集成SpringBoot主要有两种方式,一个是使用redisson-spring-boot-starter依赖(优先推荐),毕竟springboot主打的就是约定大于配置,这个依赖就是为springboot准备的。 再一种方式就是引入rediss…

JVM学习-javap解析Class文件

解析字节码的作用 通过反编译生成字节码文件,可以深入了解Java工作机制,但自己分析类文件结构太麻烦,除了第三方的jclasslib工具外,官方提供了javapjavap是jdk自带的反解析工具,它的作用是根据class字节码文件&#x…

一个投稿好方法让你的文章早日发表

作为一名单位信息宣传员,我初入此行时,满腔热情,怀揣着传播单位价值、展示团队风采的理想,一头扎进了稿件撰写的海洋。我的目标很简单,就是通过文字的力量,让外界听到我们的声音,感受到我们的活力。然而,理想很丰满,现实却给我上了生动的一课。 起初,我遵循传统路径,选择了一家…

QT安装和配置[安装注意点][QT找不到python27.dll][缩小空间]

安装注意点 本文摘录于:https://blog.csdn.net/Python_0011/article/details/131699443只是做学习备份之用,绝无抄袭之意,有疑惑请联系本人! 双击"qt-online-installer-windows-x64-4.8.0.exe"文件后输入账号选择如下控…

什么是Capto刀柄,一起来认识一下

大家好,今天咱们不聊齿轮,说一说一款刀柄的相关内容。目前,高速加工中心的主轴转速可以达到10,000——50,000r /min ,极大地提高了生产率。高速加工工具系统的主要作用是保证刀具在机床主轴中的精确定位,将主轴的运动和…

Python脚本启动应用并输入账号或密码

一、简介 如果每天要启动某个软件还要输入账号密码登录的需求的话,可以参考本文章; 二、Python环境 环境:Python3.11 已经在Windows电脑中配置Python环境变量,且配置了pipd的环境变量; 三、安装模块 安装所需要的…

计算机毕业设计 | SpringBoot招投标系统 任务发布网站(附源码)

1,绪论 在市场范围内,任务发布网站很受欢迎,有很多开发者以及其他领域的牛人,更倾向于选择工作时间、工作场景更自由的零工市场寻求零散单子来补贴家用。 如今市场上,任务发布网站鱼龙混杂,用户需要找一个…

(原创)从右到左排列RecycleView的数据

问题的提出 当我们写一个Recycleview时,默认的效果大概是这样的: 当然,我们也可以用表格布局管理器GridLayoutManager做成这样: 可以看到,默认的绘制方向是: 从左到右,从上到下 那么问题来了…

STM32系列(HAL库)——F103C8T6通过HC-SR04超声波模块实现测距

一、模块资料 (1)模块简介 超声波是振动频率高于20kHz的机械波。它具有频率高、波长短、绕射现象小、方向性好、能够成为射线而定向传播等特点。HC-SRO4是一款尺寸完全兼容老版本,增加UART和IIC功能的开放式超声波测距模块,默认条件下,软件…

执行普罗米修斯插件mysqld_exporter出现闪退问题如何解决?

运行 mysqld_exporter.exe 文件闪退的问题可能是由于配置文件或环境变量设置不正确导致的。 检查配置文件 my.cnf: 打开 my.cnf 文件,确保其中的配置项正确无误,尤其是 MySQL 数据库的连接信息。配置示例:[client] useryour_mysql…