【若川视野 x 源码共读】第32期 | yocto-queue 队列 链表

79 阅读2分钟

本文参加了由公众号@若川视野 发起的每周源码共读活动,点击了解详情一起参与。

本篇是源码共读第32期 | yocto-queue 队列 链表,点击了解本期详情

项目源码

yocto-queue

应用场景

截屏2023-08-02 17.37.18.png 当我们在大型数组上执行大量的push和shift操作时应该使用该包来代替数组,数组的线性时间复杂度为O(n)而Queue具有恒定的时间复杂度O(1)

队列是有序的元素列表,其中元素插入到队列的末尾并从队列的前面删除。队列基于先进先出 (FIFO) 原则工作。

class Node

class Node {
  // 当前节点值 
  value;
  // 下一个节点
  next;

  constructor(value: any) {
    this.value = value;
  }

}

class Queue

class Queue {
  // 定义私有字段
  // 从作用域之外引用 `#` 名称、内部在未声明的情况下引用私有字段、
  // 或尝试使用 `delete` 移除声明的字段都会抛出语法错误。
  #head;
  #tail;
  #size;

  constructor() {
    // 重置私有字段值
    this.clear();
  }

  // 入队
  enqueue(value) {
    // 创建一个节点
    const node = new Node(value);

    // 如果已存在头结点
    if(this.#head) {
      // 将尾节点的下一个赋值为node
      // 在第一次入队时,head和tail指向同一个对象Node
      // #head: { value: 1, next: { value: 2, next: undefined }}
      // #tail: { value: 1, next: { value: 2, next: undefined }}
      this.#tail.next = node;
      
      // 更新尾节点
      // #head: { value: 1, next: { value: 2, next: undefined }}
      // #tail: { value: 2, next: undefined }
      this.#tail = node;
    } else {
      // 反之将头结点和尾节点赋值为node
      this.#head = node;
      this.#tail = node;
    }

    // 队列长队加一
    this.#size++;
  }

 // 出队
  dequeue() {
    const current = this.#head;

    // 如果不存在head直接return
    if(!current) {
      return;
    }

    // 基于先进先出(FIFO)原则,从头节点开始
    // 将当前head节点的next节点赋值给当前head
    this.#head = this.#head.next;
    
    // 队列长度减一
    this.#size--;

    // 返回已被删除的值
    return current;
  }

  // 清空队列
  clear() {
    this.#head = undefined;
    this.#tail = undefined;
    this.#size = 0;
  }

  // 为queue定义一个迭代器,使对象Queue可被循环遍历
  *[Symbol.iterator]() {
    let current = this.#head;

    while(current) {
      // 输出当前值
      yield current.value;

      // 指向下一个节点
      current = current.next;
    }
  }
}

总结

· 队列在处理大型数组时为更优选择

· [Symbol.iterator] (){} 可为对象定义一个迭代器