目录
前言
小伙伴们大家好,今天我们来了解一篇有关队列和栈的力扣题目:用队列实现栈。
然后接下来我们还会有一篇文章,是用栈实现队列,在这两道题目中,我们都是用栈和队列的一些接口函数去实现,同时我们并不会改变栈和队列原有的结构。
题目
首先,我们来了解一下力扣上对该题的描述:
如上图所示:我们需要用两个队列去实现一个栈,同时该栈支持基本栈的四种操作,分别为插入,删除,返回栈顶元素以及最后一个判断栈是否为空。
思路
我们知道,如果想实现栈的先进后出:
还有需要实现的函数有,返回栈顶元素以及判断栈是否为空。
接口功能代码实现
当我们有了以上思路之后,其实代码主要就是一些接口套用实现:
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
//将两个队列实现初始化
MyStack*st=(MyStack*)malloc(sizeof(MyStack));
QueueInit(&st->q1);
QueueInit(&st->q2);
return st;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q1,x);
}
}
int myStackPop(MyStack* obj) {
Queue*emptyQ=&obj->q1;
Queue*noneemptyQ=&obj->q2;
if(!QueueEmpty(&obj->q1))
{
emptyQ=&obj->q2;
noneemptyQ=&obj->q1;
}
while(QueueSize(noneemptyQ)>1)
{
QueuePush(emptyQ,QueueFront(noneemptyQ));
QueuePop(noneemptyQ);
}
int ret=QueueFront(noneemptyQ);
QueuePop(noneemptyQ);
return ret;
}
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->q1);
QueueDestroy(&obj->q2);
free(obj);
}
对于以上代码来说,我们有如下解释:
第一点
因为我们用队列实现的栈,用了两个队列,所以这里我们将这两个队列集中在一个结构体中,所以我们需要给该结构体分配一个空间,除此之外,每个新增的元素的空间都在队列的接口中已经实现了,这里我们只需要考虑这两个队列的空间,而且只需要开辟一次就可以了。
然后我们就需要对其进行初始化,因为需要修改结构体内容,所以需要传递指针。
第二点
在进行删除操作时,首先我们假设 q1 是空队列,q2 是非空队列。之后我们进行一个判断,如果不是,我们则将其互换。这样后面就不用判断,直接进行出栈的操作了。
第三点
对于判断是否为空的接口,其返回值是 bool 值,所以我们只需要调用队列判空的函数,然后确定两个都是空的时候,此时才表示该栈为空。
好的,那么总结来说,这里实现栈我们直接用数组是可以实现的,但是这里就是单纯为了大家去实际体验接口函数的嵌套实现。
源码
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
//初始化栈
void StackInit(ST*ps);
//销毁
void StackDestroy(ST*ps);
//插入
void StackPush(ST*ps,STDataType x);
//删除
void StackPop(ST*ps);
//取栈顶的数据
STDataType StackTop(ST* ps);
//栈里面有多少个数据
int StackSize(ST* ps);
//判断栈是否满
bool StackEmpty(ST* ps);
//初始化栈
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
//销毁
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->top = ps->capacity = 0;
}
//插入
void StackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newcapacity = (ps->capacity == 0) ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->a,newcapacity*sizeof(STDataType));
ps->capacity = newcapacity;
ps->a = tmp;
}
//插入
ps->a[ps->top] = x;
ps->top++;
}
//删除
void StackPop(ST* ps)
{
assert(ps && ps->top > 0);
assert(!StackEmpty(ps));
ps->top--;
}
//取栈顶的数据
STDataType StackTop(ST* ps)
{
assert(ps && ps->top > 0);
assert(!StackEmpty(ps));
return ps->a[ps->top-1];
}
//栈里面有多少个数据
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
//判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
typedef struct {
ST pushST;
ST popST;
} MyQueue;
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) {
if(StackEmpty(&obj->popST))
{
while(!StackEmpty(&obj->pushST))
{
StackPush(&obj->popST,StackTop(&obj->pushST));
StackPop(&obj->pushST);
}
}
int front=StackTop(&obj->popST);
StackPop(&obj->popST);
return front;
}
int myQueuePeek(MyQueue* obj) {
//如果pushST为空怎么办,不应该是先判断吗
//为什么这里没有判断
if(StackEmpty(&obj->popST))
{
while(!StackEmpty(&obj->pushST))
{
StackPush(&obj->popST,StackTop(&obj->pushST));
StackPop(&obj->pushST);
}
}
return StackTop(&obj->popST);
}
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&obj->popST)&&StackEmpty(&obj->pushST);
}
void myQueueFree(MyQueue* obj) {
StackDestroy(&obj->pushST);
StackDestroy(&obj->popST);
free(obj);
}
那么本文到此就结束啦!如有不对的地方,还请大家指正啊!