优先队列不再遵循先入先出的原则,而是分为两种情况。

  • 最大优先队列,无论入队顺序如何,都是当前最大的元素优先出队;
  • 最小优先队列,无论入队顺序如何,都是当前最小的元素优先出队;

可以使用最大堆和最小堆来分别实现最大优先队列和最小优先队列。

代码实现

  1. public class PriorityQueue {
  2. private int[] array;
  3. private int size;
  4. public PriorityQueue() {
  5. // 队列初始长度为 32
  6. array = new int[32];
  7. }
  8. // 扩容
  9. public void resize() {
  10. // 队列容量翻倍
  11. int newSize = this.size * 2;
  12. this.array = Arrays.copyOf(this.array, newSize);
  13. }
  14. // 上浮
  15. private void upAdjust() {
  16. int childIndex = size - 1;
  17. int parentIndex = (childIndex - 1) / 2;
  18. // temp 保存插入的叶子节点值,用于最后的赋值
  19. int temp = array[childIndex];
  20. while (childIndex > 0 && temp > array[parentIndex]) {
  21. // 无需真正交换,单项赋值即可
  22. array[childIndex] = array[parentIndex];
  23. childIndex = parentIndex;
  24. parentIndex = parentIndex / 2;
  25. }
  26. array[childIndex] = temp;
  27. }
  28. // 下沉
  29. private void downAdjust() {
  30. // temp 保存父节点的值,用于最后赋值
  31. int parentIndex = 0;
  32. int childIndex = 1;
  33. int temp = array[parentIndex];
  34. while (childIndex < size) {
  35. // 如果有右孩子,且右孩子值大于左孩子,则定位到右孩子
  36. if (childIndex + 1 < size && array[childIndex + 1] > array[childIndex]) {
  37. childIndex++;
  38. }
  39. // 如果父节点大于任何一个孩子的值,直接跳出
  40. if (temp >= array[childIndex]) break;
  41. // 无需真正交换,单向赋值即可
  42. array[parentIndex] = array[childIndex];
  43. parentIndex = childIndex;
  44. childIndex = 2 * childIndex + 1;
  45. }
  46. array[parentIndex] = temp;
  47. }
  48. // 入队
  49. public void enQueue(int key) {
  50. // 队列长度超出范围,扩容
  51. if (size >= array.length) {
  52. resize();
  53. }
  54. array[size++] = key;
  55. upAdjust();
  56. }
  57. // 出队
  58. public int deQueue() throws Exception {
  59. if (size <= 0) {
  60. throw new Exception("the queue if empty!");
  61. }
  62. // 获取堆顶元素
  63. int head = array[0];
  64. // 让最后一个元素移动到堆顶
  65. array[0] = array[--size];
  66. downAdjust();
  67. return head;
  68. }
  69. public static void main(String[] args) throws Exception {
  70. PriorityQueue priorityQueue = new PriorityQueue();
  71. priorityQueue.enQueue(3);
  72. priorityQueue.enQueue(5);
  73. priorityQueue.enQueue(10);
  74. priorityQueue.enQueue(2);
  75. priorityQueue.enQueue(7);
  76. System.out.println("出队元素:" + priorityQueue.deQueue());
  77. System.out.println("出队元素:" + priorityQueue.deQueue());
  78. }
  79. }

上述代码采用数组来存储二叉堆的元素,因此当元素数量超过数组长度时,需要进行扩容来扩大数组长度。