赞
踩
提到优先队列我们首先想到的就是队列这个数据结构
先进先出(FIFO)。
入队列:
出队列:
那么,优先队列又是什么样子呢?
优先队列不再遵循先入先出的原则,而是分为两种情况:
最大优先队列,无论入队顺序,当前最大的元素优先出队。
最小优先队列,无论入队顺序,当前最小的元素优先出队。
比如有一个最大优先队列,它的最大元素是8,那么虽然元素8并不是队首元素,但出队的时候仍然让元素8首先出队:
让我们回顾一下二叉堆的特性:
1.最大堆的堆顶是整个堆中的最大元素
2.最小堆的堆顶是整个堆中的最小元素
因此,我们可以用最大堆来实现最大优先队列,每一次入队操作就是堆的插入操作,每一次出队操作就是删除堆顶节点。
入队操作:
1.插入新节点5
2.新节点5上浮到合适位置。
出队操作:
1.把原堆顶节点10“出队”
2.最后一个节点1替换到堆顶位置
3.节点1下沉,节点9成为新堆顶
import java.util.Arrays; public class PriorityQueue { private int[] array; private int size; public PriorityQueue() { // 队列初始长度32 array = new int[32]; } /** * 入队 * @param key 入队元素 */ private void enQueue(int key){ // 队列长度超出范围,扩容 if (size >= array.length) { resize(); } array[size++] = key; upAdjust(); } /** * * 出队 * */ private int deQueue() throws Exception{ if (size <=0) { throw new Exception("the queue is empty !"); } // 获取堆顶元素 int head = array[0]; // 最后一个元素移动到堆顶 array[0] = array[--size]; downAdjust(); return head; } /** * * 上浮调整 * */ private void upAdjust() { int childIndex = size - 1; int parentIndex = childIndex / 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 temp = array[parentIndex]; int childIndex = 1; 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; } /** * * 扩容调整 * */ private void resize() { // 队列容量翻倍 int newSize = this.size * 2; this.array = Arrays.copyOf(this.array, newSize); } 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()); System.out.println("出队元素:" + priorityQueue.deQueue()); System.out.println("出队元素:" + priorityQueue.deQueue()); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
}
代码中采用数组来存储二叉堆的元素,因此当元素超过数组范围的时候,需要进行resize来扩大数组长度。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。