Realize Queue with Stack Simulation (c language version)

insert image description here

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

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.
①: stackpushEntering the simulating queue
②: stackpopExiting the simulating queue

insert image description here

1.2 Initialization (myQueueCreate):

The queue is implemented by two stacks, so focus on the initialization of the two stacks.

step:

  1. Apply for space of two stack sizes.
    Judge when the application fails.
  2. 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.

  1. In the initial state or stackpop(simulateddequeueWhen the data is out of the queue to empty, there is no data in it, so first judge stackpopwhether there is data.
    If there is data: it will be obtained stackpopdirectlystack topelement asteam leaderElement.
    No data: Reverse all the data from the simulated enqueue stack. (Reverse data)
  2. acquired stackpop_stack topelement asteam leaderElements, use topvariables to record. (Because it will be executed laterpop outoperate).
  3. pop out(simulating out of the queue), and returns topthe 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):

  1. stackpopWhen it is not empty, the first element of the team is stackpopthe stacktopelement.
  2. stackpopWhen it is empty, the first element of the team is stackpushthe 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 myQueuePopthe (dequeue) function, this function just returns the first element of the queue, and does not point to the popdequeue operation.
So we myQueuePopcan reuse myQueuePeekthe 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):

  1. Release the space opened up by the initialization of the two stacks
  2. 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:
insert image description here

Guess you like

Origin blog.csdn.net/qq_67276605/article/details/131138092