(动画详解)LeetCode225.用队列实现栈

. - 力扣(LeetCode)

题目描述

解题思路

这道题的思路就是使用两个队列来实现

入栈就是入队列

出栈就是将非空队列的前n-1个元素移动到新的队列中去

再将最后一个元素弹出

动画详解

代码实现

 

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

typedef int QDataType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType x;
}QNode;

// 使用另一个结构体来存储头尾指针,指向队列的头尾
typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

void QueueDestroy(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);

		cur = next;
	}

	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

// 队尾插入
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}

	newnode->next = NULL;
	newnode->x = x;

	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}

	pq->size++;
}

// 队头删除
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

	/*QNode* next = pq->phead->next;
	free(pq->phead);
	pq->phead = next;

	if (pq->phead == NULL)
		pq->ptail = NULL;*/

		// 一个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else // 多个节点
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}

	pq->size--;
}

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);

	return pq->phead->x;
}

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);

	return pq->ptail->x;
}


int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

bool QueueIsEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}

typedef struct
{
	Queue q1;
	Queue q2;
} MyStack;


MyStack* myStackCreate()
{
	// 使用malloc开辟新的栈,防止局部变量出作用域之后被销毁
	// 不能使用全局变量,因为下一次调用的时候全局变量不会初始化
	MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
	// 调用队列初始化函数对两个队列进行初始化
	QueueInit(&(obj->q1));
	QueueInit(&(obj->q2));
	return obj;
}

void myStackPush(MyStack* obj, int x)
{
	// 向不为空的队列插入数据
	if (QueueIsEmpty(&obj->q1))
	{
		QueuePush(&(obj->q1), x);
	}
	else
	{
		QueuePush(&(obj->q2), x);
	}
}

int myStackPop(MyStack* obj)
{
	// 将前size-1个数据弹出,导入到不为空的队列中去,再删除非空队列中的最后一个数据
	// 使用假设法来判断空队列
	Queue* empty = &(obj->q1);
	Queue* notempty = &(obj->q2);
	if (!QueueIsEmpty(&(obj->q1)))
	{
		notempty = &(obj->q1);
		empty = &(obj->q2);
	}
	// 开始遍历
	while (QueueSize(notempty) > 1)
	{
		// 向空队列中插入非空队列中的数据
		QueuePush(empty, QueueFront(notempty));
		// 弹出非空队列的数据
		QueuePop(notempty);
	}
	int top = QueueFront(notempty);
	// 弹出非空队列中的最后一个数据,实现出栈操作
	QueuePop(notempty);
	return top;
}

int myStackTop(MyStack* obj)
{
	if (!QueueIsEmpty(&obj->q1))
	{
		return QueueBack(&obj->q1);
	}
	else
	{
		return QueueBack(&obj->q2);
	}
}

bool myStackEmpty(MyStack* obj)
{
	return QueueIsEmpty(&(obj->q1)) && QueueIsEmpty(&(obj->q2));

}

void myStackFree(MyStack* obj)
{
	// 不能直接释放obj,因为还有剩下的链表没有释放,将成为野指针
	QueueDestroy(&obj->q1);
	QueueDestroy(&obj->q2);
	free(obj);
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);

 * int param_2 = myStackPop(obj);

 * int param_3 = myStackTop(obj);

 * bool param_4 = myStackEmpty(obj);

 * myStackFree(obj);
*/

复杂度分析

我们可以发现,这个代码仅有在将非空队列的元素导入空队列时有循环,因此时间复杂度为O(n)

总结

Bye!!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿梦Anmory

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值