使用栈实现队列功能

思路

队列讲究的时先进先出(FIFO)原则,我们的栈是先进后出,最先入栈的会在栈的底部,这与我们的原则相悖,那么如何解决这个问题呢?可以采取双栈的设计,一个栈instack负责入队操作,一个栈outstack负责出队操作,比如入队一个元素,会进入到instack的底部,如果我们再希望他出队的话,只需要将他取出来压入到outstack里面,这个过程中他上面的元素在outstack中是依次往下的,要出队的元素在outstack最上面,outstack的出栈顺序和出队顺序一样的。这样就达到了入队出队的效果。

实现

#include <stack>
#include <iostream>

template <typename T>
class MyQueue {
private:
    std::stack<T> inStack;   // 输入栈,负责入队操作
    std::stack<T> outStack;  // 输出栈,负责出队操作

    // 将输入栈数据转移到输出栈(核心操作)
    void transfer() {
        while (!inStack.empty()) {
            outStack.push(inStack.top());
            inStack.pop();
        }
    }

public:
    MyQueue() {}

    // 入队操作:时间复杂度 O(1)
    void push(T x) {
        inStack.push(x);
    }

    // 出队操作:摊还时间复杂度 O(1)
    T pop() {
        if (outStack.empty()) {
            transfer();
        }
        T val = outStack.top();
        outStack.pop();
        return val;
    }

    // 查看队首元素:摊还时间复杂度 O(1)
    T peek() {
        if (outStack.empty()) {
            transfer();
        }
        return outStack.top();
    }

    // 判断队列是否为空:时间复杂度 O(1)
    bool empty() {
        return inStack.empty() && outStack.empty();
    }

    // 获取队列元素数量:时间复杂度 O(1)
    size_t size() {
        return inStack.size() + outStack.size();
    }
};

/* 
 * 复杂度分析:
 * - push: O(1) 直接压栈
 * - pop/peek: 
 *   - 最佳情况 O(1)(当 outStack 不为空时)
 *   - 最差情况 O(n)(需要转移整个 inStack)
 *   - 摊还分析:每个元素最多经历两次栈操作(压入 inStack,弹出 inStack,压出 outStack)
 *   因此 m 次操作的摊还时间复杂度为 O(m) → 单次操作摊还 O(1)
 */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值