优先队列及其应用

优先队列(Priority Queue)是一种特殊的队列,它的出队顺序与普通队列不同,而是根据元素的优先级来决定的。具有高优先级的元素先出队列,相同优先级的元素按照其在队列中的顺序出队列。

优先队列的实现方式有很多种,其中一种比较常见的方式是使用堆(Heap)来实现。堆是一种完全二叉树,它的每个节点的值都比其子节点的值小(或大),这种特性使得堆可以用来实现优先队列。

下面我们以 JavaScript 为例,来看一个基于最小堆实现的优先队列的例子:

class PriorityQueue {
  constructor() {
    this.heap = [null];
  }

  // 元素入队列
  enqueue(value, priority = 0) {
    const node = { value, priority };
    this.heap.push(node);
    let current = this.heap.length - 1;
    let parent = Math.floor(current / 2);

    while (parent && this.heap[current].priority < this.heap[parent].priority) {
      [this.heap[current], this.heap[parent]] = [this.heap[parent], this.heap[current]];
      current = parent;
      parent = Math.floor(current / 2);
    }
  }

  // 获取队列中优先级最高的元素
  dequeue() {
    const min = this.heap[1];
    if (this.heap.length === 2) {
      this.heap = [null];
    } else {
      this.heap[1] = this.heap.pop();
      let current = 1;
      let [left, right] = [current * 2, current * 2 + 1];
      let child = this.heap[right] && this.heap[right].priority < this.heap[left].priority ? right : left;

      while (child && this.heap[current].priority > this.heap[child].priority) {
        [this.heap[current], this.heap[child]] = [this.heap[child], this.heap[current]];
        current = child;
        [left, right] = [current * 2, current * 2 + 1];
        child = this.heap[right] && this.heap[right].priority < this.heap[left].priority ? right : left;
      }
    }

    return min ? min.value : null;
  }

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

  // 获取队列长度
  size() {
    return this.heap.length - 1;
  }
}

// 创建一个新的优先队列
const priorityQueue = new PriorityQueue();

// 元素入队列
priorityQueue.enqueue('A', 1);
priorityQueue.enqueue('B', 2);
priorityQueue.enqueue('C', 3);

// 获取队列中优先级最高的元素
console.log(priorityQueue.dequeue()); // 'A'

// 元素入队列
priorityQueue.enqueue('D', 2);

// 获取队列中优先级最高的元素
console.log(priorityQueue.dequeue()); // 'B'

// 获取队列中优先级最高的元素
console.log(priorityQueue.dequeue()); // 'C'

// 获取队列中优先级最高的元素
console.log(priorityQueue.dequeue()); // 'D'

优先队列可以应用于很多场景,例如操作系统中的进程调度、网络数据包的传输等。举个例子,假设我们要实现一个任务调度器,其中包含多个不同优先级的任务,需要按照优先级高低来执行。我们可以使用优先队列来实现这个功能。

class Task {
  constructor(id, priority) {
    this.id = id;
    this.priority = priority;
  }
}

class TaskScheduler {
  constructor() {
    this.priorityQueue = new PriorityQueue();
    this.currentTask = null;
    this.timer = null;
  }

  addTask(task) {
    this.priorityQueue.enqueue(task, task.priority);
    this.scheduleTask();
  }

  scheduleTask() {
    if (this.currentTask) {
      return;
    }

    const nextTask = this.priorityQueue.dequeue();
    if (!nextTask) {
      return;
    }

    this.currentTask = nextTask.value;
    console.log(`Start executing task ${this.currentTask.id} with priority ${this.currentTask.priority}`);

    const executionTime = Math.random() * 5000;
    this.timer = setTimeout(() => {
      console.log(`Finish executing task ${this.currentTask.id}`);
      this.currentTask = null;
      this.scheduleTask();
    }, executionTime);
  }
}

const taskScheduler = new TaskScheduler();

taskScheduler.addTask(new Task(1, 3));
taskScheduler.addTask(new Task(2, 1));
taskScheduler.addTask(new Task(3, 2));

在上面的例子中,我们创建了一个任务调度器 TaskScheduler,其中包含一个优先队列 priorityQueue。当用户添加任务时,我们将任务入队列,并立即调用 scheduleTask 方法来开始执行任务。

scheduleTask 方法首先检查当前是否有正在执行的任务,如果有,则不进行任何操作。否则,它从优先队列中获取下一个要执行的任务,并将其作为当前任务。然后,它随机生成一个执行时间,模拟任务的执行过程。一旦任务完成,它将当前任务设置为 null,然后递归调用 scheduleTask 方法来继续执行下一个任务。

在上面的例子中,我们添加了三个任务,它们的优先级分别为 3、1 和 2。由于优先级为 1 的任务是最高优先级的任务,因此它将首先执行。一旦该任务完成,调度器将自动继续执行剩余的任务,直到队列为空为止。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值