当前位置: 首页 > news >正文

使用队列实现栈和使用栈实现队列

在数据结构中,栈和队列是两种非常基础且重要的数据结构。栈遵循后进先出(LIFO)的原则,而队列遵循先进先出(FIFO)的原则。本文将介绍如何使用队列来实现栈,以及如何使用栈来实现队列,并给出相应的代码实现。

使用队列实现栈

相关OJ题 225. 用队列实现栈 - 力扣(LeetCode)

思路

为了使用队列实现栈,我们可以使用两个队列 q1 和 q2。在入栈操作时,我们将元素插入到非空的队列中;在出栈操作时,我们将非空队列中的元素除了最后一个元素外,全部移动到另一个空队列中,然后弹出最后一个元素。

代码实现

以下是使用队列实现栈的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>typedef int QDataType;typedef struct QueueNode
{struct QueueNode* next;QDataType val;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;// 初始化与销毁队列
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);// 队尾插入
void QueuePush(Queue* pq, QDataType x);
// 队头删除
void QueuePop(Queue* pq);// 取队头和队尾的数据
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);// 队列大小
int QueueSize(Queue* pq);// 判空
bool QueueEmpty(Queue* pq);// 初始化与销毁队列
void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}void QueueDestory(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while(cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}// 队尾插入
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if(newnode == NULL){perror("malloc fail!");return;}newnode->next = NULL;newnode->val = x;if(pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}// 队头删除
void QueuePop(Queue* pq)
{assert(pq);assert(pq->size != 0);// 一个节点if(pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else // 多个节点{QNode* next =  pq->phead->next;free(pq->phead);pq->phead = next;}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;
}// 队列大小
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));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 top = QueueFront(nonEmpty);QueuePop(nonEmpty);return top;
}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) 
{QueueDestory(&obj->q1);QueueDestory(&obj->q2);free(obj);obj = NULL;
}

复杂度分析

  • 入栈操作:时间复杂度为 O(1),因为只需要将元素插入到队列的尾部。
  • 出栈操作:时间复杂度为 O(n),因为需要将 n−1 个元素从一个队列移动到另一个队列。

使用栈实现队列

相关OJ题 232. 用栈实现队列 - 力扣(LeetCode)

思路

为了使用栈实现队列,我们可以使用两个栈 s1 和 s2。在入队操作时,我们将元素压入栈 s1;在出队操作时,如果栈 s2 为空,我们将栈 s1 中的元素全部弹出并压入栈 s2,然后从栈 s2 中弹出元素。

代码实现

以下是使用栈实现队列的代码:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;// 初始化与销毁
void STInit(ST* pst);
void STDestory(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 = NULL;pst->top = 0;pst->capacity = 0;
}void STDestory(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");exit(1);}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 s1;ST s2;    
} MyQueue;MyQueue* myQueueCreate() 
{MyQueue* pst = (MyQueue*)malloc(sizeof(MyQueue));STInit(&pst->s1);STInit(&pst->s2);return pst;    
}void myQueuePush(MyQueue* obj, int x) 
{if(!STEmpty(&obj->s1)){STPush(&obj->s1, x);}    else{STPush(&obj->s2, x);}
}int myQueuePop(MyQueue* obj) 
{ST* Empty = &obj->s1;ST* nonEmpty = &obj->s2;if(!STEmpty(&obj->s1)){Empty = &obj->s2;nonEmpty = &obj->s1;}while(STSize(nonEmpty) > 1){STPush(Empty, STTop(nonEmpty));STPop(nonEmpty);}int top = STTop(nonEmpty);STPop(nonEmpty);while(!STEmpty(Empty)){STPush(nonEmpty, STTop(Empty));STPop(Empty);}return top;
}int myQueuePeek(MyQueue* obj) 
{ST* Empty = &obj->s1;ST* nonEmpty = &obj->s2;if(!STEmpty(&obj->s1)){Empty = &obj->s2;nonEmpty = &obj->s1;}while(STSize(nonEmpty) > 1){STPush(Empty, STTop(nonEmpty));STPop(nonEmpty);}int top = STTop(nonEmpty);STPush(Empty, STTop(nonEmpty));STPop(nonEmpty);while(!STEmpty(Empty)){STPush(nonEmpty, STTop(Empty));STPop(Empty);}return top;
}bool myQueueEmpty(MyQueue* obj) 
{return (STEmpty(&obj->s1) && (STEmpty(&obj->s2)));    
}void myQueueFree(MyQueue* obj) 
{STDestory(&obj->s1);STDestory(&obj->s2);free(obj);obj = NULL;   
}

复杂度分析

  • 入队操作:时间复杂度为 O(1),因为只需要将元素压入栈 s1
  • 出队操作:平均时间复杂度为 O(1),因为每个元素最多只会从栈 s1 移动到栈 s2 一次。

总结

通过使用队列实现栈和使用栈实现队列,我们可以更好地理解栈和队列的特性,以及它们之间的转换关系。在实际应用中,我们可以根据具体的需求选择合适的数据结构来实现相应的功能。

相关文章:

  • vue + ant-design + xlsx 实现表格导出进度提示功能
  • 牛客round94E
  • vue3 数值计算 保留小数位
  • 嵌入式学习之系统编程(五)进程(2)
  • day8补充(中断驱动和队列缓冲实现高效数据处理)
  • 文件管理(第八章、九)
  • PDF处理控件Aspose.PDF教程:以编程方式合并PDF文档
  • 一文带你彻底理清C 语言核心知识 与 面试高频考点:从栈溢出到指针 全面解析 附带笔者手写2.4k行代码加注释
  • DP KVM 为何更难实现 EDID 模拟器?
  • day38python打卡
  • 主流Agent Memory工具or框架对比(Mem0、LangMem、Letta)
  • 若依框架中返回自定义实体类分页数据和总记录数的实现方法
  • 【鸿蒙开发】Hi3861学习笔记-雨滴传感器
  • 433M射频接收芯片 XL520 产品特性,空旷环境下通讯距离可达200米
  • liunx、ubantu22.04安装neo4j数据库并设置开机自启
  • 【多智能体系统开发框架AutoGen解析与实践】
  • 【关于C++跨平台开发的挑战】
  • World of Warcraft [CLASSIC] Jewelcrafting Gemstone 3 [80 WLK]
  • 什么是风控合规?企业如何高效构建风控合规体系?
  • Python多线程:超详细实例讲解线程的创建
  • wap网站建设方案/百度网址大全在哪里找
  • 十堰网站设计0719web/在线培训系统app
  • wordpress 手机端打开速度慢/优化seo培训班
  • 唐山网站建设多少钱/电脑培训学校
  • 如何用家用电脑做网站/黄页88网推广服务
  • 新闻网站开发课程设计模板/淘宝seo是什么