前言
我们知道栈的原理是先进后出,队列的原理是先进先出。
在JS中主要通过数组来实现队列和数组的功能。
首先我们来看栈
入栈可以用 arr.push()
出栈可以用 arr.pop()
然后是队列
入队可以用 arr.push()
出队可以用 arr.shift()
接下来通过两道经典的题目来进一步熟悉栈和队列
leetcode 232 用栈实现队列
题目链接
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
)
主要思路:
我们需要用两个栈,一个负责入队stackIn,一个负责出队stackOut。
入队push()的时候,直接压入stackIn中即可,重点在于出队的操作。在pop()时,如果stackOut为空,则将stackIn全部数据都导入stackOut,这样一来,stackOut栈顶元素就是第一个入栈的元素,也就是我们需要出队的元素。如果stackOut不为空,则直接出栈弹出数据即可。
判断队列是否为空,只需要stackIn和stackOut均为空即说明队列为空。
具体代码实现:
var MyQueue = function() {
this.stackIn = [];
this.stackOut = [];
};
/**
* @param {number} x
* @return {void}
*/
MyQueue.prototype.push = function(x) {
this.stackIn.push(x)
};
/**
* @return {number}
*/
MyQueue.prototype.pop = function() {
if(this.stackOut.length){
return this.stackOut.pop();
}
while(this.stackIn.length !== 0){
this.stackOut.push(this.stackIn.pop());
}
return this.stackOut.pop();
};
/**
* @return {number}
*/
MyQueue.prototype.peek = function() {
const x = this.pop();
this.stackOut.push(x);
return x;
};
/**
* @return {boolean}
*/
MyQueue.prototype.empty = function() {
return !this.stackIn.length && !this.stackOut.length;
};
/**
* Your MyQueue object will be instantiated and called as such:
* var obj = new MyQueue()
* obj.push(x)
* var param_2 = obj.pop()
* var param_3 = obj.peek()
* var param_4 = obj.empty()
*/
leetcode 225 用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push
、top
、pop
和 empty
)。
主要思路:
由于队列是先进先出,这个题目肯定不能和leetcode232一样。但我们同样是使用两个队列queue1和queue2。queue2主要的作用其实是备份,存储最后一个“入栈”元素以外的所有元素。这样可以保证queue1中队首元素始终是栈顶元素。
入栈我们还是直接压入queue1即可。重点在于出栈操作,我们刚才也介绍过要做到栈顶元素就是queue1队首元素。因此 当queue1中元素个数大于1时,就将其pop()出去存储在queue2中。(这样可以保证que1中只有栈顶元素)。这里需要注意的一点是,如果已经出栈一次,queue1就会为空,此时我们需要将queue1与queue2进行交换。(如果交换后queue1元素个数大于1,会重复之前的操作)。
具体代码实现:
var MyStack = function() {
this.queue1 = [];
this.queue2 = [];
};
/**
* @param {number} x
* @return {void}
*/
MyStack.prototype.push = function(x) {
this.queue1.push(x);
};
/**
* @return {number}
*/
MyStack.prototype.pop = function() {
if(!this.queue1.length){
[this.queue1, this.queue2] = [this.queue2, this.queue1];
}
while(this.queue1.length > 1){
this.queue2.push(this.queue1.shift());
}
return this.queue1.shift();
};
/**
* @return {number}
*/
MyStack.prototype.top = function() {
const x = this.pop();
this.queue1.push(x);
return x;
};
/**
* @return {boolean}
*/
MyStack.prototype.empty = function() {
return !this.queue1.length && !this.queue2.length;
};
/**
* Your MyStack object will be instantiated and called as such:
* var obj = new MyStack()
* obj.push(x)
* var param_2 = obj.pop()
* var param_3 = obj.top()
* var param_4 = obj.empty()
*/
栈和队列还有许多经典的题目,如:leetcode 20 有效的括号、leetcode 150 逆波兰表达式求值,感兴趣的朋友也可以自己尝试做一下, 巩固自己对栈和队列的理解。