栈和队列的相互实现

本文讲述了如何用队列实现栈和栈实现队列,强调了数据结构之间的转换及其在理解栈和队列特性的价值,以及不同数据结构的适用场景。
摘要由CSDN通过智能技术生成

  • 栈和队列的互相转换是非常经典的一道oj题目,这其中涉及的原理可以加深我们对栈和队列的理解。
  • 此外,我们也能由此得知,不同的数据结构是可以转换的。既然如此,那为什么还要设计这么多的数据结构呢?显然是由于不同数据结构的适用场景不同。天下英雄如过江之鲫,这些经典的数据结构却能够屹立不倒,是有其存在的意义和魅力的。

队列实现栈

  • 用队列实现栈其难点在于解决各自结构上的差异。
  • 队列是FIFO,而栈却是FILO。所以实现弹栈这个功能就必须至少有两个或者两个以上的队列相互配合。
  • 当进行弹栈操作时,可以将一个队列中的元素依次存入另一个队列,然后保留最后一个进行出队列的操作。
  • 详细实现代码如下。
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*emptyq=&obj->q1;
    Queue*nonemptyq=&obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        emptyq=&obj->q2;
        nonemptyq=&obj->q1;
    }
    while(QueueSize(nonemptyq)>1)
    {
        QueuePush(emptyq,QueueFront(nonemptyq));
        QueuePop(nonemptyq);
    }
    int top=QueueFront(nonemptyq);
    QueuePop(nonemptyq);
    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) 
{
        QueueDestroy(&obj->q2);
        QueueDestroy(&obj->q1);
        free(obj);
}

栈实现队列

  • 用栈实现队列和用队列实现栈的难点大差不差,如果能自主完成用队列实现栈,那么想必这个也不在话下。
  • 着重考虑出队列的操作,是不是要像用队列实现栈一样,每当进行出队列操作时就将非空栈的所有元素转移到空栈,然后再弹栈?这样做只能说是无可厚非,但如果深入思考我们可以敏锐的发现,进行一次倒栈操作后,原来元素的弹栈顺序直接颠倒过来,那不就实现了FIFO了吗?
  • 也就是说我们完全可以创建一个专门用来入队列的栈和一个专门用来出队列的栈,这样的构建出来的队列出队列效率就会大大增加。
MyQueue* myQueueCreate() 
{
    MyQueue* pq=(MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&pq->pushst);
    StackInit(&pq->popst);
    return pq;
}

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

int myQueuePop(MyQueue* obj) 
{
    int x=0;
    if(StackEmpty(&obj->popst))
    {
        x=StackTop(&obj->popst);
        StackPop(&obj->popst);
        return x;
    }
    else if(StackEmpty(&obj->pushst))
    {
        while(StackEmpty(&obj->pushst))
           {
               int cur=StackTop(&obj->pushst);
               StackPop(&obj->pushst);
               StackPush(&obj->popst,cur);
           }
        x=StackTop(&obj->popst);
        StackPop(&obj->popst);
        return x;
    }
    return 0;
}

int myQueuePeek(MyQueue* obj) 
{
    if(StackEmpty(&obj->popst))
    {
        return StackTop(&obj->popst);
    }
    else if(StackEmpty(&obj->pushst))
    {
        while(StackEmpty(&obj->pushst))
            {
                int cur=StackTop(&obj->pushst);
                StackPop(&obj->pushst);
                StackPush(&obj->popst,cur);
            }
        return StackTop(&obj->popst);
    }
    return 0;
}

bool myQueueEmpty(MyQueue* obj) 
{
    return StackEmpty(&obj->pushst)==0&&StackEmpty(&obj->popst)==0;
}

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

-以上便是本期文章的全部内容,希望能加深各位对栈和队列的理解。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值