JavaScript 数据结构(栈)

251 阅读1分钟

我们知道函数之间的相互调用: A 调用 B ,B 调用 C ,C 调用 D 。那么在函数相互调用执行的过程是这样的:

  1. 会首先将 A 压入栈,A 没有执行完,所以不会弹出栈;

  2. 在执行 A 的过程中调用了 B ,所以会将 B 压入栈,这个时候 A 在栈底部,B 在栈顶;

  3. 如果这个时候 B 执行完的话,就会弹出栈,然而 B 并没有执行完, 而是调用了 C;

  4. 所以 C 会压入栈,并且在栈顶,而 C 调用了 D,这个时候 D 会压入到栈顶;

  5. 所以当前栈的顺序是: 栈顶 -> 栈底,D -> C -> B -> A;

  6. D 执行完,弹出栈,C、B、A 依次弹出栈;

  7. 所以我们有函数调用栈的称呼,就是来自于它们内部的实现机制(通过栈来实现)。

栈的常规操作有哪些呢,下面一一列举:

  • push(element) : 添加一个元素到栈顶;

  • pop(): 移除栈顶元素,同时返回被移除的元素;

  • peek(): 返回栈顶元素,这个方法不会移除栈顶元素,仅仅会返回它;

  • isEmpty(): 是否为空;

  • size(): 返回栈的长度;

  • toString(): 将栈结构的内容以字符的形式放回。

下面用 JavaScript 来实现,具体代码如下:

class Stack{
  constructor() {
    this.stack = [];
  };

  push(element) {
    this.stack.push(element);
  }

  pop() {
    if (this.isEmpty()) {
      throw new Error('当前栈为空');
    }
    return this.stack.pop();
  }

  peek() {
    if (this.isEmpty()) {
      throw new Error('当前栈为空');
    }
    return this.stack[this.stack.length - 1];
  }

  isEmpty() {
    return this.stack.length === 0;
  }

  size() {
    return this.stack.length;
  }

  toString() {
    let str = '';
    for (let index = 0; index < this.stack.length; index++) {
      str  += `${this.stack[index]} `;
    }
    return str;
  }
}

const stack = new Stack();
console.log(stack.push(1));
console.log(stack.push(2));
console.log(stack.push(3));
console.log(stack.size());
console.log(stack.toString());
console.log(stack.peek());
console.log(stack.pop());
console.log(stack.isEmpty());