优先队列中的每个元素都有对应的优先级,优先级最高的元素最先获得服务,优先级相同的元素按照其在优先队列中的顺序得到服务。

操作

  • 插入带有优先级的元素
  • 取出具有最高优先级的元素
  • 查看最高优先级的元素

其它可选的操作:

  • 检查优先级高的一批元素
  • 清空优先队列
  • 批插入一批元素
  • 合并多个优先队列
  • 调整一个元素的优先级

实现

初级实现

使用有序数组,插入时排序,插入效率为🎏优先队列的JavaScript实现 - 图1,取出效率为🎏优先队列的JavaScript实现 - 图2

  1. import Queue from "./Queue";
  2. class QueueElement {
  3. constructor(element, priority) {
  4. this.element = element;
  5. this.priority = priority;
  6. }
  7. }
  8. export class PriorityQueue extends Queue {
  9. constructor() {
  10. super();
  11. }
  12. // euqueue 入队
  13. // 重写enqueue,需要加入priority
  14. enqueue(element, priority) {
  15. // 根据传入元素,创建QueueElement对象
  16. const queueElement = new QueueElement(element,priority);
  17. // 判断队列是否为空
  18. if (this.isEmpty()) {
  19. // 如果是空队列,就不管优先级了,直接添加
  20. this.items.push(queueElement);
  21. } else {
  22. // 定义变量记录是否添加新元素
  23. let added = false;
  24. for(let i = 0; i < this.items.length; i++) {
  25. // 让新加入的元素进行优先级比较,priority越小,优先级越大
  26. if (queueElement.priority < this.items[i].priority) {
  27. this.items.splice(i,0, queueElement);
  28. added = true;
  29. break;
  30. }
  31. }
  32. // 如果队列中元素都被遍历了,说明优先级最小,插到队列末尾
  33. if (!added) {
  34. this.items.push(queueElement);
  35. }
  36. }
  37. }
  38. // dequeue 出队,从队列中删除前端元素,返回被删除的元素,因为已经插入时就排好序了,所以此时就无需排序
  39. dequeue() {
  40. return super.dequeue();
  41. }
  42. // peek 查看队列前端元素
  43. peek() {
  44. return super.peek();
  45. }
  46. // isEmpty 查看队列是否为空
  47. isEmpty() {
  48. return super.isEmpty();
  49. }
  50. // size 查看队列中元素个数
  51. size() {
  52. return super.size();
  53. }
  54. // clear 清除队列中的元素
  55. clear() {
  56. return super.clear();
  57. }
  58. // toString 将队列中元素以字符串形式输出
  59. toString() {
  60. let result = '';
  61. for (let item of this.items) {
  62. result += item.element + '-' + item.priority;
  63. }
  64. return result;
  65. }
  66. }

典型实现

出于性能考虑,优先队列用)来实现,具有O(log n)时间复杂度的插入元素性能,O(n)的初始化构造的时间复杂度。如果使用自平衡二叉查找树,插入与删除的时间复杂度为O(log n),构造二叉树的时间复杂度为O(n log n)。
从计算复杂度的角度,优先级队列等价于排序算法
有一些特殊的)为优先队列的实现提供了额外的性能:二叉堆的插入与提取操作的时间复杂度为O(log n),并可以常量时间复杂度的peek操作。二项堆提供了几种额外操作。斐波那契堆的插入、提取、修改元素优先级等操作具有分摊常量时间复杂度,[1],但删除操作的时间复杂度为O(log n)。Brodal queue具有最糟糕情况下的常量复杂度但算法相当复杂因而不具有实用性。
对于整型、浮点型等具有有限值域的元素的数据类型,优先队列有更快的实现。