使用两个栈实现一个队列
- 要实现Push接口其实不难,因为我们只需要向一个栈里面Push数据即可,我们暂且将这个栈定义为栈一,另一个栈设定为栈二
- 要实现Pop接口的话,其实只要先判断栈二是否为空栈,如果栈二不为空那么直接Pop出一个元素即可,如果栈二不为空,那么需要先将栈一中的元素全部转移到栈二中,然后栈二就有元素了,直接Pop出一个即可!
#include "Topic.h"
void QueueByTwoStackInit(QueueByTwoStack* qts)
{
assert(qts);
StackInit(&(qts->s1));
StackInit(&(qts->s2));
}
void QueueByTwoStackDestory(QueueByTwoStack* qts)
{
assert(qts);
StackDestory(&(qts->s1));
StackDestory(&(qts->s2));
}
//永远向栈一Push元素
void QueueByTwoStackPush(QueueByTwoStack* qts, DataType x)
{
assert(qts);
StackPush(&(qts->s1),x);
}
void QueueByTwoStackPop(QueueByTwoStack* qts)
{
assert(qts);
//如果栈二为空需要先将栈一中的元素全部转移到栈二中
if (StackEmpty(&(qts->s2)) == 0)
{
while (StackEmpty(&(qts->s1)))
{
StackPush(&(qts->s2), StackTop(&(qts->s1)));
StackPop(&(qts->s1));
}
}
StackPop(&(qts->s2));
}
DataType QueueByTwoStackFront(QueueByTwoStack* qts)
{
assert(qts);
if (StackEmpty(&(qts->s2)) == 0)
{
while (StackEmpty(&(qts->s1)))
{
StackPush(&(qts->s2), StackTop(&(qts->s1)));
StackPop(&(qts->s1));
}
}
return StackTop(&(qts->s2));
}
int QueueByTwoStackSize(QueueByTwoStack* qts)
{
assert(qts);
return StackSize(&(qts->s1)) + StackSize(&(qts->s2));
}
int QueueByTwoStackEmpty(QueueByTwoStack* qts)
{
assert(qts);
return StackEmpty(&(qts->s1)) | StackEmpty(&(qts->s2));
}
void TestQueueByTwoStack()
{
QueueByTwoStack qs;
QueueByTwoStackInit(&qs);
QueueByTwoStackPush(&qs, 11);
QueueByTwoStackPush(&qs, 22);
QueueByTwoStackPush(&qs, 33);
QueueByTwoStackPush(&qs, 44);
QueueByTwoStackPop(&qs);
QueueByTwoStackPop(&qs);
QueueByTwoStackPush(&qs, 55);
QueueByTwoStackDestory(&qs);
}
使用两个队列实现一个栈
接下来是两个队列实现一个栈,首先先大致说一下怎么实现?
如图所示,两个队列总有一个是空队列,一个是非空队列,要入栈的话,必须要入非空队列,出栈的话,必须让非空队列将元素转移到空队列里面,直到非空队列剩余一个元素,然后将剩余的这一个元素出队列,即可完成“出栈”
#include "motive.h"
//初始化
void StackByTwoQueueInit(StackByTwoQueue* stq)
{
assert(stq);
QueueInit(&(stq->q1));
QueueInit(&(stq->q2));
}
//销毁
void StackByTwoQueueDestory(StackByTwoQueue* stq)
{
assert(stq);
QueueDestory(&(stq->q1));
QueueDestory(&(stq->q2));
}
//分配空队列与非空队列
static EmptyCmp(Queue** em, Queue** noem, StackByTwoQueue** pstq)
{
assert(stq);
QueueEmpty(&(*pstq)->q1) == 1 ? ((*noem = &(*pstq)->q1), *em = &((*pstq)->q2)) : ((*noem = &(*pstq)->q2), *em = &((*pstq)->q1));
}
//获取顶部数据
DataType StackByTwoQueueTop(StackByTwoQueue* stq)
{
assert(stq);
Queue *empty;
Queue *noempty;
DataType ret;
//通过三元运算符确定空队列与非空队列
EmptyCmp(&empty, &noempty, &stq);
//将非空队列的元素转移到非空队列,保留一个
while (QueueSize(noempty) > 1)
{
QueuePush(empty, QueueFront(noempty));
QueuePop(noempty);
}
//获取保留结果数据
ret = QueueFront(noempty);
//将剩下的一个数据也转移
QueuePop(noempty);
QueuePush(empty, ret);
return ret;
}
//判断模拟栈是否为空,为空返回0,不为空返回1
int StackByTwoQueueEmpty(const StackByTwoQueue* stq)
{
assert(stq);
//只要有一个队列不为空那么模拟栈就不为空
return QueueEmpty(&(stq->q1)) | QueueEmpty(&(stq->q2));
}
//模拟栈中存入的元素个数
int StackByTwoQueueSize(const StackByTwoQueue* stq)
{
assert(stq);
return QueueSize(&(stq->q1)) + QueueSize(&(stq->q2));
}
//Push数据
void StackByTwoQueuePush(StackByTwoQueue* stq, DataType x)
{
Queue *empty;
Queue *noempty;
assert(stq);
EmptyCmp(&empty, &noempty, &stq);
//永远向不为空的队列插入数据
QueuePush(noempty,x);
}
//Pop数据
void StackByTwoQueuePop(StackByTwoQueue* stq)
{
Queue *empty;
Queue *noempty;
assert(stq);
EmptyCmp(&empty, &noempty, &stq);
//与StackByTwoQueueTop()一样的过程,只是最后余下的元素直接出队列
while (QueueSize(noempty) > 1)
{
QueuePush(empty, QueueFront(noempty));
QueuePop(noempty);
}
printf("Pop:%d\n", noempty->_front->_data);
QueuePop(noempty);
}
//测试函数
void TestStackByTwoQueue()
{
StackByTwoQueue sq;
StackByTwoQueueInit(&sq);
StackByTwoQueuePush(&sq, 11);
StackByTwoQueuePush(&sq, 22);
StackByTwoQueuePush(&sq, 33);
StackByTwoQueuePush(&sq, 44);
StackByTwoQueuePop(&sq);
StackByTwoQueuePop(&sq);
StackByTwoQueuePush(&sq, 55);
StackByTwoQueuePop(&sq);
StackByTwoQueuePop(&sq);
StackByTwoQueuePop(&sq);
StackByTwoQueueDestory(&sq);
}