用栈实现队列

该博客详细介绍了如何使用栈实现队列,包括理解题意、创建结构体、初始化空间、入栈、出栈、获取元素、判断队列是否为空以及释放空间等步骤。博主强调了在实现过程中需要注意的细节,如防止内存泄漏,并提供了思路和简化代码的方法。
摘要由CSDN通过智能技术生成

题目:

232. 用栈实现队列 - 力扣(LeetCode)

这题跟我们之前写过的 用队列实现栈 很像,感兴趣的可以自行了解一下。

题目内容

准备工作

这题明确说明了需要用栈来实现队列,介于C语言没有队列的库,所以在此之前我们需要用调用之前学的栈,详见

我们如果之前写过的话,直接复制过来就可以了,由于重点是讲用栈实现队列,所以这里就不过多了解栈了。

typedef int STDataType;
struct Stack
{
    STDataType* a;
    int top;       // 栈顶
    int capacity;  // 容量,方便增容
};

//typedef struct Stack ST;
typedef struct Stack Stack;

void StackInit(Stack* pst);
void StackDestroy(Stack* pst);

// 性质就决定在栈顶出入数据
void StackPush(Stack* pst, STDataType x);
void StackPop(Stack* pst);
STDataType StackTop(Stack* pst);

bool StackEmpty(Stack* pst);
int StackSize(Stack* pst);

void StackInit(Stack* pst)
{
    assert(pst);

    pst->a = (STDataType*)malloc(sizeof(STDataType) * 4);
    pst->top = 0;
    pst->capacity = 4;
}

void StackDestroy(Stack* pst)
{
    assert(pst);
    free(pst->a);
    pst->a = NULL;
    pst->capacity = pst->top = 0;
}

// 性质就决定在栈顶出入数据
void StackPush(Stack* pst, STDataType x)
{
    assert(pst);
    if (pst->top == pst->capacity)
    {
        STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType)*pst->capacity * 2);
        if (tmp == NULL)
        {
            printf("realloc fail\n");
            exit(-1); // 结束整个程序
        }

        pst->a = tmp;
        pst->capacity *= 2;
    }

    pst->a[pst->top] = x;
    pst->top++;
}

void StackPop(Stack* pst)
{
    assert(pst);
    assert(!StackEmpty(pst));
    pst->top--;
}

STDataType StackTop(Stack* pst)
{
    assert(pst);
    assert(!StackEmpty(pst));

    return pst->a[pst->top - 1];
}

bool StackEmpty(Stack* pst)
{
    assert(pst);

    return pst->top == 0;
}

int StackSize(Stack* pst)
{
    assert(pst);

    return pst->top;
}

看懂题

这样之后,我们有些小伙伴觉得自己英语不好,看不懂那些函数名,从而放弃这题,其实这里和英语好不好是没有太多关系的。注意看:

我们通过返回值大概了解了,题目中函数的含义。

创建结构体

“typedef struct”这个函数,有过对数据结构的基础认识,看到“struct”肯定是创建结构体。创建出的结构体决定了我们之下来的解题思路。所以我们先来了解一下实现这题的基本思路:

用栈实现队列的基本思路

我们如此反复倒数据,每次到最后一个元素就把它pop掉,所以我们避免不了要用到两个指针,指向两个链表的指针。如此一来“typedef struct”这个函数就容易实现了。

typedef struct 
{
    //定义两个栈指针
    Stack* pop;
    Stack* push;
} MyQueue;

创建空间

MyQueue* myQueueCreate() ”我们有了结构体,一定要初始化,不初始化会导致结构体内部的值不确定,容易出错。现在最新的“vs”如果不初始化,都编译不了了。

 MyQueue* myQueueCreate() 
{
    MyQueue* ps = (MyQueue*)malloc(sizeof(MyQueue));
    if(ps == NULL)
    {
        perrof("malooc:");
        excit(-1);
    }
    //初始化
    StackInit(&obj->pop);
    StackInit(&obj->push);

    return ps;
}

入栈

这个只要我们把push里的数据导入pop里就行了。

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

出栈

上图分析了,这个要分有无数据两种情况讨论。

int myQueuePop(MyQueue* obj) 
{
    if(StackEmpty(&obj->pop))
    {
        //倒数据
        while(!StackEmpty(&obj->push))
        {
            StackPush(&obj->pop, StackTop(&obj->push));
            StackPop(&obj->push);
        }
    }
    else
    {
        StackTop(&obj->pop);
    }
}

获取元素

这里还是要分两种情况,但是我们可以取巧一点:我们假设,pop有数据的时候,我们直接取顶,或者直接调用上文写的出栈函数;pop无数据的时候,我们就倒数据,就行了。

int myQueuePeek(MyQueue* obj) {
    if (StackEmpty(&obj->pop))
    {
        while (!StackEmpty(&obj->push))
        {
            StackPush(&obj->pop, StackTop(&obj->push));
            StackPop(&obj->push);
        }
    }
    return StackTop(&obj->pop);
}

这里我们再来看上文的出栈,发现这里其实可以相互调用的。

int myQueuePop(MyQueue* obj) 
{   
    int top = myQueuePeek(obj);
    StackPop(&obj->popST);
    return top;
}

这样就简化了代码。

判空

两个队列同时为空

bool myQueueEmpty(MyQueue* obj) 
{
    return StackEmpty(&obj->push) && StackDestory(&obj->pop);
}

释放空间

释放两个链表的同时,不要忘记释放两个指针,避免内存泄漏

void myQueueFree(MyQueue* obj) 
{
    StackDestory(&obj->push);
    StackDestory(&obj->push);

    free(ps);
    ps = NULL;
}

总结

我们可以发现原理(几幅图就能搞定)都不难,主要是代码的实现,需要注意许多细节,一定要注意避免内存泄漏。

欢迎大家点赞和评论。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

染柒_GRQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值