队列实现栈
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列是先进先出
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈是后进先出
栈顶:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
栈底:栈的删除操作叫做出栈。出数据也在栈顶
我们选择链表进行操作
为什么不用数组呢?
对于队列我们要进行入队和出队的操作,如果是使用数组来实现的话,那么我们所需要的时间开销就很大,需要不停的挪动数据。但是反过来看链表的话,就方便了许多,不需要频繁的挪动数据,入队出队时的操作都显得相对容易和快速
我们的思路就是:创建两个队列,保存一个队列存数据不为空,另一个队列为空。
- pop接口:
把非空队列的前n-1个元素转移到空队列中,再把空队列中的最后一个元素pop掉。
这里我借用大佬的动图给你们演示一下。
-
push接口:
直接在非空队列插入即可
q1为空就在q1插入
q2为空就在q2插入 -
top接口:
判断哪个队列为非空队列,直接返回非空队列的队尾节点 -
empty接口:
两个队列都为空就为true
代码实现
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&obj->q1);
QueueInit(&obj->q2);
return obj;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
{
return QueuePush(&obj->q1, x);
}
else
{
return QueuePush(&obj->q2, x);
}
}
int myStackPop(MyStack* obj) {
//设置非空和空队列
Queue* Qempty = &obj->q1;
Queue* noQempty = &obj->q2;
if(!QueueEmpty(&obj->q1))
{
noQempty = &obj->q1;
Qempty = &obj->q2;
}
//把非空中前n-1个元素push到空中
while(QueueSize(noQempty) > 1)
{
//转移
QueuePush(Qem