- 栈和队列的互相转换是非常经典的一道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);
}
-以上便是本期文章的全部内容,希望能加深各位对栈和队列的理解。