目录
🎬 攻城狮7号:个人主页
🔥 个人专栏: 《C/C++算法》
⛺️ 君子慎独!
🌈 大家好,欢迎来访我的博客!
⛳️ 此篇文章主要讲解算法题目:化栈为队
📚 本期文章收录在《C/C++算法》,大家有兴趣可以自行查看!
⛺️ 欢迎各位 ✔️ 点赞 👍 收藏 ⭐留言 📝!
一、题目
实现一个MyQueue类,该类用两个栈来实现一个队列。
示例:
MyQueue queue = new MyQueue(); queue.push(1); queue.push(2); queue.peek(); // 返回 1 queue.pop(); // 返回 1 queue.empty(); // 返回 false
说明:
- 你只能使用标准的栈操作 -- 也就是只有
push to top
,peek/pop from top
,size
和is empty
操作是合法的。 - 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
- 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
二、解题思路
使用两个栈来实现队列的功能:一个栈作为输入栈,专门用于接收和存储通过 push
操作传入的数据;另一个栈作为输出栈,专门用于处理 pop
和 peek
操作。
当执行 pop
或 peek
操作时,如果输出栈为空,则需要将输入栈中的所有元素依次弹出并压入输出栈。这样一来,输出栈中的元素顺序就会与队列的顺序一致,即输出栈的栈顶元素对应队列的队首元素,栈底元素对应队列的队尾元素。
三、代码实现
#include <iostream>
#include <stack>
using namespace std;
class MyQueue {
private:
stack<int> inStack, outStack; // 定义两个栈:输入栈和输出栈
// 将输入栈中的元素转移到输出栈
void in2out() {
while (!inStack.empty()) {
outStack.push(inStack.top()); // 将输入栈的栈顶元素压入输出栈
inStack.pop(); // 弹出输入栈的栈顶元素
}
}
public:
MyQueue() {} // 构造函数
// 将元素 x 推入队列
void push(int x) {
inStack.push(x); // 直接将元素压入输入栈
}
// 弹出队列的队首元素
int pop() {
if (outStack.empty()) { // 如果输出栈为空,需要将输入栈的元素转移到输出栈
in2out();
}
int x = outStack.top(); // 获取输出栈的栈顶元素(即队首元素)
outStack.pop(); // 弹出输出栈的栈顶元素
return x; // 返回队首元素
}
// 获取队列的队首元素(不弹出)
int peek() {
if (outStack.empty()) { // 如果输出栈为空,需要将输入栈的元素转移到输出栈
in2out();
}
return outStack.top(); // 返回输出栈的栈顶元素(即队首元素)
}
// 判断队列是否为空
bool empty() {
return inStack.empty() && outStack.empty(); // 当输入栈和输出栈都为空时,队列为空
}
};
int main() {
MyQueue queue;
// 测试 push 操作
queue.push(1);
queue.push(2);
queue.push(3);
// 测试 peek 操作
cout << "队首元素: " << queue.peek() << endl; // 输出 1
// 测试 pop 操作
cout << "弹出元素: " << queue.pop() << endl; // 输出 1
cout << "弹出元素: " << queue.pop() << endl; // 输出 2
// 测试 empty 操作
cout << "队列是否为空: " << (queue.empty() ? "是" : "否") << endl; // 输出 否
// 再次测试 push 操作
queue.push(4);
// 测试 peek 操作
cout << "队首元素: " << queue.peek() << endl; // 输出 3
// 测试 pop 操作
cout << "弹出元素: " << queue.pop() << endl; // 输出 3
cout << "弹出元素: " << queue.pop() << endl; // 输出 4
// 测试 empty 操作
cout << "队列是否为空: " << (queue.empty() ? "是" : "否") << endl; // 输出 是
return 0;
}
时间复杂度分析:
-
push
操作和empty
操作的时间复杂度均为 O(1)。 -
pop
操作和peek
操作的均摊时间复杂度为 O(1)。这是因为每个元素最多只会被压入和弹出栈各两次,因此均摊下来每个操作的时间复杂度是常数级别。
空间复杂度分析:
-
空间复杂度为 O(n),其中 n 是操作的总数。在最坏情况下,如果进行了 n 次
push
操作,队列中可能会存储 n 个元素,因此需要 O(n) 的额外空间。
看到这里了还不给博主点一个:
⛳️ 点赞
☀️收藏
⭐️ 关注
!
💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
再次感谢大家的支持!
你们的点赞就是博主更新最大的动力!