栈和队列

72 阅读2分钟

栈和队列

栈(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)。

像我们日常中买票排队就是一个典型的队列形式,先来的先买票。

用栈实现队列

描述

使用两个栈实现先入先出队列。队列需要支持pushpoppeekempty操作。实现类MyQueue:

  1. push(x):将元素x推到队列的尾部,无返回值
  2. pop():返回队列头部第一个元素并移除
  3. peek():返回队列开头的元素
  4. empty():队列是否为空,为空返回true,不为空返回false

分析

注意题目描述,是需要定义两个栈来完成,不能直接定义一个数组类型的栈,然后使用数组的方法来完成,这样不需要两个了,一个数组就能实现队列的这四个方法。

栈在上面理论部分也说了,是一种特殊的线性表,仅能操作栈顶。

  1. push方法是给尾部添加一个元素,可以直接用栈(数组)的push方法
  2. empty判断,可以用数组的length属性
  3. 栈只能操作顶部元素,不能直接获取到第一个元素,需要用到两个栈相互倒腾才行
  4. 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
};