数据结构——用栈实现队列


介绍

题目来源

题目来源于力扣网站:用栈实现队列
题目


原理讲解

根据要求,只能使用标准的栈操作实现队列,关于标准的栈操作可以看我写过的文章:数据结构——栈

我们知道,栈是先进后出,而队列是先进先出,所以毫无疑问,仅用一个栈没办法实现队列

进一步考虑,栈的出入顺序是相反的,所以如果将出栈顺序逆序,就实现了先进先出,因此可以使用两个栈来达到这个效果
结构示意图
上图用栈操作来讲解就是,队列尾插,相当于对pushst入栈,然后将pushst出栈同时对popst入栈,当队列头删时,相当于popst出栈

以上是基本原理,接下来我们用代码实现这个队列


代码实现

栈的基本操作如下

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);

队列结构

//MyQueue
typedef struct {
    ST pushst;
    ST popst;
} MyQueue;

初始化

 
初始化一个队列,返回队列的指针
1.申请空间
2.将队列里两个栈初始化
3.返回队列的指针

MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    STInit(&(obj->pushst));
    STInit(&(obj->popst));
    return obj;
}

销毁

 
销毁队列占用的空间,传入队列的指针
1.销毁两个栈
2.释放队列指针

void myQueueFree(MyQueue* obj) {
    STDestroy(&(obj->pushst));
    STDestroy(&(obj->popst));
    free(obj);
}

尾插

 
尾插新数据,传入队列指针和新数据x
根据前文中讲的原理,对队列尾插相当于对pushst入栈,因此直接调用入栈函数即可

void myQueuePush(MyQueue* obj, int x) {
    STPush(&(obj->pushst),x);
}

头删

 
队列头删,传队列指针,返回队头元素
根据上述原理,队列头删相当于popst出栈
popst的顶端元素就是队列的队头元素,根据题目要求,头删时返回队头元素
因此首先判断popst是否为空
如果popst为空,就将pushst里的所有数据先出栈,再入栈到popst
接下来用ret接收popst的顶端元素,再对popst执行出栈
最后返回ret

int myQueuePop(MyQueue* obj) {
	//栈判空
    if(STEmpty(&(obj->popst)))
    {	
    	//将数据从pushst出栈,同时入栈到popst
        while(!STEmpty(&(obj->pushst)))
        {
            STPush(&(obj->popst),STTop(&(obj->pushst)));
            STPop(&(obj->pushst));
        }
    }
    //接收队头数据
    int ret = STTop(&(obj->popst));
    STPop(&(obj->popst));
    return ret;
}

返回队头数据

 
获取队头元素,传入队列指针
这个函数来源于上面头删函数,但是不需要对popst出栈

int myQueuePeek(MyQueue* obj) {
    if(STEmpty(&(obj->popst)))
    {
        while(!STEmpty(&(obj->pushst)))
        {
            STPush(&(obj->popst),STTop(&(obj->pushst)));
            STPop(&(obj->pushst));
        }
    }
    return STTop(&(obj->popst));
}

判空

 
判断队列是否为空,返回bool值
当队列中两个栈都为空时,队列就是空,因此用逻辑与对两个栈判空即可

bool myQueueEmpty(MyQueue* obj) {
    if(STEmpty(&(obj->pushst)) && STEmpty(&(obj->popst)))
    {
        return true;
    }
    return false;
}

总结

问题的突破关键在于,栈遵守先进后出的原则队列遵守先进先出的原则,栈可以逆序数据,两个栈就是两次逆序,两次逆序后顺序不变,从而实现了队列的原则

在尾插时对pushst入栈,在头删时对popst出栈,两个栈互不干扰
只有当popst为空时,才需要将pushst的数据压入popst

最后这是代码的通过截图
通过截图

如果你有更高性能的实现方式,欢迎在评论区探讨

以上是用栈实现队列的全部讲解
如果存在错误,欢迎指正
  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值