代码随想录Day 10 栈与队列
232用栈实现队列
栈的特点是后进先出,而队列的特点是先进先出。我们使用两个栈来模拟队列的先进先出特点。
假设我们先往队列中依次加入1、2、3这三个元素(即执行三次push操作),在执行peek操作,按照队列的特点peek操作得到的应该是1,但是在栈中我们通过top得到的是3,我们再用另一个栈将元素的顺序逆转一下,如图所示:
每次在push操作时,我们把要加入队列的元素先加入inStack中;当要执行peek操作或者pop操作时,如果outStack栈中不为空,直接对outStack栈进行top操作或者pop操作;如果outStack栈为空,先把inStack栈中的元素全部弹入到outStack栈中,再对outStack栈进行top操作或者pop操作 【这里为什么要先判断outStack是否为空? outStack栈中已有元素的顺序永远在inStack栈中元素的前面】
以下为可运行代码:
class MyQueue {
public:
MyQueue() {
}
void push(int x) {
inStack.push(x);
}
int pop() {
//如果出栈为空
if(outStack.empty()){
while(!inStack.empty()){
outStack.push(inStack.top());
inStack.pop();
}
}
int result = outStack.top();
outStack.pop();
return result;
}
int peek() {
// 这里直接复用已经实现的pop操作,但是pop函数里弹出了栈顶元素,这里要把弹出的元素再加入到outStack中
int result = this->pop();
outStack.push(result);
return result;
}
bool empty() {
if(inStack.empty() && outStack.empty()){
return true;
}
return false;
}
private:
stack<int> inStack, outStack;
};
225用队列实现栈
可以用一个队列也可以用两个队列来实现栈
方法一:使用一个队列
用一个队列时,只要循环操作就可以实现栈的功能,如图:
我们先依次弹入三个元素1、2、3,在执行top操作时,我们想得到的是元素3,这时只要把元素3前面已有的元素从队列中以此弹出并重新加入队列中即可。
代码如下:
class MyStack {
public:
MyStack() {
}
void push(int x) {
queue1.push(x);
}
int pop() {
int size = queue1.size();
for(int i = 0; i < size - 1; i++){
int temp = queue1.front();
queue1.pop();
queue1.push(temp);
}
int result = queue1.front();
queue1.pop();
return result;
}
int top() {
return queue1.back();
}
bool empty() {
if(queue1.empty()){
return true;
}
return false;
}
private:
queue<int> queue1;
};
方法二:使用两个队列
用两个队列也可以实现,和用两个栈实现队列方法的不同,这两个队列需要进行交换操作,代码如下:
class MyStack {
public:
MyStack() {
}
void push(int x) {
queue1.push(x);
}
int pop() {
int result = 0;
// 这一段代码其实就相当于把循环的元素另外写入到备用的queue2中,而不是像方法一那样重新再加入到queue1中
while(!queue1.empty()){
result = queue1.front();
queue1.pop();
if(!(queue1.empty())){
queue2.push(result);
}
}
//将queue2中的值重新赋给queue1,并将queue2清零
queue1 = queue2;
while(!queue2.empty()){
queue2.pop();
}
return result;
}
int top() {
return queue1.back();
}
bool empty() {
if(queue1.empty() && queue2.empty()){
return true;
}
return false;
}
private:
queue<int> queue1, queue2;
};
方法一和方法二的主要区别在于,图示中浅蓝色的1、2两个元素是直接加入到原本队列里,还是再用一个新的queue2来保存。