优先队列不再遵循先入先出的原则,而是分为两种情况。
- 最大优先队列,无论入队顺序如何,都是当前最大的元素优先出队;
- 最小优先队列,无论入队顺序如何,都是当前最小的元素优先出队;
可以使用最大堆和最小堆来分别实现最大优先队列和最小优先队列。
代码实现
public class PriorityQueue {private int[] array;private int size;public PriorityQueue() {// 队列初始长度为 32array = new int[32];}// 扩容public void resize() {// 队列容量翻倍int newSize = this.size * 2;this.array = Arrays.copyOf(this.array, newSize);}// 上浮private void upAdjust() {int childIndex = size - 1;int parentIndex = (childIndex - 1) / 2;// temp 保存插入的叶子节点值,用于最后的赋值int temp = array[childIndex];while (childIndex > 0 && temp > array[parentIndex]) {// 无需真正交换,单项赋值即可array[childIndex] = array[parentIndex];childIndex = parentIndex;parentIndex = parentIndex / 2;}array[childIndex] = temp;}// 下沉private void downAdjust() {// temp 保存父节点的值,用于最后赋值int parentIndex = 0;int childIndex = 1;int temp = array[parentIndex];while (childIndex < size) {// 如果有右孩子,且右孩子值大于左孩子,则定位到右孩子if (childIndex + 1 < size && array[childIndex + 1] > array[childIndex]) {childIndex++;}// 如果父节点大于任何一个孩子的值,直接跳出if (temp >= array[childIndex]) break;// 无需真正交换,单向赋值即可array[parentIndex] = array[childIndex];parentIndex = childIndex;childIndex = 2 * childIndex + 1;}array[parentIndex] = temp;}// 入队public void enQueue(int key) {// 队列长度超出范围,扩容if (size >= array.length) {resize();}array[size++] = key;upAdjust();}// 出队public int deQueue() throws Exception {if (size <= 0) {throw new Exception("the queue if empty!");}// 获取堆顶元素int head = array[0];// 让最后一个元素移动到堆顶array[0] = array[--size];downAdjust();return head;}public static void main(String[] args) throws Exception {PriorityQueue priorityQueue = new PriorityQueue();priorityQueue.enQueue(3);priorityQueue.enQueue(5);priorityQueue.enQueue(10);priorityQueue.enQueue(2);priorityQueue.enQueue(7);System.out.println("出队元素:" + priorityQueue.deQueue());System.out.println("出队元素:" + priorityQueue.deQueue());}}
上述代码采用数组来存储二叉堆的元素,因此当元素数量超过数组长度时,需要进行扩容来扩大数组长度。
