代码随想录算法训练营第十天_第五章_栈与队列 | 理论基础、232.用栈实现队列、225. 用队列实现栈

理论基础

  • 了解栈与队列的内部实现机制
  1. C++中stack 是容器么?
  2. 我们使用的stack是属于哪个版本的STL?
  3. 我们使用的STL中stack是如何实现的?
  4. stack 提供迭代器来遍历stack空间么?
  •  容器适配器(C++ Primer 9.6 P329)

LeetCode 232.用栈实现队列

题目描述:仅使用两个栈实现先入先出队列。

        队列应当支持一般队列支持的所有操作(push、pop、peek、empty)

实现 MyQueue 类:

        void push(int x) 将元素 x 推到队列的末尾
        int pop() 从队列的开头移除并返回元素
        int peek() 返回队列开头的元素
        boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:

        只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。

视频讲解https://www.bilibili.com/video/BV1nY4y1w7VC文章讲解https://programmercarl.com/0232.%E7%94%A8%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97.html

用两个栈实现队列(FIFO)

                                                                                  1        2        3        4

                                                                        4        1        2        3

                                                              3        4        1        2

                                                    2        3        4        1

                                          1        2        3        4

                                                                                  1        2

                                                                        2        1

                                                              1        2

                                                              1        2        3        4

  • 思路:
    • 左栈为空,右栈元素依次转移到左栈(LIFO→FILO)
    • 左栈不为空,则左栈顶元素为队列开头(FILO→LIFO)
    • 右→左发生在左栈为空的时候,且右栈元素全部转移出来,说明当前右栈元素进栈之前,已经进行了右→左的操作,则一定有左栈元素先于右栈
  • 代码:
class MyQueue {
public:
    stack<int> LeftStack;
    stack<int> RightStack;
    // 初始化
    MyQueue() {

    }
    // 压入右栈
    void push(int x) {
        RightStack.push(x);
    }
    // 如果左栈不为空,直接弹出左栈顶
    // 如果左栈为空,先将右栈中的所有元素转移到左栈,再弹出左栈顶
    int pop() {
        if (LeftStack.empty()) {
            while (!RightStack.empty()) {
                int value = RightStack.top();
                RightStack.pop();
                LeftStack.push(value);
            }
        }
        int result = LeftStack.top();
        LeftStack.pop();
        return result;
    }
    // 即返回左栈顶元素
    // 或右栈底
    int peek() {
        if (LeftStack.empty()) {
            while (!RightStack.empty()) {
                int value = RightStack.top();
                RightStack.pop();
                LeftStack.push(value);
            }
        }
        return LeftStack.top();
    }
    // 左栈和右栈都为空才算空
    bool empty() {
        if (LeftStack.empty() && RightStack.empty()) {
            return true;
        }
        return false;
    }
};

⭐函数复用

// 代码随想录
class MyQueue {
public:
    stack<int> stIn;
    stack<int> stOut;
    /** Initialize your data structure here. */
    MyQueue() {

    }
    /** Push element x to the back of queue. */
    void push(int x) {
        stIn.push(x);
    }

    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        // 只有当stOut为空的时候,再从stIn里导入数据(导入stIn全部数据)
        if (stOut.empty()) {
            // 从stIn导入数据直到stIn为空
            while(!stIn.empty()) {
                stOut.push(stIn.top());
                stIn.pop();
            }
        }
        int result = stOut.top();
        stOut.pop();
        return result;
    }

    /** Get the front element. */
    int peek() {
        int res = this->pop(); // 直接使用已有的pop函数
        stOut.push(res); // 因为pop函数弹出了元素res,所以再添加回去
        return res;
    }

    /** Returns whether the queue is empty. */
    bool empty() {
        return stIn.empty() && stOut.empty();
    }
};

 pop() 比 peek() 多了一步,复用 peek() 更方便:

// 复用peek()
class MyQueue {
public:
    stack<int> LeftStack;
    stack<int> RightStack;
    // 初始化
    MyQueue() {

    }
    // 压入右栈
    void push(int x) {
        RightStack.push(x);
    }
    // 复用peek()
    // 弹出左栈顶元素
    int pop() {
        int result = this->peek();
        LeftStack.pop();
        return result;
    }
    // 若左栈为空,先将右栈元素全部转移到左栈
    // 获取左栈顶元素
    int peek() {
        if (LeftStack.empty()) {
            while (!RightStack.empty()) {
                LeftStack.push(RightStack.top());
                RightStack.pop();
            }
        }
        return LeftStack.top();
    }
    // 左栈、右栈均为空,队列才为空
    bool empty() {
        return LeftStack.empty() && RightStack.empty();
    }
};

LeetCode 225. 用队列实现栈

题目描述:仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

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

视频讲解https://www.bilibili.com/video/BV1Fd4y1K7sm/?spm_id_from=333.788&vd_source=f98f2942b3c4cafea8907a325fc56a48文章讲解https://programmercarl.com/0225.%E7%94%A8%E9%98%9F%E5%88%97%E5%AE%9E%E7%8E%B0%E6%A0%88.html

  • 思路:
    • 两个队列实现栈:que1,que2(弹出队尾元素时,用于对前面元素进行备份)
      • push():  直接插入到que1队尾
      • pop():    把前 size - 1 个元素依次挪入que2,弹出队首元素,其余元素归位
      • top():     直接获取que1队尾元素
      • empty():直接判断que1是否为空
    • 一个队列实现栈:que
      • push():  直接插入到que队尾
      • pop():    把前 size - 1 个元素依次挪到队尾,弹出队首元素
      • top():     直接获取que队尾元素
      • empty():直接判断que是否为空
  • 代码:
// 两个队列实现栈:
class MyStack {
public:
    queue<int> que1;
    queue<int> que2; // 辅助队列,用来备份
    /** Initialize your data structure here. */
    MyStack() {

    }

    /** Push element x onto stack. */
    void push(int x) {
        que1.push(x);
    }

    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int size = que1.size();
        size--;
        while (size--) { // 将que1 导入que2,但要留下最后一个元素
            que2.push(que1.front());
            que1.pop();
        }

        int result = que1.front(); // 留下的最后一个元素就是要返回的值
        que1.pop();
        que1 = que2;            // 再将que2赋值给que1
        while (!que2.empty()) { // 清空que2
            que2.pop();
        }
        return result;
    }

    /** Get the top element. */
    int top() {
        return que1.back();
    }

    /** Returns whether the stack is empty. */
    bool empty() {
        return que1.empty();
    }
};
// 一个队列实现栈:
class MyStack {
public:
    queue<int> que;
    /** Initialize your data structure here. */
    MyStack() {

    }
    /** Push element x onto stack. */
    void push(int x) {
        que.push(x);
    }
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int size = que.size();
        size--;
        while (size--) { // 将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部
            que.push(que.front());
            que.pop();
        }
        int result = que.front(); // 此时弹出的元素顺序就是栈的顺序了
        que.pop();
        return result;
    }

    /** Get the top element. */
    int top() {
        return que.back();
    }

    /** Returns whether the stack is empty. */
    bool empty() {
        return que.empty();
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值