[Queue Exercise] - Implementing a queue with a stack

topic description

Description
Please use only two stacks to implement a first-in-first-out queue. The queue should support all operations supported by general queues (push, peek, pop, empty) to
implement the MyQueue class:
1. void push(int x) pushes element x into the end of the queue.Method: Enter data into pushST.
2. int pop() removes and returns elements from the beginning of the queue.Method: Pop the data in pushST, put it in popST, and then pop out the data at the top of the stack.
3. int peek() returns the element at the beginning of the queue.Method: If popST is empty, first import the data in pushST into popST, and then return the data at the top of the stack. Otherwise, directly return the data at the top of the popST stack.
4. boolean empty() returns true if the queue is empty, otherwise returns false.Method: When the data of both stacks are empty, the stack is empty.

Note:
1. The queue is first in first out. 2. The stack is last in first out.
3. There is no ready-made stack in the C language, and the stack structure implemented by oneself is used. For details, refer to [Data Structure and Algorithm] - Stack


Problem solving analysis:

Idea:
core idea: first-in-first-out
Assuming pushA and popB stacks have entered 1234, how to make first-out 1?
1. When inputting data, go to the pushA stack to input data.
2. When outputting data, all the data in the pushA stack will be pushed out from the stack in turn, transferred to the popB stack for storage, and then pushed out to the popB stack.
3. Only when all the data in the popB stack is out, the data in the pushA stack is transferred to the popB stack, and the data continues to be out.
Hypothesis: first put 1 2 3 4 into A, then pop 4 3 2 1 into B, and finally pop 1.
If you want to enter data, then enter 5 6 into A. First output the data in B, then pop 5 and 6 into B, and finally pop 6.
insert image description here


Code:

1. MyQueue* myQueueCreate(); Create a queue

#include "Stack.h"

typedef struct {
    
    
	ST pushST;
	ST popST;
}MyQueue;

MyQueue* myQueueCreate()
{
    
    
	MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
	if (q == NULL)
		return NULL;
	//队列由两个栈pushST和popST组成,pushST和popST是由数组组成
	StackInit(&q->pushST);
	StackInit(&q->popST);

	return q;
	//为什么不定义MyQueue* q;再返回&q。因为不能返回局部变量的地址。你也可以使用传址调用通过形参返回。
}

2. void myQueuePush(MyQueue* obj, int x); enter the queue

//入数据,往pushA栈中,入数据
void myQueuePush(MyQueue* obj, int x)
{
    
    
	assert(obj);
	//在pushST栈中入数据
	StackPush(&obj->pushST, x);
}

3. int myQueuePop(MyQueue* obj); out of the queue

//出数据的候,将pushA栈依次从栈顶出数据,转移(栈入数据)到popB栈中保存,然后往popB栈顶出数据。
//移出并返回队头元素
int myQueuePop(MyQueue* obj)
{
    
    
	assert(obj);	
	//在popST栈中出数据(出数据时,只有当PopST栈没有数据才从PushST倒过去后,
	//再出数据,因为只有倒过来的数据才符合先进先出的顺序,否则直接在popST中出数据)
	if (StackEmpty(&obj->popST))
	{
    
    
		while (!StackEmpty(&obj->pushST))
		{
    
    
			StackPush(&obj->popST, StackTop(&obj->pushST));
			StackPop(&obj->pushST);
		}
	}
	
	//popST不为空,直接取数据
	int front = StackTop(&obj->popST);
	StackPop(&obj->popST);

	return front;//返回队头元素
}

4. int myQueuePeek(MyQueue* obj); get the queue head element

//返回队头元素
int myQueuePeek(MyQueue* obj)
{
    
    
	assert(obj);
	//如果popST中没有数据,将PushST中的数据导过去,再返回popST栈顶数据
	if (StackEmpty(&obj->popST))
	{
    
    
		while (!StackEmpty(&obj->pushST))
		{
    
    
			StackPush(&obj->popST, StackTop(&obj->pushST));
			StackPop(&obj->pushST);
		}
	}

	//如果popST不为空,直接取栈顶数据
	return StackTop(&obj->popST);
}

5. bool myQueueEmpty(MyQueue* obj); determine whether the queue is empty

bool myQueueEmpty(MyQueue* obj)
{
    
    
	assert(obj);
	//两个栈都为空,则队列为空
	return StackEmpty(&obj->popST) && StackEmpty(&obj->pushST);
}

6. void myQueueFree(MyQueue* obj); destroy the queue

void myQueueFree(MyQueue* obj)
{
    
    
	assert(obj);
	//注意:队列的结构
	StackDestroy(&obj->pushST);
	StackDestroy(&obj->popST);
	free(obj);
}

code testing

int main()
{
    
    
	MyQueue* q = myQueueCreate();

	myQueuePush(q, 1);
	myQueuePush(q, 2);
	myQueuePush(q, 3);
	myQueuePush(q, 4);

	while (!myQueueEmpty(q))
	{
    
    
		int front = myQueuePeek(q);
		printf("%d ", front);
		myQueuePop(q);
	}

	myQueueFree(q);
	return 0;
}

Summary:
1. When inputting data, go to the pushA stack to input data.
2. When outputting data, sequentially push all the data in the pushA stack from the top of the stack, transfer them to the popB stack for storage, and then push out the data to the popB stack. .
3. Only when all the data in the popB stack is out, the data in the pushA stack is transferred to the popB stack, and the data continues to be out.


Guess you like

Origin blog.csdn.net/qq_48163964/article/details/130139610