什么是优先队列

优先队列也是一种队列,只不过不同的是,优先队列的出队顺序是按照优先级来的。
优先队列(ADT, Abstract Data Type)是一种数据结构, 支持插入和删除最小/大值操作(返回并删除最小/大元素)。
image.png

对于最小健值元素拥有最高的优先队列, 称之为升序优先队列
同理, 对于最大健值元素拥有最高的优先队列,称之为降序优先队列

解决什么问题

需要找到元素集合中的最小或最大元素。

优先队列ADT操作

主要操作

  • 插入
  • 删除
  • 获取

辅助操作

  • 第k小/大
  • 大小
  • 堆排列

优先队列的应用

  • 数据压缩:赫夫曼编码算法
  • 最短路径算法:Dijkstra算法
  • 最小生成树算法:Prim算法
  • 事件驱动仿真:顾客排队算法
  • 选择问题:查找第k个最小元素 拜托,面试别再问我TopK了!!!

练习题集合

堆(大根堆/小根堆)

大根堆:父节点的值比每一个子节点的值都要大。
同理, 小根堆:父节点的值比每一个子节点的值都要小。

  1. class MinHeap {
  2. constructor(data = []) {
  3. this.data = data;
  4. this.comparator = (a, b) => a - b;
  5. this.heapify();
  6. }
  7. // 堆化
  8. heapify() {
  9. if (this.size() < 2) return;
  10. for (let i = 1; i < this.size(); i++) {
  11. this.bubbleUp(i);
  12. }
  13. }
  14. peek() {
  15. if (this.size() === 0) return null;
  16. return this.data[0];
  17. }
  18. offer(value) {
  19. this.data.push(value);
  20. this.bubbleUp(this.size() - 1);
  21. }
  22. poll() {
  23. if (this.size() === 0) {
  24. return null;
  25. }
  26. const result = this.data[0];
  27. const last = this.data.pop();
  28. if (this.size() !== 0) {
  29. this.data[0] = last;
  30. this.bubbleDown(0);
  31. }
  32. return result;
  33. }
  34. bubbleUp(index) {
  35. while (index > 0) {
  36. const parentIndex = (index - 1) >> 1;
  37. if (this.comparator(this.data[index], this.data[parentIndex]) < 0) {
  38. this.swap(index, parentIndex);
  39. index = parentIndex;
  40. } else {
  41. break;
  42. }
  43. }
  44. }
  45. bubbleDown(index) {
  46. const lastIndex = this.size() - 1;
  47. while (true) {
  48. const leftIndex = index * 2 + 1;
  49. const rightIndex = index * 2 + 2;
  50. let findIndex = index;
  51. if (
  52. leftIndex <= lastIndex &&
  53. this.comparator(this.data[leftIndex], this.data[findIndex]) < 0
  54. ) {
  55. findIndex = leftIndex;
  56. }
  57. if (
  58. rightIndex <= lastIndex &&
  59. this.comparator(this.data[rightIndex], this.data[findIndex]) < 0
  60. ) {
  61. findIndex = rightIndex;
  62. }
  63. if (index !== findIndex) {
  64. this.swap(index, findIndex);
  65. index = findIndex;
  66. } else {
  67. break;
  68. }
  69. }
  70. }
  71. swap(index1, index2) {
  72. [this.data[index1], this.data[index2]] = [this.data[index2], this.data[index1]];
  73. }
  74. size() {
  75. return this.data.length;
  76. }
  77. }

第k个最小元素

var KthLargest = function(k, nums) {
    this.k = k;
    this.heap = new MinHeap();
    for (let num of nums) {
        this.add(num);
    }
};

KthLargest.prototype.add = function(val) {
    this.heap.offer(val);
    if (this.heap.size() > this.k) {
        this.heap.poll();
    }
    return this.heap.peek();
};