【队列练习】 - 用栈实现队列

题目描述

描述
请你仅使用两个栈实现一个先入先出的队列,队列应当支持一般队列支持的所有操作(push、peek、pop、empty)
实现MyQueue类:
1、void push(int x)将元素x推入队列的末尾。方法:往pushST中入数据。
2、int pop()从队列的开头移除并返回元素。方法:将pushST中的数据pop掉,放入popST中,再出栈顶的数据。
3、int peek()返回队列开头的元素。方法:如果popST为空,则先将pushST中的数据导入popST中,再返回栈顶的数据。否则直接返回popST栈顶的数据。
4、boolean empty()如果队列为空,返回true,否则返回false。方法:当两个栈的数据都为空,则栈为空。

注意:
1、队列是先进先出。2、栈是后进先出。
3、C语言没有现成的栈,使用自己实现的栈结构,详情参考【数据结构和算法】 - 栈


解题分析:

思路:
核心思路:符合先进先出
假设pushA和popB栈,入了1234,如何使得先出1?
1、入数据的时候,往pushA栈中,入数据
2、出数据的时候,依次将pushA栈所有的数据从栈顶出数据,转移到popB栈中保存,然后往popB栈顶出数据。
3、只有当popB栈中所有的数据都出完后,再将pushA栈中的数据转移到popB栈中,继续出数据。
假设:先1 2 3 4入A中,再pop掉4 3 2 1放入到B中,最后再pop掉1。
如果要入数据,再向A中入5 6。先出完B中的数据,再pop掉5 6放入到B中,最后再pop掉6。
在这里插入图片描述


代码实现:

1、MyQueue* myQueueCreate();创建队列

#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);入队列

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

3、int myQueuePop(MyQueue* obj);出队列

//出数据的候,将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);获取队头元素

//返回队头元素
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);判断队列是否为空

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

6、void myQueueFree(MyQueue* obj);销毁队列

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

代码测试

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;
}

总结:
1、入数据的时候,往pushA栈中,入数据
2、出数据的时候,依次将pushA栈所有的数据从栈顶出数据,转移到popB栈中保存,然后往popB栈顶出数据。
3、只有当popB栈中所有的数据都出完后,再将pushA栈中的数据转移到popB栈中,继续出数据。


猜你喜欢

转载自blog.csdn.net/qq_48163964/article/details/130139610
今日推荐