大家好,我是怒码少年小码。
栈和队列,大家都懂了,那么如何让这两个互选转化?
用栈实现队列
队列的特点是先进先出,但是栈的特点是后进先出,这个可咋整?
这也是LeetCode 232:使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push,pop,peek,empty)
我们先用输入栈保存入队的元素,再把它们弹出,然后进入输出栈,这样我们从输出栈顶取出的元素就是最先进入输入栈的元素了。
人话:用两个栈捣鼓了两遍,把顺序颠倒了一下。
输入输入栈的元素:1、2、3,输入栈弹出的元素3、2、1;进入输出栈的元素:3、2、1,输出栈弹出的元素:1、2、3
//定义
struct Queue {
stack<int> inStack;
stack<int> outStack;
};
//入队
void push01(Queue* queue, int x) {
queue->inStack.push(x);
}
//出队
int pop01(Queue* queue) {
if (queue->outStack.empty()) {
while (!queue->inStack.empty() ) {
int cur = queue->inStack.top();
queue->inStack.pop();
queue->outStack.push(cur);
}
}
if (queue->outStack.empty()) {
cout << "队列空了" << endl;
return -1;
}
int val = queue->outStack.top();
queue->outStack.pop();
return val;
}
//获取队首元素
int peek(Queue* queue) {
if (queue->outStack.empty()) {
while (!queue->inStack.empty()) {
int cur = queue->inStack.top();
queue->inStack.pop();
queue->outStack.push(cur);
}
}
if (queue->outStack.empty()) {
cout << "队列空了" << endl;
return -1;
}
return queue->outStack.top();
}
//判空
bool empty01(Queue* queue) {
if (queue->inStack.empty() && queue->outStack.empty()) {
cout << "队列空了" << endl;
return true;
}
else {
cout << "还有还有" << endl;
return false;
}
}
这里为了方便我使用了C++的标准库stack
,记得引入#include<stack>
。
值得注意的是:pop()
的作用删除栈顶元素,它没有返回值,代码中的 int val = queue->outStack.top(); queue->outStack.pop();
不可以写成int val = queue->outStack.pop();
测试一下:
int main() {
Queue queue;
push01(&queue, 1);
push01(&queue, 2);
push01(&queue, 3);
pop01(&queue);
int a=peek(&queue);
cout << a << endl;
cout << empty01(&queue) << endl;
}
用队列实现栈
LeetCode225:使用两个队列实现一个后入先出的栈,并支持普通栈的全部四种操作(push,top,pop,empty)。
思路:queue1用于存储栈内的元素,queue2作为入栈操作的辅助队列,入栈操作时,首先将元素入队到queue2,然后将queue1的全部元素依次出队并入队到queue2,此时queue2的前端的元素即为新入栈的元素,再将queue1和queue2互换,则queue1的元素即为栈内的元素,queue1的前端和后端分别对应栈顶和栈底。
class MyStack {
private:
queue<int> queue1; // 主队列
queue<int> queue2; // 辅助队列
public:
MyStack() {}
void push(int x) {
// 将新元素入队到辅助队列
queue2.push(x);
// 将主队列的元素依次入队到辅助队列
while (!queue1.empty()) {
queue2.push(queue1.front());
queue1.pop();
}
// 交换主队列和辅助队列
swap(queue1, queue2);
}
int pop() {
int topElement = queue1.front();
queue1.pop();
return topElement;
}
int top() {
return queue1.front();
}
bool empty() {
return queue1.empty();
}
};
例如分别入栈1、2、3;1进入queue2,此时queue1为空,直接交换queue1和queue2,此时:
- queue1:1
- queue2:
然后2进入queue2,此时queue1不为空,把queue1中的元素出队并入队到queue2,此时:
- queue1:
- queue2:2,1
此时queue2的顺序已经排好,然后交换queue1和queue2:
- queue1:2,1
- queue2:
然后3进入queue2,此时queue1不为空,把queue1中的元素出队并入队到queue2,此时:
- queue1:
- queue2:3,2,1
此时queue2的顺序已经排好,然后交换queue1和queue2:
- queue1:3,2,1
- queue2:
这样就排好了!queue1出队的效果和出栈一样,实现了后进先出
出栈操作只需要移除queue1的前端元素并返回即可,获得栈顶元素操作只需要获得queue1的前端元素并返回即可(不移除元素)。由于queue1用于存储站内的元素,判断栈是否为空时,只需要判断queue1是否为空即可。
写一段代码测试一下:
MyStack stack;
stack.push(1);
stack.push(2);
stack.push(3);
cout << "Top element: " << stack.top() << endl;
cout << "Pop element: " << stack.pop() << endl;
cout << "Top element: " << stack.top() << endl;
return 0;
END
这篇理解起来不难,但是如果你不用C++的标准库估计要写上一会了😊~