本篇文章来用两个栈来实现队列
目录
做题链接:232. 用栈实现队列 - 力扣(LeetCode) (leetcode-cn.com)
用栈实现队列
用两个后进先出的栈实现一个先进先出的队列。
入栈1 2 3 4 5
出栈1 2 3 4 5
栈的编写
栈有后进先出的性质,对栈顶进行操作即可,我们选用顺序表来进行栈的实现,前面已经实现过,我们直接上代码:
typedef int Datatype;
typedef struct Stack
{
Datatype* a;
int top; //栈顶位置
int capacity; //容量
}ST;
void StackInit(ST* ps);
void StackDestory(ST* ps);
void StackPush(ST* ps,Datatype x);
void StackPop(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);
//数据个数
int StackSize(ST* ps);
//访问栈顶数据
Datatype StackTop(ST* ps);
//初始化
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->capacity = 0;
ps->top = 0;
}
//销毁
void StackDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
void StackPush(ST* ps, Datatype x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
ps->a = realloc(ps->a, newcapacity*sizeof(Datatype));
if (ps->a == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
assert(ps);
assert(ps->top>0);
ps->top--;
}
//判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
//if (ps->top > 0)
//{
// return false;
//}
//else
//{
// return true;
//}
return ps->top == 0;
}
//数据个数
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
//访问栈顶数据
Datatype StackTop(ST* ps)
{
assert(ps);
assert(ps->top>0);
return ps->a[ps->top-1];
}
队列的实现分析
两个栈实现队列,用两个后进先出的栈实现一组数据的先进先出。
图解:
队列的定义及初始化
依旧是开辟空间,判断是否成功,然后初始化队列中的两个栈。
typedef struct {
ST Pushs1;
ST Pops2;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
assert(obj);
StackInit(&obj->Pushs1);
StackInit(&obj->Pops2);
return obj;
}
入队(入栈)
栈初始化,已经置空,直接入栈即可
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
StackPush(&obj->Pushs1,x);
}
出队(出栈)
由图解分析得,先得进行一次数据得倒入,再出栈有数据的栈即可
先判断第二个栈是否为空栈,空栈才能进行倒入,在判断第一个栈是否有元素。
倒入一个栈顶元素进空栈,并出栈原栈的栈顶元素,循环进行,直到原栈为空
注意:要求pop时要返回对头元素,对头元素即是栈顶元素。
之后出栈栈顶元素即可。
int myQueuePop(MyQueue* obj) {
assert(obj);
//s2空时需要push进s1元素才能出
if(StackEmpty(&obj->Pops2))
{
while(!StackEmpty(&obj->Pushs1))
{
StackPush(&obj->Pops2,StackTop(&obj->Pushs1));
StackPop(&obj->Pushs1);
}
}
int front=StackTop(&obj->Pops2);
StackPop(&obj->Pops2);
return front;
}
返回队头元素
队头元素是倒入一次数据后非空栈的栈顶元素
进行一次判断倒入后,直接返回即可。
int myQueuePeek(MyQueue* obj) {
assert(obj);
if(StackEmpty(&obj->Pops2))
{
while(!StackEmpty(&obj->Pushs1))
{
StackPush(&obj->Pops2,StackTop(&obj->Pushs1));
StackPop(&obj->Pushs1);
}
}
return StackTop(&obj->Pops2);
}
判断队列是否为空和队列的销毁
队列里面还有两个栈,两个栈为空队列才为空,直接return即可。
销毁时先销毁两个栈,再销毁队列,防止内存泄漏。
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&obj->Pushs1)&&StackEmpty(&obj->Pops2);
}
void myQueueFree(MyQueue* obj) {
StackDestory(&obj->Pushs1);
StackDestory(&obj->Pops2);
free(obj);
}