📜  Javascript中优先队列的实现(1)

📅  最后修改于: 2023-12-03 15:01:47.432000             🧑  作者: Mango

Javascript中优先队列的实现

优先队列是一种特殊的队列数据结构,每个元素都被赋予一个优先级,在队列中高优先级的元素被优先处理。

在Javascript中,我们可以通过数组和堆来实现优先队列。这里将介绍两种常见的实现方式。

1. 使用数组实现优先队列
class PriorityQueue {
  constructor() {
    this.queue = [];
  }

  // 添加元素到队列
  enqueue(element, priority) {
    const queueElement = { element, priority };
    let added = false;
    for (let i = 0; i < this.queue.length; i++) {
      if (queueElement.priority < this.queue[i].priority) {
        this.queue.splice(i, 0, queueElement);
        added = true;
        break;
      }
    }
    if (!added) {
      this.queue.push(queueElement);
    }
  }

  // 移除并返回队列中第一个元素
  dequeue() {
    if (!this.isEmpty()) {
      return this.queue.shift().element;
    }
    return null;
  }

  // 返回队列中第一个元素
  front() {
    if (!this.isEmpty()) {
      return this.queue[0].element;
    }
    return null;
  }

  // 判断队列是否为空
  isEmpty() {
    return this.queue.length === 0;
  }

  // 返回队列的长度
  size() {
    return this.queue.length;
  }

  // 清空队列
  clear() {
    this.queue = [];
  }
}

// 使用例子
const priorityQueue = new PriorityQueue();
priorityQueue.enqueue('Task 1', 3);
priorityQueue.enqueue('Task 2', 1);
priorityQueue.enqueue('Task 3', 2);

console.log(priorityQueue.front()); // 输出 "Task 2"
console.log(priorityQueue.dequeue()); // 输出 "Task 2"
console.log(priorityQueue.size()); // 输出 2
2. 使用堆实现优先队列
class Heap {
  constructor() {
    this.heap = [];
  }

  // 获取父节点的索引
  getParentIndex(index) {
    return Math.floor((index - 1) / 2);
  }

  // 获取左子节点的索引
  getLeftChildIndex(index) {
    return index * 2 + 1;
  }

  // 获取右子节点的索引
  getRightChildIndex(index) {
    return index * 2 + 2;
  }

  // 上移操作
  siftUp(index) {
    let parentIndex = this.getParentIndex(index);
    while (index > 0 && this.heap[parentIndex] > this.heap[index]) {
      [this.heap[parentIndex], this.heap[index]] = [this.heap[index], this.heap[parentIndex]];
      index = parentIndex;
      parentIndex = this.getParentIndex(index);
    }
  }

  // 下移操作
  siftDown(index) {
    const leftChildIndex = this.getLeftChildIndex(index);
    const rightChildIndex = this.getRightChildIndex(index);
    let swapIndex = index;
    if (leftChildIndex < this.heap.length && this.heap[leftChildIndex] < this.heap[swapIndex]) {
      swapIndex = leftChildIndex;
    }
    if (rightChildIndex < this.heap.length && this.heap[rightChildIndex] < this.heap[swapIndex]) {
      swapIndex = rightChildIndex;
    }
    if (index !== swapIndex) {
      [this.heap[index], this.heap[swapIndex]] = [this.heap[swapIndex], this.heap[index]];
      this.siftDown(swapIndex);
    }
  }

  // 入队列
  enqueue(value) {
    this.heap.push(value);
    this.siftUp(this.heap.length - 1);
  }

  // 出队列
  dequeue() {
    if (!this.isEmpty()) {
      const front = this.heap[0];
      const last = this.heap.pop();
      if (!this.isEmpty()) {
        this.heap[0] = last;
        this.siftDown(0);
      }
      return front;
    }
    return null;
  }

  // 返回队列中第一个元素
  front() {
    if (!this.isEmpty()) {
      return this.heap[0];
    }
    return null;
  }

  // 判断队列是否为空
  isEmpty() {
    return this.heap.length === 0;
  }

  // 返回队列的长度
  size() {
    return this.heap.length;
  }

  // 清空队列
  clear() {
    this.heap = [];
  }
}

// 使用例子
const priorityQueue = new Heap();
priorityQueue.enqueue(3);
priorityQueue.enqueue(1);
priorityQueue.enqueue(2);

console.log(priorityQueue.front()); // 输出 1
console.log(priorityQueue.dequeue()); // 输出 1
console.log(priorityQueue.size()); // 输出 2

以上是使用数组和堆来实现Javascript中优先队列的两种常见方式。根据实际需求和性能要求,选择合适的实现方式来管理有优先级的元素队列。