栈和队列
栈
栈(Stack),先进后出(FILO:First In Last Out)。一种特殊的线性表。仅能在栈顶进行操作。
像羽毛球桶(一端开的那种),子弹夹之类的设计都是栈结构,先进的最后才能出来。
常用方法
- enqueue 尾部添加
- dequeue 头部删除
- head 返回头部元素
- size 队列大小
- clear 清空
- isEmpty 是否为空
- tail 返回队列的尾结点
应用
约瑟夫环: 每隔2个数删1个,最后剩下的那个元素是什么
斐波那契序列: f(n) = f(n-1) + f(n-2) 去f(n)值
打印杨辉三角 1 1 1 2 1
队列
队列(Queue),先进先出(FIFO:First In First Out)。
像我们日常中买票排队就是一个典型的队列形式,先来的先买票。
用栈实现队列
描述
使用两个栈实现先入先出队列。队列需要支持push、pop、peek、empty操作。实现类MyQueue:
- push(x):将元素x推到队列的尾部,无返回值
- pop():返回队列头部第一个元素并移除
- peek():返回队列开头的元素
- empty():队列是否为空,为空返回true,不为空返回false
分析
注意题目描述,是需要定义两个栈来完成,不能直接定义一个数组类型的栈,然后使用数组的方法来完成,这样不需要两个了,一个数组就能实现队列的这四个方法。
栈在上面理论部分也说了,是一种特殊的线性表,仅能操作栈顶。
- push方法是给尾部添加一个元素,可以直接用栈(数组)的push方法
- empty判断,可以用数组的length属性
- 栈只能操作顶部元素,不能直接获取到第一个元素,需要用到两个栈相互倒腾才行
- pop和peek方法类似,都需要返回队列第一个元素,不同的是pop不仅返回对首元素,还要进行删除,改变队列的长度
程序实现
var MyQueue = function() {
this.s1 = []
this.s2 = []
// pop和peek的公共方法,两者的区别仅在于是否删除队列的第一个元素
this.isRemoveFirst = function (remove = true) {
let fir
this.s2 = []
while (this.s1.length) {
if (this.s1.length === 1) {
fir = this.s1.pop()
if (!remove) {
this.s2.push(fir)
}
} else {
this.s2.push(this.s1.pop())
}
}
while (this.s2.length) {
this.s1.push(this.s2.pop())
}
return fir
}
};
/**
* @param {number} x
* @return {void}
* 将元素x推到队列的末尾
*/
MyQueue.prototype.push = function(x) {
this.s1.push(x)
};
/**
* @return {number}
* 移出队列第一个元素并返回
*/
MyQueue.prototype.pop = function() {
return this.isRemoveFirst()
};
/**
* @return {number}
* 返回队列开头的元素
*/
MyQueue.prototype.peek = function() {
return this.isRemoveFirst(false)
};
/**
* @return {boolean}
* 判断是否为空
*/
MyQueue.prototype.empty = function() {
return !this.s1.length
};