队列和栈的相互实现(二)

本篇文章来用两个栈来实现队列

目录

用栈实现队列

栈的编写

队列的实现分析

队列的定义及初始化

 入队(入栈)

出队(出栈)

返回队头元素

判断队列是否为空和队列的销毁


做题链接: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);
}

猜你喜欢

转载自blog.csdn.net/weixin_53316121/article/details/123928054