LeetCode-225:用队列实现栈(图文并茂)

题目描述

225.用队列实现栈

请你仅使用两个队列实现一个后入先出(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 这些操作。

示例1:

输入:
[“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

题解

用队列的先进先出来实现栈的先进后出,显然,一个队列是不够的,我们需要用两个队列来完成。即用一个队列来存储栈中的值,另一个队列负责保存有值队列中的值,以便于出栈。

① 实现入栈操作
假设已经在两个队列中已经插入了一些值了,但是我们并不知道到底是哪个队列中存在值,因为我们要保证另一条队列为空,才能实现出栈的操作,因此我们只需要判断一下两个队列的尾指针是否为空,然后在非空的队列的队尾插入数值。

在这里插入图片描述

②实现出栈操作
出栈是将栈顶的元素弹出,在队列中即就是将尾指针指向的地方弹出,则我们需要的将非空的队列中的元素通过出队操作存入空的队列中,直至剩下最后一个元素,在直接将其弹出即可

初始情况:
在这里插入图片描述
①将非空队列的元素存入空队列,直至剩余最后一个元素
在这里插入图片描述
②再将其弹出即可
在这里插入图片描述
因此,再经过一系列的入栈出栈操作后,我们并不知道哪个队列是空,哪个队列是非空,所以在每次入栈和出栈操作时,需要判断哪个队列为空

题解代码

typedef struct QNode
{
    struct QNode* next;
    int data;
}QListNode;

typedef struct QList
{
    QListNode* front;
    QListNode* tail;
}Queue;

//初始化
void QueueInit(Queue* q)
{
    assert(q);
    q->front = q->tail = NULL;

}

//申请一个队列结点
QListNode* BuyNode(int x)
{
    QListNode* ret = (QListNode*)malloc(sizeof(QListNode));
    ret->data = x;
    ret->next = NULL;
    return ret;
}

//入队列
void QueuePush(Queue* q,int data)
{
    assert(q);

    QListNode* tmp = BuyNode(data);

    //证明列表为NULL
    if(q->tail == NULL)
    {
        q->tail = q->front = tmp;
    }
    else
    {
        q->tail->next = tmp;
        q->tail = tmp;
    }
}

//出队列(并返回数值)
void QueuePop(Queue* q)
{
    assert(q);
    assert(!QueueEmpty(q));


    //只有一个结点时
    if(q->front == q->tail)
    {
        free(q->front);
        q->front = q->tail = NULL;
    }
    else
    {
        QListNode* tmp = q->front->next;
        free(q->front);
        q->front = tmp;
    }

}

//获取队列当前的值(队头)
int GetQueueFront(Queue* q)
{
    assert(q);
    assert(!QueueEmpty(q));
    return q->front->data;
}

//获取队尾的值
int GetQueueTail(Queue* q)
{
    assert(q);
    assert(!QueueEmpty(q));
    return q->tail->data;
}

//获取当前队列的元素个数
int GetQueueSize(Queue* q)
{
    assert(q);

    QListNode* cur = q->front;
    int size = 0;

    while(cur)
    {
        size++;
        cur = cur->next;
    }
    return size;
}

//检查是否为NULL,是则返回1,否则返回0
int QueueEmpty(Queue* q)
{
    assert(q);

    return q->front == NULL ? 1 : 0;
}

//摧毁队列
void QueueDestory(Queue* q)
{
    assert(q);

    QListNode* cur = q->front;
    while(cur)
    {
        QListNode* tmp = cur->next;
        free(cur);
        cur = tmp;
    }
    q->front = q->tail = NULL;
}



typedef struct {
    Queue first;
    Queue second;
} MyStack;

/** Initialize your data structure here. */

MyStack* myStackCreate() {
    MyStack* my = (MyStack*)malloc(sizeof(MyStack));
    QueueInit(&my->first);
    QueueInit(&my->second);
    return my;
}

/** Push element x onto stack. */
void myStackPush(MyStack* obj, int x) {
    Queue* q1 = &obj->first;
    Queue* q2 = &obj->second;
    //谁不为NULL就往进插
    if(!QueueEmpty(q1))
    {
        QueuePush(q1,x);
    }
    else{
        QueuePush(q2,x);
    }
}

/** Removes the element on top of the stack and returns that element. */
int myStackPop(MyStack* obj) {
    
    //q1代表空队列,q2代表非空数列
    Queue* q1 = &obj->first;
    Queue* q2 = &obj->second;

    //若q1是非空队列,则交换q1,q2
    if(!QueueEmpty(q1))
    {
        Queue* tmp = q1;
        q1 = q2;
        q2 = tmp;
    }

    //然后将非空队列的值从队头插入到空队列的队尾中去,最后只剩一个元素
    while(GetQueueSize(q2) > 1)
    {
        QueuePush(q1,GetQueueFront(q2));
        QueuePop(q2);
    }

    //将剩下的一个元素返回,并将其弹出
    int ret = GetQueueFront(q2);
    QueuePop(q2);
    return ret;
}

/** Get the top element. */
int myStackTop(MyStack* obj) {
    //若first队列不为空,则返回他的队尾元素
    if(!QueueEmpty(&obj->first))
    {
        return GetQueueTail(&obj->first);
    }
    else{
        return GetQueueTail(&obj->second);
    }
}

/** Returns whether the stack is empty. */
bool myStackEmpty(MyStack* obj) {
    //只有当两个均为空时,栈才为空
    return QueueEmpty(&obj->first) && QueueEmpty(&obj->second);

}

void myStackFree(MyStack* obj) {
    //将两个全部free才可以
    QueueDestory(&obj->first);
    QueueDestory(&obj->second);

    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);
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用两个队列实现的 Kotlin 代码: ``` import java.util.* class MyStack() { private val queue1 = LinkedList<Int>() private val queue2 = LinkedList<Int>() private var topElement: Int? = null /** Push element x onto stack. */ fun push(x: Int) { queue2.offer(x) topElement = x while (!queue1.isEmpty()) { queue2.offer(queue1.poll()) } val temp = queue1 queue1 = queue2 queue2 = temp } /** Removes the element on top of the stack and returns that element. */ fun pop(): Int { val popped = queue1.poll() if (queue1.isEmpty()) { topElement = null } else { topElement = queue1.peek() } return popped } /** Get the top element. */ fun top(): Int { return topElement!! } /** Returns whether the stack is empty. */ fun empty(): Boolean { return queue1.isEmpty() } } ``` 解释一下代码: 我们使用两个队列 `queue1` 和 `queue2` 来模拟。`queue1` 存储中的元素,而 `queue2` 用来在 `push` 操作时暂存元素。 在 `push` 操作中,我们首先把元素 `x` 加入到 `queue2` 中,然后将 `queue1` 中的所有元素依次加入到 `queue2` 中。这样做的目的是为了让 `queue2` 中的元素按照的顺序排列,即最后加入的元素在队首,而最先加入的元素在队尾。然后我们将 `queue2` 和 `queue1` 交换,这样 `queue1` 中的元素就按照的顺序排列了。 在 `pop` 操作中,我们直接从 `queue1` 中弹出队首元素即可。如果 `queue1` 变为空队列,则将 `topElement` 置为 `null`。 在 `top` 操作中,我们返回 `topElement`,它记录了顶元素的值。 在 `empty` 操作中,我们判断 `queue1` 是否为空即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值