文章目录
- (1)题目描述
- (2)解题思路
题目难度:《简单》
(1)题目描述
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(
push
、top
、pop
和empty
)。实现
MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。注意:
- 你只能使用队列的基本操作 —— 也就是
push to back
、peek/pop from front
、size
和is 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 掉,此时该队列为空了
- 动图演示
- 代码如下
首先实现一个队列(链式结构),博主的上一篇博客讲了队列的实现,这里就直接贴代码了哦
【数据结构入门】队列(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); //释放动态申请的空间
}
大家快去动手试一试吧!