数据结构之栈和队列的相互实现

在之前的文章中,我们讲了栈和队列的代码实现,而栈和队列也可以相互实现。
本文将详解栈和队列的相互实现。
在这里我们用leetcode的题来进行讲解。

用栈实现队列

在这里插入图片描述

算法思想

利用栈是先进后出,队列是先进先出的特性,使用两个栈来模拟队列。

我们可以用一个栈来模拟入队操作,另一个栈模拟出队操作,这样就可以实现先进先出。
入队栈只入队,出队栈只用来出队。
如图所示:

数据进入时进入到入队栈中。
在这里插入图片描述

当需要出队的时候,将入队栈里的数据都转移到出队栈中。
在这里插入图片描述

出队时只需对出队栈进行出栈操作即可完成出队操作。
在这里插入图片描述

以上就是算法思想,接下里进行代码实现。

代码实现

leetcode中我们需要手搓一个栈出来,栈的代码实现见链接:https://blog.csdn.net/m0_74089804/article/details/129678048?spm=1001.2014.3001.5501



//下面是用栈实现队列

//先创建一个入队栈,出队栈
typedef struct {
    Stack pushst;
    Stack popst;

} MyQueue;

//初始化入队出队栈
MyQueue* myQueueCreate() {
    MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
    Init(&obj->pushst);
    Init(&obj->popst);
    return obj;
}

//队列的插入即入队栈的插入
void myQueuePush(MyQueue* obj, int x) {
    Push(&obj->pushst,x);
}

//队列开头元素,即转移数据后出队栈的栈顶元素
int myQueuePeek(MyQueue* obj) {
    //出队栈如果为空则转移全部数据
    if(SEmpty(&obj->popst))
    {
        int size=Size(&obj->pushst);
        while(size--)
        {
            Push(&obj->popst,STop(&obj->pushst));
            Pop(&obj->pushst);
        }
    }
    //返回栈顶元素
    return STop(&obj->popst);
}

//删除队头元素,即删除转移数据后出队栈的栈顶元素
int myQueuePop(MyQueue* obj) {
    //转移数据操作一样,可以直接使用myQueuePeek接口
    int front=myQueuePeek(obj);
    Pop(&obj->popst);
    return front;
}

//判断队列是否为空,入队栈出队栈都为空即队列为空
bool myQueueEmpty(MyQueue* obj) {
    return SEmpty(&obj->pushst) && SEmpty(&obj->popst);
}
//队列的销毁,将入队栈出队栈都销毁即可
void myQueueFree(MyQueue* obj) {
    Destroy(&obj->pushst);
    Destroy(&obj->popst);
    free(obj);
    obj=NULL;
}

用队列实现栈

在这里插入图片描述

算法思想

用队列实现栈,算法思想和用栈实现队列相似,结合栈和队列先入后出,先进先出的特性,我们可以这样实现。

如图所示:

数据进入时先进入到一个队列。
在这里插入图片描述

出栈时需要将一个队列的数据转移到另一个队列,留下最后一个元素,即需要出栈的元素。
在这里插入图片描述

出栈时直接将剩下的最后一个元素删除即可完成出栈。

在这里插入图片描述
当再次需要入栈时,继续往有元素的那个队列插入,再重复以上操作即可。
在这里插入图片描述

总体思想就是保持一个队列一直为空,出栈时将数据转移到空队列中,留下一个出栈。

代码实现

代码如下:

leetcode中需要手搓一个队列出来,队列详解请看:https://blog.csdn.net/m0_74089804/article/details/129738965?spm=1001.2014.3001.5501

//下面实现队列模拟栈
//先创建两个队列并进行初始化
typedef struct 
{
    Queue q1;
    Queue q2;
} MyStack;

MyStack* myStackCreate() {
    MyStack* obj=(MyStack*)malloc(sizeof(MyStack));
    QueueInit(&obj->q1);
    QueueInit(&obj->q2);
    return obj;
}

//入栈即在不为空的队列中插入数据
void myStackPush(MyStack* obj, int x) {
    //如果q1不为空就在q1插入,反之在q2插入
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    }

}

//出栈的操作,先转移数据,再删除
int myStackPop(MyStack* obj) {
    //判断哪个是空队列
    MyStack* empty=&obj->q1;
    MyStack* noempty=&obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        empty=&obj->q2;
        noempty=&obj->q1;
    }
    
    //转移数据
    while(QueueSize(noempty)>1)//需要剩一个元素来出栈
    {
        QueuePush(empty,QueueFront(noempty));
        QueuePop(noempty);
    }
    
    //剩下的那个元素出队列,也就是出栈
    int top=QueueFront(noempty);
    QueuePop(noempty);
    return top;
}

//栈顶元素即不为空队列的队尾元素
int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    else
    {
        return QueueBack(&obj->q2);
    }
}

//判断栈是否为空即判断两个队列的size都为空,栈就为空
bool myStackEmpty(MyStack* obj) {
    if(QueueSize(&obj->q1)==0 && QueueSize(&obj->q2)==0)
    {
        return true;
    }
    else
        return false;
}

//栈的销毁即销毁创建的两个队列即可
void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);
    obj=NULL;
}

总结

栈和队列的相互实现还是很考验算法思想,利用好栈和队列的结构特性,即可完成相互实现,前提也是需要熟知栈和队列本身的代码实现。
以上就是本人对栈和队列相互实现的一点见解,不足之处请大佬批评指正,共同进步🌹🌹🌹

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值