优先队列是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有1) 查找;2) 插入一个新元素;3) 删除。当访问元素时,具有最高优先级的元素最先删除(百度百科)。所以,每当插入数据时,我们都会利用堆来将数据进行排序,以方便读取并删除最大值。本代码中,用数组进行存储堆数据,插入数据时将数据存储在数组最后,然后在将其与父节点比较,若大于父节点,则与父节点交换,如此循环直至根节点为止。删除最大值时,将最后一个数据放入根节点位置,然后利用下沉即将父节点与最大子节点比较,若小于最大子节点则与之交换,若此循环,直至不小于任意子节点或者已经是叶子节点为止。
public class MaxPQ<Key extends Comparable<Key>> {
private Key[] pq;//优先级队列
private int N = 0;//当前元素的个数
public MaxPQ(int MaxN)
{
pq = (Key[])new Comparable[MaxN + 1];//不能直接使用泛型创建对象,创建一个数组用于存放堆排序的数据,其中0位置不存放数据
}
public boolean isEmpty()
{
return N == 0;
}
public int size()
{
return N;
}
public void insert(Key v)
{
pq[++N] = v;//将其放入数组的末尾
//利用堆排序进行处理,将数据进行上浮处理
swim(N);
}
public Key delMax()//删除并返回最大值
{
Key temp = pq[1];//存放最大值
exch(1, N--);//将最后一个数据放入树根点,并减少数据的个数
sink(1);//将根节点的数据利用堆排序进行下沉处理
return temp;//返回最大值
}
public boolean less(int i, int j)//判断数组a中a[i]是否小于a[j]
{
return pq[i].compareTo(pq[j]) < 0;
}
public void exch(int i, int j)//交换i和j的数据
{
Key temp = pq[i];
pq[i] = pq[j];
pq[j] = temp;
}
//堆排序上浮
public void swim(int k)
{
while(k > 1 && less(k/2, k))
{
//因为二叉堆中节点的父节点为k/2,子节点为2k,2k+1
exch(k/2, k);//交换两者位置
k = k/2;
}
}
//堆排序下沉
public void sink(int k)
{
while(2 * k + 1 <= N)
{
int j = 2 * k;//左子节点
if(less(j, j + 1))
j++;//取较大的子节点索引赋给j
//若父节点不小于任意子节点,则结束
if(!less(k, j))
break;
exch(k, j);//交换父节点和最大子节点
k = j;//继续判断交换后的子节点是否下沉
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MaxPQ<String> a = new MaxPQ<String>(10);
a.insert("A");
a.insert("S");
a.insert("X");
a.insert("W");
a.insert("B");
a.insert("Z");
a.insert("a");
String t = a.delMax();
System.out.println(t);
}
}