一, 概念
在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级高的对象,然后处理 次高的对象。简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电 话。
在这种情况下,我们的数据结构应该提供两个基本的操作,一个是返回高优先级对象,一个是添加新的对象。 这种数据结构就是优先级队列(Priority Queue)
二,内部原理
优先级队列的实现方式有很多,但常见的是使用堆来构建。
三, 操作-入队列
过程(以大堆为例):
- 首先按尾插方式放入数组
- 比较其和其双亲的值的大小,如果双亲的值大,则满足堆的性质,插入结束
- 否则,交换其和双亲位置的值,重新进行 2、3 步骤
- 直到根结点
四, 操作-出队列(优先级最高)
为了防止破坏堆的结构,删除时并不是直接将堆顶元素删除,而是用数组的后一个元素替换堆顶元素,然后通过 向下调整方式重新调整成堆
五, 返回队首元素(优先级最高)
返回堆顶元素即可
六,上代码(具体的操作看代码及注释)
public class MyPriorityQueue {
private int[] array = new int[100];
private int size = 0;
//入队列
public void offer(int val){
array[size] = val;
size ++;
//把新加入的元素进行向上调整
shiftUp(array,size-1);
}
private static void shiftUp(int[] array,int index){
int child = index;
int parent = (child - 1)/2;
while(child > 0){
if(array[parent] < array[child]){
//当前不符合大堆结构,就进行调整
int temp = array[parent];
array[parent] = array[child];
array[child] = temp;
} else{
break;//发现当前父节点比子节点大,这时说明整个数组已经符合堆的要求了
}
child = parent;
parent = (child-1)/2;
}
}
//出队列
public int poll(){
//下标为0,即队首元素,删除堆顶元素,还要保证剩下的结构依旧为堆
int result = array[0]; // 先将队首元素保存下来
array[0] = array[size-1]; //再将队尾元素粘到队首
size--; //表示删除一个元素
shiftDown(array,size,0); //针对队首元素进行向下调整
return result; //返回保存的队首元素
}
private static void shiftDown(int[] array, int size,int index ){
int parent = index;
int child = 2 * parent + 1;//通过parent找到child的下标
while(child < size){
//比较左右子树找到较大值
if(child + 1 < size && array[child+1] > array[child] ){
child = child + 1;
}
//经过上面的比较已经不知道child是左子树,还是右子树了
//但是child下标一定对应左右子树中的较大值下标
//拿child位置元素与parent位置元素比较
if(array[child] > array[parent]){ //不符合就交换父子节点
int temp = array[child];
array[child] = array[parent];
array[parent] = temp;
} else {
//调整完毕,不需要再调整
break;
}
//更新parent和child节点,处理下一层数据
parent = child;
child = 2 * parent + 1;
}
}
//取队首元素
public int peek(){
return array[0];
}
public boolean isEmpty(){
return size == 0;
}
public static void main(String[] args) {
MyPriorityQueue queue = new MyPriorityQueue();
queue.offer(9);
queue.offer(5);
queue.offer(2);
queue.offer(7);
queue.offer(3);
queue.offer(6);
queue.offer(8);
while (!queue.isEmpty()){
int cur = queue.poll();
System.out.print(cur + " ");
}
}
}