相关概念
优先队列不再遵循传统的队列先进先出的原则
最大优先队列:无论入队顺序如何,都是当前最大的元素优先出队。
最小优先队列:无论入队顺序如何都是当前最小的元素优先出队。
存储结构:
最大优先队列可以用二叉堆的大顶堆实现
最小优先队列可以用二叉堆的小顶堆实现
出队操作
如下图,要将堆顶10出队,应该先将最后一个叶子节点拿过来放到堆顶,然后再根据二叉堆的“下沉”操作调整二叉堆,从而形成新的优先队列。
“下沉”操作 过程代码图解:
经过一轮的“下沉”操作之后结果如下图:
同理,重复上述操作即可得到最后的结果:
代码实现
/**
* 优先队列的实现
*/
public class PriorityQueue {
private int[] array;
private int size;
public PriorityQueue() {
//队列的初始长度
array = new int[32];
}
@Override
public String toString() {
return "PriorityQueue{" +
"array=" + Arrays.toString(array) +
", size=" + size +
'}';
}
/**
* 入队
* @param key 入队元素
*/
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 is empty!");
}
//获取堆顶元素
int head = array[0];
//让最后一个元素移到堆顶来
array[0] = array[--size];
//下沉调整
downAdjust();
return head;
}
/**
* "上浮" 调整
*/
public 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;
}
/**
* "下沉" 调整
*/
public void downAdjust(){
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 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);
int size = priorityQueue.size;
System.out.println(priorityQueue);
for(int i=0;i<size;i++){
System.out.println("出队元素"+priorityQueue.deQueue());
}
}
}
最后的运行结果如下: