标签:
这节总结一下优先队列的常用实现方法。
普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (largest-in,first-out)的行为特征。(百度百科)
抽象数据类型:
优先队列的接口同前面讲到的队列的接口一样,是其基于泛型的API接口代码如下:
public interface Queue<E> {
//队列是否为空
boolean isEmpty();
//队列的大小
int size();
//入队
void enQueue(E element);
//出队
E deQueue();
}
实现优先队列最简的方法就是基于前面讲到的基于数组的栈的代码,只需对插入或删除操作作相应的更改即可。
在栈的代码的插入方法中添加代码,将所有较大的元素向右移动一格,以保证数组有序(和插入排序相同),这里我们可以使用二分查找的方法来找出元素应插入的位置,然后再移动元素。这样最大元素,总是在数组的最右边,其删除操作和栈的实现中一样。
代码:
/**
* 基于有序数组的实现的优先队列
* @author Alent
* @param <E>
*/
public class PriorityQueue<E extends Comparable<E>> implements Queue<E>{
private E[] elements;
private int size=0;
@SuppressWarnings("unchecked")
public PriorityQueue() {
elements = (E[])new Comparable[1];
}
@Override public int size() {return size;}
@Override public boolean isEmpty() {return size == 0;}
@Override
public void enQueue(E element) {
if(size == elements.length) {
resizingArray(2*size);//若数组已满将长度加倍
}
elements[size++] = element;
insertSort(elements);
}
@Override
public E deQueue() {
E element = elements[--size];
elements[size] = null; //注意:避免对象游离
if(size > 0 && size == elements.length/4) {
resizingArray(elements.length/2);//小于数组1/4,将数组减半
}
return element;
}
//插入排序,由于前面n-1个元素是有序的,这里只插入最后一个元素
public void insertSort(E[] a) {
int N = size -1; //最后一个元素是size-1,不是a.length-1
if(N == 0) return;
int num = binaryFind(a, a[N], 0, N-1);
E temp = a[N];
//num后的元素向后移动
for (int j = N; j > num; j--) {
a[j] = a[j-1];
}
a[num] = temp;
}
//找出元素应在数组中插入的位置
public int binaryFind(E[] a, E temp, int down, int up) {
if(up<down || up>a.length || down<0) {
System.out.println("下标错误");
}
if(temp.compareTo(a[down]) < 0) return down;
if(temp.compareTo(a[up]) > 0) return up+1;
int mid = (up-down)/2 + down;
if(temp.compareTo(a[mid]) == 0) {
return mid + 1;
}else if(temp.