javascript 之顺序队列(链表实现)

479 阅读1分钟

大家好,我是 17。

优先队列 不同,顺序队列没有特权,所有元素都是平等的,先进的先出。

代码

class Node {
  constructor(val) {
    this.val = val
    this.next = null
  }
}

class Queen {
  constructor() {
    this.length = 0
    const node = new Node()
    this.head = node
    this.tail = node
  }
  push(val) {
    const node = new Node(val)
    this.tail.next = node
    this.tail = node
    this.length++
  }
  pop() { 
    if (this.length <= 0) return undefined
    let val = this.head.next.val
    this.head = this.head.next
    this.length--
    return val
  }
  peekHead() { 
    if (this.length <= 0) return undefined
    else return this.head.next.val
  }
  peekTail(){
    if (this.length <= 0) return undefined
    else return this.tail.val
  }
}

方法命名参照数组的命名。push 是在队尾入队元素,pop 是在队首出队元素。length 是队列的长度。我在所有相关 线性表 的方法命名上都会参考数组命名,这样的好处是不用记。

入队和出队一个元素的时间复杂度都是 O(1),这是用链表的好处。如果用数组来实现的话,出队或入队将为 O(n)。还有一种实现方式是用 hash 表的方式,用连续的数字做 key,好处是可以查询到任意位置的元素,坏处是数字可能遇到上限。

所以如果只是从队尾入,从队首出的话,链表是最好的选择。

应用

顺序队列的一个应用是缓存数据。在生产者和消费者之间建立一个缓冲,以缓解生产和消费速度不一致的矛盾。

在实际应用中,可能生产者在某段时间的能力特别强,会导致队列过大,所以还得加个限制。

class Queen {
  constructor(max = Infinity) {
    this.max = max
    this.length = 0
    const node = new Node()
    this.head = node
    this.tail = node
  }
  push(val) {
    const node = new Node(val)
    this.tail.next = node
    this.tail = node
    this.length++
    if (this.length > this.max) {
      this.pop()
    }
  }
  pop() {
    if (this.length <= 0) return undefined
    let val = this.head.next.val
    this.head = this.head.next
    this.length--
    return val
  }
  peek() {
    if (this.length <= 0) return undefined
    else return this.head.next.val
  }
}

加上 max 参数,最大长度限度,相当于是一个保险。如果超过长度,新元素入队,老元素出队,操持最大长度。