当前位置:首页 » 《随便一记》 » 正文

【LeetCode】用队列实现栈(225. 题)| 动图演示,超详细哦~_codewinterll的博客

26 人参与  2021年11月11日 12:03  分类 : 《随便一记》  评论

点击全文阅读


文章目录

    • (1)题目描述
    • (2)解题思路

题目难度:《简单》

(1)题目描述

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppopempty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false

注意:

  • 你只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsizeis empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
[ “MyStack”, “push”, “push”, “top”, “pop”, “empty” ]
[ [ ], [1], [2], [ ], [ ], [ ] ]
输出:
[ null, null, null, 2, 2, false ]

解释:
MyStack myStack = new MyStack( );
myStack.push(1);
myStack.push(2);
myStack.top( ); //返回 2
myStack.pop( ); //返回 2
myStack.empty( ); //返回 False

LeetCode链接:225. 用队列实现栈


(2)解题思路

  • 两个队列 Q1 和 Q2,相互倒数据,实现栈(先进后出)
  • 入数据,向不为空的那个队列入,
  • 出数据,将不为空的队列的前 size - 1 个数据倒入到另外一个空队列中,然后将不为空队列中剩下的一个数 Pop 掉,此时该队列为空了
  • 动图演示
LeetCode - 用队列实现栈_Trim
  • 代码如下

首先实现一个队列(链式结构),博主的上一篇博客讲了队列的实现,这里就直接贴代码了哦

【数据结构入门】队列(Queue)详解(定义、销毁、入队、出队等)| 图解数据结构,超详细哦~

typedef int QDataType;

typedef struct QueueNode  //队列节点结构
{
	QDataType data;          //节点数据
	struct QueueNode* next;  //节点指针
}QueueNode;

typedef struct QueuePtr  //队列的链式结构
{
	QueueNode* phead;  //队头指针
	QueueNode* ptail;  //队尾指针
}LinkQueue;

//初始化队列
void QueueInit(LinkQueue* pQ);
//销毁队列
void QueueDestroy(LinkQueue* pQ);
//入队(尾插)
void QueuePush(LinkQueue* pQ, QDataType x);
//出队(头删)
void QueuePop(LinkQueue* pQ);
//获取队列元素个数
int QueueSize(LinkQueue* pQ);
//获取队头元素
QDataType QueueFront(LinkQueue* pQ);
//获取队尾元素
QDataType QueueBack(LinkQueue* pQ);
//检查队列是否为空
bool QueueEmpty(LinkQueue* pQ);

//初始化队列
void QueueInit(LinkQueue* pQ)
{
	assert(pQ);
	//队列为空
	pQ->phead = pQ->ptail = NULL;
}

//销毁队列
void QueueDestroy(LinkQueue* pQ)
{
	assert(pQ);

	QueueNode* cur = pQ->phead;
	while (cur)  //遍历链式队列
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	cur = NULL;
	pQ->phead = pQ->ptail = NULL;  //队列为空
}

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

	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));  //动态申请一个节点
	if (newnode == NULL)  //检查是否申请成功
	{
		perror("malloc");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;  //尾节点next指针置空

	if (pQ->phead == NULL)  //队列为空
	{
		pQ->phead = newnode;
	}
	else  //队列不为空
	{
		pQ->ptail->next = newnode;
	}
	pQ->ptail = newnode;   //更新队尾指针
}

//出队(头删)
void QueuePop(LinkQueue* pQ)
{
	assert(pQ);
	assert(!QueueEmpty(pQ));  //队列不能为空

	if (pQ->phead == pQ->ptail)  //队列中只有一个节点
	{
		free(pQ->phead);
		pQ->phead = pQ->ptail = NULL;
	}
	else
	{
		QueueNode* next = pQ->phead->next;  //记录头节点的直接后继
		free(pQ->phead);  //释放头节点
		pQ->phead = next; //更新队头指针
	}
}

//获取队列元素个数
int QueueSize(LinkQueue* pQ)
{
	assert(pQ);

	int size = 0;
	QueueNode* cur = pQ->phead;
	while (cur)
	{
		size++;
		cur = cur->next;
	}
	return size;
}

//获取队头元素
QDataType QueueFront(LinkQueue* pQ)
{
	assert(pQ);
	assert(!QueueEmpty(pQ));  //队列不能为空

	return pQ->phead->data;
}

//获取队尾元素
QDataType QueueBack(LinkQueue* pQ)
{
	assert(pQ);
	assert(!QueueEmpty(pQ));  //队列不能为空

	return pQ->ptail->data;
}

//检查队列是否为空,若为空返回true,否则返回false
bool QueueEmpty(LinkQueue* pQ)
{
	assert(pQ);
	return pQ->phead == NULL && pQ->ptail == NULL;
}

核心代码

typedef struct {
    LinkQueue Q1;  //队列1
    LinkQueue Q2;  //队列2
} MyStack;

/** 初始化栈 */
MyStack* myStackCreate() {
    //创建两个队列
    MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
    if(pst == NULL)  //检查是否申请成功
    {
        perror("malloc");
        exit(-1);
    }
    //初始化两个队列
    QueueInit(&pst->Q1);
    QueueInit(&pst->Q2);

    return pst;
}

/** 入栈 */
void myStackPush(MyStack* obj, int x) {
    assert(obj);
    //入数据,向不为空的那个队列入
    if(!QueueEmpty(&obj->Q1))  //Q1不为空
    {
        QueuePush(&obj->Q1, x);
    }
    else
    {
        QueuePush(&obj->Q2, x);
    }
}

/** 出栈 */
int myStackPop(MyStack* obj) {
    assert(obj);
    
    //设置2个标志变量
    LinkQueue* emptyQ = &obj->Q1;    //假设Q1为空
    LinkQueue* nonemptyQ = &obj->Q2; //假设Q2不为空
    
    //确定标志变量
    if(!QueueEmpty(&obj->Q1))  //Q1不为空
    {
        nonemptyQ =  &obj->Q1; //Q1不为空
        emptyQ = &obj->Q2;     //Q2为空
    }
    
    //将非空队列的前size-1个元素导入到空队列中
    while(QueueSize(nonemptyQ) > 1)
    {
        QueuePush(emptyQ, QueueFront(nonemptyQ));
        QueuePop(nonemptyQ);
    }
    
    //Pop掉非空队列中剩下的最后一个元素,这个数据相当于MyStack的栈顶元素
    int top = QueueFront(nonemptyQ);  //获取最后一个元素
    QueuePop(nonemptyQ);              //出队最后一个元素
    return top;
}

/** 获取栈顶元素 */
int myStackTop(MyStack* obj) {
    assert(obj);

    //非空队列的队尾元素其实就是myStack栈顶元素
    if(!QueueEmpty(&obj->Q1))  //Q1不为空
    {
        return QueueBack(&obj->Q1);
    }
    else  //Q2不为空
    {
        return QueueBack(&obj->Q2);
    }
}

/** 对栈判空,若为空返回true,否则返回false */
bool myStackEmpty(MyStack* obj) {
    assert(obj);

    return QueueEmpty(&obj->Q1) && QueueEmpty(&obj->Q2);
}

/** 释放栈 */
void myStackFree(MyStack* obj) {
    assert(obj);

    QueueDestroy(&obj->Q1);  //释放链式队列Q1
    QueueDestroy(&obj->Q2);  //释放链式队列Q2

    free(obj);  //释放动态申请的空间
}

大家快去动手试一试吧!


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/30772.html

队列  为空  元素  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1