用两个栈实现一个队列

用两个栈实现一个队列



一、基本思路

通过使用两个栈来模拟队列的先进先出(FIFO)特性:一个栈用于执行入队操作(将新元素压入栈1),另一个栈用于出队操作(从栈2中弹出元素)。在出队时,如果栈2为空,则将栈1中的所有元素逐一弹出并压入栈2,从而确保出队的顺序与入队顺序一致。

二、队列功能实现

1.入队操作

    // 入队操作
    void enqueue(const T &item) {
        // 将新元素压入栈1
        stack1.push(item);
    }

2.出队操作

    // 出队操作
    T dequeue() {
        if (isEmpty()) {
            throw std::runtime_error("Queue is empty!"); // 抛出异常
        }
        // 如果栈2为空,将栈1的所有元素移动到栈2
        if (stack2.empty()) {
            while (!stack1.empty()) {
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        // 返回栈2的顶部元素
        T item = stack2.top();
        stack2.pop();
        return item;
    }

3.查看队头元素

    // 查看队头元素
    T peek() const{
        if (isEmpty()) {
            throw std::runtime_error("Queue is empty!"); // 抛出异常
        }
        // 如果栈2为空,将栈1的所有元素移动到栈2
        if (stack2.empty()) {
            while (!stack1.empty()) {
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        return stack2.top(); // 返回栈2的顶部元素
    }

4.判断队列是否为空

    // 检查队列是否为空
    bool isEmpty() const {
        return stack1.empty() && stack2.empty();
    }

三、完整代码及测试

#include <iostream>
#include <stack>
#include <stdexcept>

template <typename T>
class QueueUsingStacks {
public:
    // 入队操作
    void enqueue(const T &item) {
        // 将新元素压入栈1
        stack1.push(item);
    }

    // 出队操作
    T dequeue() {
        if (isEmpty()) {
            throw std::runtime_error("Queue is empty!"); // 抛出异常
        }
        // 如果栈2为空,将栈1的所有元素移动到栈2
        if (stack2.empty()) {
            while (!stack1.empty()) {
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        // 返回栈2的顶部元素
        T item = stack2.top();
        stack2.pop();
        return item;
    }

    // 查看队头元素
    T peek() const{
        if (isEmpty()) {
            throw std::runtime_error("Queue is empty!"); // 抛出异常
        }
        // 如果栈2为空,将栈1的所有元素移动到栈2
        if (stack2.empty()) {
            while (!stack1.empty()) {
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        return stack2.top(); // 返回栈2的顶部元素
    }

    // 检查队列是否为空
    bool isEmpty() const {
        return stack1.empty() && stack2.empty();
    }

private:
    std::stack<T> mutable stack1; // 用于入队
    std::stack<T> mutable stack2; // 用于出队
};

int main() {
    QueueUsingStacks<int> queue;

    queue.enqueue(1); // 入队 1
    queue.enqueue(2); // 入队 2
    queue.enqueue(3); // 入队 3

    std::cout << "Front item: " << queue.peek() << std::endl; // 输出队头元素: 1

    queue.dequeue(); // 出队操作
    std::cout << "Front item after dequeue: " << queue.peek() << std::endl; // 输出队头元素: 2

    std::cout << "Is queue empty? " << (queue.isEmpty() ? "Yes" : "No") << std::endl; // 检查队列是否为空

    return 0; // 程序结束
}

代码说明

  1. 数据结构

    • 使用两个栈(stack1stack2)来实现队列的功能。
  2. 入队操作(enqueue)

    • 将元素直接压入 stack1
  3. 出队操作(dequeue)

    • 如果 stack2 为空,将 stack1 中的所有元素转移到 stack2,然后从 stack2 中弹出顶部元素作为出队元素。
    • 如果 stack2 不为空,直接弹出顶部元素。
  4. 查看队头元素(peek)

    • 和出队操作类似,首先检查 stack2 是否为空。如果为空,则将 stack1 的元素转移到 stack2,然后返回 stack2 的顶部元素。
  5. 检查队列是否为空

    • 当两个栈都为空时,队列被认为是空的。

性能分析

  • 使用两个栈的结构使得队列的实现简单且易于理解。虽然单次出队操作可能会有较高的时间复杂度(O(n)),但整体平均时间复杂度为 O(1)。
  • 空间复杂度是 O(n),其中 n 是队列中元素的数量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值