foreword
use"stack implements queue", an oj question in Likou, can help novices who are new to "stack" and "queue" better understand the two structures of stack and queue.
The topic comes from Leetcode :
Topic link : https://leetcode.cn/problems/implement-queue-using-stacks/
Difficulty: Simple
Table of contents
1. The interfaces of the queue:
1.1 Type declaration (MyQueue):
//模拟队列类型的声明
typedef struct {
ST stackpush; //用于模拟队列的 入队操作
ST stackpop; //用于模拟队列的 出队操作
} MyQueue;
Here is the use of two stacks for simulating queues.
①: stackpush
Entering the simulating queue
②: stackpop
Exiting the simulating queue
1.2 Initialization (myQueueCreate):
The queue is implemented by two stacks, so focus on the initialization of the two stacks.
step:
- Apply for space of two stack sizes.
Judge when the application fails. - For two stacks in the queue, call theirinitializationFunction. (Don't miss this, Niu Niu has been looking for a long time after missing it)
//队列的初始化
MyQueue* myQueueCreate() {
//给队列开辟空间
MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
if(obj==NULL)
{
perror("obj malloc fail");
}
//一定要记得这里要初始化(别漏掉了哦)
InitST(&obj->stackpush);
InitST(&obj->stackpop);
return obj;
}
1.3 Entering the queue (myQueuePush)
The simulation implementation of entering the queue is very simple, just push the data onto the stack (simulate entering the queue: stackpush
).
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
STPush(&obj->stackpush,x);
}
1.4 Queue out (myQueuePop)
Function requirements:
Dequeue the first element of the team, and return the first element of the team that has just been dequeued.
Simulating dequeuing is relatively complicated.
- In the initial state or
stackpop
(simulateddequeueWhen the data is out of the queue to empty, there is no data in it, so first judgestackpop
whether there is data.
If there is data: it will be obtainedstackpop
directlystack topelement asteam leaderElement.
No data: Reverse all the data from the simulated enqueue stack. (Reverse data) - acquired
stackpop
_stack topelement asteam leaderElements, usetop
variables to record. (Because it will be executed laterpop outoperate). - pop out(simulating out of the queue), and returns
top
the variable.
int myQueuePop(MyQueue* obj) {
assert(obj);
if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出队列的栈)为空,则向栈(stackpush模拟入队列的栈)要数据
{
//下面循环结束的条件是不为空
while(!STEmpty(&obj->stackpush))//将数据从模拟入队列栈全部倒过来
{
//将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出栈)
STPush(&obj->stackpop,STTop(&obj->stackpush));
STPop(&obj->stackpush);
}
}
int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
STPop(&obj->stackpop);
return top;
}
1.5 Empty judgment of the queue (myQueueEmpty)
When there are no elements in either stack, the queue is empty.
//Writing 1
bool myQueueEmpty(MyQueue* obj) {
if(STEmpty(&obj->stackpush)&&STEmpty(&obj->stackpop))//如果都为空,则为空栈
{
return true;
}
else
return false;
}
//Writing 2.
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->stackpush) && STEmpty(&obj->stackpop);
}
1.6 Return to the first element of the queue (myQueuePeek):
stackpop
When it is not empty, the first element of the team isstackpop
the stacktopelement.stackpop
When it is empty, the first element of the team isstackpush
the stackendelement.
So here also need to pour data.
int myQueuePeek(MyQueue* obj) {
assert(obj);
if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出队列)为空,则向栈(stackpush模拟入队列)要数据
{
while(!STEmpty(&obj->stackpush))
{
//将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出队列)
STPush(&obj->stackpop,STTop(&obj->stackpush));
STPop(&obj->stackpush);
}
}
int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
return top;
}
Compared with myQueuePop
the (dequeue) function, this function just returns the first element of the queue, and does not point to the pop
dequeue operation.
So we myQueuePop
can reuse myQueuePeek
the function when implementing the function.
int myQueuePop(MyQueue* obj) {
int top=myQueuePeek(obj);
STPop(&obj->stackpop);
return top;
}
1.7 Destruction of the queue (myQueueFree):
- Release the space opened up by the initialization of the two stacks
- Release the space requested by the queue.
void myQueueFree(MyQueue* obj) {
STDestory(&obj->stackpush);
STDestory(&obj->stackpop);
free(obj);
}
Second, the total code:
The previous code is the implementation of the stack, because the C language cannot directly call the library like C++.
typedef int stacktype;
typedef struct stack//定义栈的类型
{
stacktype* data;
int top;
int capacaity;
}ST;
void InitST(ST* ps);//初始化栈
void STPush(ST* ps, stacktype x);//压栈
void STPop(ST* ps);//出栈
bool STEmpty(ST* ps);//判断是否为空栈
stacktype STTop(ST* ps);//返回栈顶元素
void STDestory(ST* ps);//栈的销毁
void InitST(ST* ps)//初始化栈
{
assert(ps);
ps->top = -1;
ps->capacaity = 4;
ps->data = (stacktype*)malloc(ps->capacaity * sizeof(stacktype));
}
void STPush(ST* ps, stacktype x)//压栈
{
assert(ps);
if (ps->top+1 == ps->capacaity)
{
ps->capacaity *= 2;
ST* tmp = (stacktype*)realloc(ps->data, ps->capacaity * sizeof(stacktype));
if(tmp == NULL)
{
printf("增容失败\n");
}
ps->data = tmp;
}
ps->top++;
ps->data[ps->top] = x;
}
void STPop(ST* ps)//出栈
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
bool STEmpty(ST* ps)//判断是否为空栈,是空返回真
{
assert(ps);
if (ps->top == -1)
{
return true;
}
return false;
}
stacktype STTop(ST* ps)//返回栈顶元素
{
assert(ps);
return ps->data[ps->top];
}
void STDestory(ST* ps)//销毁栈
{
assert(ps);
free(ps->data);
ps->data = NULL;
ps->top = -1;
ps->capacaity = 0;
}
//模拟队列类型的声明
typedef struct {
ST stackpush;
ST stackpop;
} MyQueue;
//队列的初始化
MyQueue* myQueueCreate() {
MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
if(obj==NULL)
{
perror("obj malloc fail");
}
//一定要记得这里要初始化
InitST(&obj->stackpush);
InitST(&obj->stackpop);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
assert(obj);
STPush(&obj->stackpush,x);
}
int myQueuePop(MyQueue* obj) {
assert(obj);
if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出栈)为空,则向栈(stackpush模拟入栈)要数据
{
while(!STEmpty(&obj->stackpush))
{
//将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出栈)
STPush(&obj->stackpop,STTop(&obj->stackpush));
STPop(&obj->stackpush);
}
}
int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
STPop(&obj->stackpop);
return top;
}
bool myQueueEmpty(MyQueue* obj) {
if(STEmpty(&obj->stackpush)&&STEmpty(&obj->stackpop))//如果都为空,则为空栈
{
return true;
}
else
return false;
//return STEmpty(&obj->stackpush)&&STEmpty(&obj->stackpop);
}
int myQueuePeek(MyQueue* obj) {
if(STEmpty(&obj->stackpop))//如果栈(stackpop模拟出栈)为空,则向栈(stackpush模拟入栈)要数据
{
while(!STEmpty(&obj->stackpush))
{
//将栈(stackpush模拟入队)的栈顶元素依次压入栈(stackpop模拟出栈)
STPush(&obj->stackpop,STTop(&obj->stackpush));
STPop(&obj->stackpush);
}
}
int top=STTop(&obj->stackpop);//记录用来模拟出队列的栈的栈顶元素;
return top;
//return STTop(&obj->stackpop);
}
void myQueueFree(MyQueue* obj) {
STDestory(&obj->stackpush);
STDestory(&obj->stackpop);
free(obj);
}
operation result: