返回

入栈出栈,原来这就是 JavaScript 栈的原理!

前端

栈,这个听起来有些陌生的名词,其实在我们的日常生活中无处不在。比如,当你在浏览网页时,你点击的每个链接都会被压入浏览器的历史记录栈中。当你点击后退按钮时,历史记录栈中的链接就会被弹出,你就会回到上一个页面。再比如,当你使用文本编辑器时,你输入的每个字符都会被压入编辑器的撤销栈中。当你点击撤销按钮时,撤销栈中的字符就会被弹出,你的文本就会恢复到上一个状态。

栈是一种先进后出的数据结构,这意味着先进入栈中的元素最后会被弹出。栈的这种特性非常适合管理函数调用、浏览器历史记录和撤销操作。在JavaScript中,栈可以使用数组或链表来实现。

栈的实现

使用数组实现栈非常简单,我们只需要维护一个数组,并在数组的头部和尾部添加和删除元素即可。

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

  push(item) {
    this.items.push(item);
  }

  pop() {
    return this.items.pop();
  }

  peek() {
    return this.items[this.items.length - 1];
  }

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

使用链表实现栈稍微复杂一些,我们需要维护一个头结点和一个尾结点,并在链表的头部和尾部添加和删除元素。

class Stack {
  constructor() {
    this.head = null;
    this.tail = null;
  }

  push(item) {
    const newNode = {
      value: item,
      next: null
    };

    if (this.head === null) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.next = newNode;
      this.tail = newNode;
    }
  }

  pop() {
    if (this.head === null) {
      return null;
    }

    const value = this.head.value;
    this.head = this.head.next;

    if (this.head === null) {
      this.tail = null;
    }

    return value;
  }

  peek() {
    if (this.head === null) {
      return null;
    }

    return this.head.value;
  }

  isEmpty() {
    return this.head === null;
  }
}

栈的应用

栈在计算机科学中有很多应用,比如:

  • 管理函数调用
  • 浏览器历史记录
  • 撤销操作
  • 表达式求值
  • 编译器
  • 操作系统

栈的优缺点

栈是一种非常简单易用的数据结构,它具有以下优点:

  • 简单易懂
  • 实现简单
  • 效率高

栈也有一些缺点,比如:

  • 只支持先进后出操作
  • 不能随机访问元素

栈的复杂度

栈的复杂度如下:

操作 时间复杂度 空间复杂度
push O(1) O(1)
pop O(1) O(1)
peek O(1) O(1)
isEmpty O(1) O(1)

栈的注意事项

在使用栈时,需要注意以下几点:

  • 栈是一种先进后出的数据结构,这意味着先进入栈中的元素最后会被弹出。
  • 栈只能在一端进行插入和删除操作。
  • 栈的大小是有限的,如果栈已满,则无法再向栈中添加元素。
  • 栈是线程安全的,这意味着它可以被多个线程同时访问。