Skip to content

双端、优先级队列

实现双端队列

队列(Queue) 结构,它是一种受限的线性结构,并且限制非常的严格

双端队列在单向队列的基础上解除了一部分限制: 允许在队列的两端添加(入队)和删除(出队)元素

image-20231222160423576

继承自之前的队列结构

typescript
class ArrayDeque<T> extends ArrayQueue<T> {
  addFront(value: T) {
    this.data.unshift(value)
  }
  removeBack(): T | undefined {
    return this.data.pop()
  }
}

实现优先级队列

优先级队列(Priority Queue)是一种比普通队列更加高效的数据结构

  • 它每次出队的元素都是具有最高优先级的,可以理解为元素按照关键字进行排序
  • 优先级队列可以用数组、链表等数据结构来实现,但是堆是最常用的实现方式

优先级队列的应用

  • 一个现实的例子就是机场登机的顺序
    • 头等舱和商务舱乘客的优先级要高于经济舱乘客
    • 在有些国家,老年人和孕妇(或带小孩的妇女)登机时也享有高于其他乘客的优先级
  • 另一个现实中的例子是医院的 (急诊科) 候诊室
    • 医生会优先处理病情比较严重的患者
    • 当然,一般情况下是按照排号的顺序
  • 计算机中,我们也可以通过优先级队列来重新排序队列中任务的顺序
    • 比如每个线程处理的任务重要性不同,我们可以通过优先级的大小,来决定该线程在队列中被处理的次序

优先级队列的实现

  • 方式一:创建优先级的节点,保存在堆结构中
typescript
class PriorityNode<T> {
  priority: number
  value: T
  constructor(value: T, priority: number) {
    this.value = value
    this.priority = priority
  }
  valueOf() {
    return this.priority
  }
}
class PriorityQueue<T> {
  private heap: Heap<PriorityNode<T>> = new Heap()
  enqueue(value: T, priority: number) {
    const newNode = new PriorityNode(value, priority)
    this.heap.insert(newNode)
  }
  dequeue(): T | undefined {
    return this.heap.extract()?.value
  }
  peek(): T | undefined {
    return this.heap.peek()?.value
  }
  isEmpty() {
    return this.heap.isEmpty()
  }
  size() {
    return this.heap.size()
  }
}
  • 方式二:实现对应 valueOf 来控制对应节点优先级
typescript
class PriorityQueue2<T> {
  private heap: Heap<T> = new Heap()
  enqueue(value: T) {
    this.heap.insert(value)
  }
  dequeue(): T | undefined {
    return this.heap.extract()
  }
  peek(): T | undefined {
    return this.heap.peek()
  }
  isEmpty() {
    return this.heap.isEmpty()
  }
  size() {
    return this.heap.size()
  }
}

class Student {
  name: string
  score: number
  constructor(name: string, score: number) {
    this.name = name
    this.score = score
  }
  valueOf() {
    return this.score
  }
}
  • 方式三:使用最普通数组实现
typescript
class PriorityQueue3<T> {
  private list: { value: T; priority: number }[] = []
  enqueue(value: T, priority: number) {
    const newElement = { value, priority }
    if (this.isEmpty()) {
      this.list.push(newElement)
    } else {
      const size = this.size()
      for (let i = 0; i < size; i++) {
        if (priority > this.list[i].priority) {
          this.list.splice(i, 0, newElement)
          return
        }
      }
      this.list.push(newElement)
    }
  }
  dequeue() {
    return this.list.shift()
  }
  isEmpty() {
    return this.list.length ? false : true
  }
  size() {
    return this.list.length
  }
}

常备不懈,才能有备无患