普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在某些情况下,可能需要找出队列中的最大值或者最小值
例如:使用一个队列保存计算机的任务,一般情况下计算机的任务都是有优先级的,需要在这些计算机的任务中找出优先级最高的任务先执行,执行完毕后就需要把这个任务从队列中移除。普通的队列要完成这样的功能,需要每次遍历队列中的所有元素,比较并找出最大值,效率不是很高,这个时候,就可以使用一种特殊的队列来完成这种需求,优先队列
优先队列按照其作用不同,可以分为以下两种:
-
最大优先队列: 可以获取并删除队列中最大的值
-
最小优先队列: 可以获取并删除队列中最小的值
9.1、最大优先队列
堆这种结构是可以方便的删除最大的值,所以,可以基于堆实现最大优先队列
最大堆
1)API设计
2)代码实现
package chapter07;
/**
* @author 土味儿
* Date 2021/9/9
* @version 1.0
* 最大优先队列
* 以堆的方式实现
*/
public class MaxPriorityQueue<T extends Comparable<T>> {
/**
* 存储元素的数组
*/
private T[] items;
/**
* 元素个数
*/
private int n;
/**
* 构造器
*
* @param capacity
*/
public MaxPriorityQueue(int capacity) {
this.items = (T[]) new Comparable[capacity + 1];
this.n = 0;
}
/**
* 元素个数
*
* @return
*/
public int size() {
return n;
}
/**
* 是否为空
*
* @return
*/
public boolean isEmpty() {
return n < 1;
}
/**
* 插入元素
*
* @param t
*/
public void insert(T t) {
// 在结尾插入
items[++n] = t;
// 让新元素上浮,找到合适的位置
swim(n);
}
/**
* 删除最大元素并返回
*
* @return
*/
public T delMax() {
// 最大元素
T max = items[1];
// 交换索引1处 和 最大索引处的元素,让完全二叉树中最右的元素成为临时根结点
exch(1, n);
// 删除交换后最大索引处的元素,即原根结点(最大元素)
items[n] = null;
// 元素数量减1
n--;
// 让新根结点下沉,找到合适位置
sink(1);
return max;
}
/**
* 比较索引i处元素是否小于j处元素
*
* @param i
* @param j
* @return
*/
private boolean less(int i, int j) {
return items[i].compareTo(items[j]) < 0;
}
/**
* 交换索引i处和j处元素
*
* @param i
* @param j
*/
private void exch(int i, int j) {
T temp = items[i];
items[i] = items[j];
items[j] = temp;
}
/**
* 让索引k处元素上浮到合适的位置
*
* @param k
*/
private void swim(int k) {
// 循环比较索引k处元素和它父结点元素,如果父结点小,就交换位置
while (k > 1) {
// 比较当前结点与父结点
if (less(k / 2, k)) {
// 父比子小,交换位置
exch(k / 2, k);
}
k = k / 2;
}
}
/**
* 让索引k处元素下沉到合适的位置
*
* @param k
*/
private void sink(int k) {
// 循环比较当前结点k 和 max(左子结点2k,右子结点2k+1)的值,如果当前结点k小,就交换位置
// 循环条件 2*k <= n :表示存在 左子结点
while (2 * k <= n) {
// 获取当前结点中的较大 子结点
// 记录较大 子结点索引:默认为 左子结点
int max = 2 * k;
// 如果右结点存在,且左小于右,改变max
if (2 * k + 1 <= n && less(2 * k, 2 * k + 1)) {
max = 2 * k + 1;
}
if (!less(k, max)) {
// 当前结点不小于子结点,退出循环
break;
}
// 当前结点小于子结点,交换位置
exch(k, max);
// 交换k值,继续循环
k = max;
}
}
}
@Test
public void testMaxPriorityQueue() {
String[] arr = {
"E", "B", "A", "C", "D"};
MaxPriorityQueue<String> maxpq = new MaxPriorityQueue<