【Leetcode】用队列实现栈

本文介绍如何利用两个队列实现LeetCode中栈的功能,包括初始化、压栈、弹栈、查看栈顶元素及判断栈是否为空的操作。通过实例详细解析每个操作的逻辑和实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 225. 用队列实现栈 - 力扣(LeetCode) (leetcode-cn.com)

先看题目要求,用两个队列实现栈,我们先把之前写过的队列相关的一些函数拿来:

typedef int QDataType;


typedef struct QNode
{
	QDataType data;
	struct queue* next;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
}Queue;




void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;
}

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	assert(newnode);

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

	if (pq->tail == NULL)
	{
		assert(pq->head == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head && pq->tail);

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
}

bool QueueEmpty(Queue* q)
{
	assert(q);

	return q->head == NULL;
}

size_t QueueSize(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	size_t size = 0;
	while (cur)
	{
		size++;
		cur = cur->next;
	}

	return size;
}

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

	return pq->head->data;
}

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

	return pq->tail->data;
}

这里用两个队列实现,所以我们创建一个结构体:

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

结构体里面两个指针,每一个指针对应一个队列,然后我们正式开始写这道题

--------

先从初始化函数开始:

MyStack* myStackCreate() {
	
}

单看函数,它需要返回一致MyStack* 的指针,既然要返回指针,那我们就得用malloc开辟空间,然后开辟好的MyStack结构体其中的Queue结构体,我们可以直接调用其初始化函数,然后即可。

MyStack* myStackCreate() {
    //开辟空间
	MYStack* obj = (MYStack*)malloc(sizeof(MyStack));
    //最好判断一下开辟成功没    
    assert(obj);

    //初始化obj结构体里面的Queue结构体
    QueueInit(&obj->q1);
    QueueInit(&obj->q2);
    
    //返回初始化好的结构体
    return obj;
}

将元素X压入栈顶:

先说说思路:

我们现在有两个队列,两个队列分别有头尾指针,假设现在要将 1 2压入栈,那我们找其中一个不是空的队列压进去:

 这样方便我们之后的一系列操作:

void myStackPush(MyStack* obj, int x) {
    assert(obj);

    //判断obj->q1是否为空,不为空压q1
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    //其他情况压q2
    else
    {
        QueuePush(&obj->q2,x);
    } 
}

     移除并返回栈顶元素:

还是先看思路,我们要移除并且返回栈顶的元素,因为栈是先后后出,所以我们刚刚压进来的 1 2出的时候就应该是 2 1。

按照之前玩单链表的思路,我们就应该是先找到最后一个节点,保存里面的值,然后释放掉最后节点,但是这题要用到第二个队列,所以这样做就有点跑题,这里我们换一种办法。

已知 q1 里面有 1 2,我们要返回 2

我们拿q2来接收q1里面的值,直到q1 里面只剩一个值位置,然后我们保存这个值再将其释放掉,下一次压栈压的就是q2的位置,如果还要移除的话就把q2的值移到q1里面。

 将q1的1拿过来:

 然后返回q1里面的值,再将其置为空:

 假设现在要尾插 3 4 5:

 然后再出来就把1 3 4 移到q1里面:

重复即可,然后我们就来实现代码:

int myStackPop(MyStack* obj) {
    assert(obj);
    Queue* empty = &obj->q1;
    Queue* noempty = &obj->q2;

    if(!QueueEmpty(&obj->q1))
    {
        noempty = &obj->q1;
        empty = &obj->q2;
    }

    while(QueueSize(noempty) > 1)
    {
        QueuePush(empty,QueueFront(noempty));
        QueuePop(noempty);
    }

    int data = QueueFront(noempty);
    QueuePop(noempty);
    return data;
}

 一行一行看:

先判断obj不为空指针,然后假设空的那个队列是q1,非空的是q2,然后判断,如果q1是非空的,那就让非空的指向q1,空的指向q2

如果非空链表里面留下的节点数量大于1,说明我们还要移动

我们在空链表的后面尾插,尾插的是非空链表的元素

比方说刚刚的 1 2

那我们就把1移过去

每次移完记得删掉原本节点,不然程序会死循环

当循环结束,就意味着非空队列里面只有一个元素了,我们获取到这个元素之后再将这个节点也删掉,返回我们获得的元素。

返回栈顶元素:

返回栈顶元素,也就是返回我们最后压进去的元素,正因为我们每次压栈都是在非空队列尾插,所以我们可以直接返回非空节点的最后一个元素即可:

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

判断栈是否为空:

我们只需要判断两个队列即可,调用一下我们之前写的判断队列的函数:

ibool myStackEmpty(MyStack* obj) {
    assert(obj);
    return QueueEmpty(&obj->q1)&& QueueEmpty(&obj->q2);
}

销毁栈:

 这个更是简单,我们还是直接调用销毁队列的两个函数,最后释放掉我们的obj即可

void myStackFree(MyStack* obj) {
    assert(obj);
    QueueDestory(&obj->q1);
    QueueDestory(&obj->q2);
    free(obj);
}

这里放上全部代码,有需要可以复制:

typedef int QDataType;


typedef struct QNode
{
	QDataType data;
	struct queue* next;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
}Queue;

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


void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;
}

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	assert(newnode);

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

	if (pq->tail == NULL)
	{
		assert(pq->head == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head && pq->tail);

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
}

bool QueueEmpty(Queue* q)
{
	assert(q);

	return q->head == NULL;
}

size_t QueueSize(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	size_t size = 0;
	while (cur)
	{
		size++;
		cur = cur->next;
	}

	return size;
}

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

	return pq->head->data;
}

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

	return pq->tail->data;
}



MyStack* myStackCreate() {
	MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
    assert(obj);

    QueueInit(&obj->q1);
    QueueInit(&obj->q2);

    return obj;
}

void myStackPush(MyStack* obj, int x) {
    assert(obj);

    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
        QueuePush(&obj->q2,x);
    } 
}

int myStackPop(MyStack* obj) {
    assert(obj);
    Queue* empty = &obj->q1;
    Queue* noempty = &obj->q2;

    if(!QueueEmpty(&obj->q1))
    {
        noempty = &obj->q1;
        empty = &obj->q2;
    }

    while(QueueSize(noempty) > 1)
    {
        QueuePush(empty,QueueFront(noempty));
        QueuePop(noempty);
    }

    int data = QueueFront(noempty);
    QueuePop(noempty);
    return data;
}

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

bool myStackEmpty(MyStack* obj) {
    assert(obj);
    return QueueEmpty(&obj->q1)&& QueueEmpty(&obj->q2);
}

void myStackFree(MyStack* obj) {
    assert(obj);
    QueueDestory(&obj->q1);
    QueueDestory(&obj->q2);
    free(obj);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值