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

【力扣刷题实战】用队列实现栈

大家好,我是小卡皮巴拉

文章目录

目录

力扣题目: 用队列实现栈

题目描述

示例:

解题思路

问题理解

算法选择

具体思路

解题要点

完整代码(C语言)

兄弟们共勉 !!! 


每篇前言

博客主页:小卡皮巴拉

咱的口号:🌹小比特,大梦想🌹

作者请求:由于博主水平有限,难免会有错误和不准之处,我也非常渴望知道这些错误,恳请大佬们批评斧正。

力扣题目: 用队列实现栈

原题链接:  用队列实现栈

题目描述

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。

  • int pop() 移除并返回栈顶元素。

  • int top() 返回栈顶元素。

  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。

  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解题思路

问题理解

题目要求通过两个队列(FIFO)来模拟一个栈(LIFO)的功能,包括四个基本操作:push(入栈)、pop(出栈)、top(查看栈顶元素)和empty(检查栈是否为空)。由于栈是后入先出的数据结构,而队列是先进先出的,因此需要通过两个队列的协作来实现栈的后入先出行为。

算法选择

使用两个队列:queue1 和 queue2queue1 用于处理主要的入栈和出栈操作,而 queue2 作为辅助队列,用于在出栈和查看栈顶元素时重新排序 queue1 中的元素。

具体思路

  1. 初始化栈

    • 使用两个队列q1q2来模拟栈。

    • 初始化栈时,同时初始化这两个队列。

  2. 入栈操作(push)

    • 总是向非空队列(或任意队列,如果两个队列都为空则选择任意一个)中插入新元素。

    • 这样做是为了保持一个队列始终为空(或接近为空),以便在出栈时能够高效地转移元素。

  3. 出栈操作(pop)

    • 确定哪个队列是非空的(即包含栈顶元素的队列)。

    • 将非空队列中的元素(除了最后一个)逐个转移到空队列中。

    • 弹出非空队列中的最后一个元素(即栈顶元素),并返回其值。

    • (可选)交换两个队列的角色,以便下次出栈操作能够高效进行。但在此实现中,由于我们总是向非空队列插入新元素,因此这一步是多余的。

  4. 查看栈顶元素(top)

    • 确定哪个队列是非空的。

    • 直接返回非空队列中的最后一个元素(即栈顶元素)。

    • 不需要转移元素或交换队列角色。

  5. 检查栈是否为空(empty)

    • 同时检查两个队列是否为空。

    • 如果两个队列都为空,则栈为空;否则,栈不为空。

  6. 销毁栈

    • 销毁两个队列,并释放栈结构所占用的内存。

解题要点

  • 双队列协作:利用两个队列的先进先出特性来模拟栈的后入先出行为。

  • 元素转移:在出栈和查看栈顶元素时,将一个队列中的元素转移到另一个队列中,以便保留栈顶元素。

  • 角色交换(可选):为了优化后续操作,可以在出栈后交换两个队列的角色,但这不是必需的,特别是在top操作中。

  • 状态维护:确保在每次操作后,都能正确地反映栈的当前状态。

完整代码(C语言)

typedef int QDataType;
//定义队列结点的结构
typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QueueNode;

//定义队列的结构
typedef struct Queue
{
	QueueNode* phead;//队头
	QueueNode* ptail;//队尾
	int size;        //队列有效元素个数
}Queue;
//初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

//入队列——向队列中插入数据
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail!\n");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;

	//队列为空,队头和队尾都是newnode
	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = pq->ptail->next;
	}
	pq->size++;
}

//队列判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	//队列为空时,头为空或头和尾均为空
	return pq->phead == NULL;
}

//队列有效元素个数
int QueueSize(Queue* pq)
{
	return pq->size;
}

//出队列——从队列中删除数据
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!(QueueEmpty(pq)));
	//只有一个结点
	if (pq->phead == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	//多个结点
	else 
	{
		QueueNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	--pq->size;
}

//取队头数据
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->phead->data;
}

//取队尾数据
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->ptail->data;
}

//销毁队列
void QueueDestory(Queue* pq)
{
	assert(pq);
	QueueNode* pcur = pq->phead;
	while (pcur)
	{
		QueueNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pq->phead = pq->ptail = NULL;
	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) {
    //1.向不为空的队列中插入数据
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }
}

int myStackPop(MyStack* obj) {
    //判断空队列和非空队列
    Queue* emp = &obj->q1;//空队列
    Queue* noneEmp = &obj->q2;//非空队列
    if(QueueEmpty(&obj->q2))
    {
        emp = &obj->q2;
        noneEmp = &obj->q1;
    }
    //把noneEmp前size-1个数据导入到emp
    while(QueueSize(noneEmp) > 1)
    {
        //先取队头的数据,再将队头的数据放到emp队列中
        QueuePush(emp,QueueFront(noneEmp));
        //删除非空队列中的队头数据
        QueuePop(noneEmp);
    }
    int top = QueueFront(noneEmp);
    QueuePop(noneEmp);
    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;
}

兄弟们共勉 !!! 

码字不易,求个三连

抱拳了兄弟们!


http://www.kler.cn/news/361503.html

相关文章:

  • 认识一下:__asm { int 80h; LINUX - sys_fork }
  • 渗透实战 JS文件怎么利用
  • 保姆级VsCode配置C++编译环境
  • MySQL~数据类型
  • Elasticsearch 实战应用与优化策略研究
  • UEFI学习笔记(十二):PCIe的概述与访问
  • Vue3集成axios实现ajax请求
  • linux—基础命令及相关知识
  • Mysql同步数据库异常
  • 使用InternVL、LMDeploy和GTE搭建多模态RAG系统
  • 界面耻辱纪念堂--可视元素03
  • Python 曲线绘制
  • C++ 红黑树
  • 鸿蒙--页面跳转
  • 【鸿蒙NEXT】SaveButton保存图片
  • 无需扩散,下一个token预测直达AGI!
  • kubeadm部署的k8s证书过期解决
  • AWD的复现
  • ECharts饼图-饼图34,附视频讲解与代码下载
  • 480p 720p 1080p 2k 4k 8k 12k分辨率视频分别占用多大带宽?
  • TikTok运营对IP有什么要求?
  • 修改el-table默认滚动条样式
  • 【建议收藏】100个运维知识,懂一半绝对高手,零基础入门到精通_it运维项目的知识库内容
  • OpenCV视觉分析之运动分析(3)背景减除类:BackgroundSubtractorKNN的一系列get函数的使用
  • 软件工程python毕设课题大全
  • 信息收集-IP查询和利用搜索引擎收集