本章主要内容
- 堆排序
- 堆和优先队列
什么是优先队列
- 普通队列:先进先出;后进后出
- 优先队列:出队顺序和入队顺序无关;和优先级有关
Java中优先队列的实现类是PriorityQueue
默认是最小堆,每次弹出最小值;最大堆需要自己传入Comparator,num2-num1 > 0
- 新元素比堆顶元素大,就删除堆顶元素加入新元素,那么就是最大堆
- 如果新数比堆顶元素小,则删除堆顶元素加入新元素,那就是最小堆
核心是如下两个函数
-
offer(元素)
:优先队列加入元素 -
poll()
:优先队列弹出最值元素
PriorityQueue的常见使用
// Java自带的优先队列PriorityQueue
int[] arr = new int[]{2, 5, 3, 9, 6, 4, 7};
System.out.println("原始数组内容:");
for (int i : arr) {
System.out.print(i+" ");
}
System.out.println();
// 1.排序(升序, 默认)
System.out.println("PriorityQueue默认的升序(默认是最小堆,每次弹出最小值):");
PriorityQueue<Integer> pqAsc = new PriorityQueue<>();
for (int i : arr) {
pqAsc.offer(i);
}
while (!pqAsc.isEmpty()) {
System.out.print(pqAsc.poll() + " ");
}
System.out.println();
// 2.排序(降序)
System.out.println("PriorityQueue自定义的降序(自定义成最大堆,每次弹出最大值):");
PriorityQueue<Integer> pqDesc = new PriorityQueue<>(arr.length, new Comparator<Integer>() {
@Override
public int compare(Integer num1, Integer num2) {
return num2.compareTo(num1);
}
});
for (int i : arr) {
pqDesc.offer(i);
}
while (!pqDesc.isEmpty()) {
System.out.print(pqDesc.poll() + " ");
}
System.out.println();
// 3.取出最大的3个元素
System.out.println("取出最大的3个元素(默认是最小堆,每次弹出最小值):");
PriorityQueue<Integer> pqMax = new PriorityQueue<>();
for (int i : arr) {
if (pqMax.size() < 3) {
pqMax.offer(i);
} else if (pqMax.peek() < i) {
// 新元素大于堆顶元素,弹出堆顶元素,并把新的最大值加进去
pqMax.poll();
pqMax.offer(i);
}
}
while (!pqMax.isEmpty()) {
System.out.print(pqMax.poll() + " ");
}
System.out.println();
// 4.取出最小的3个元素
System.out.println("取出最小的3个元素(自定义成最大堆,每次弹出最大值):");
PriorityQueue<Integer> pqMin = new PriorityQueue<>(arr.length, new Comparator<Integer>() {
@Override
public int compare(Integer num1, Integer num2) {
return num2.compareTo(num1);
}
});
for (int i : arr) {
if (pqMin.size() < 3) {
pqMin.offer(i);
} else if (pqMin.peek() > i) {
// 新元素大于堆顶元素,弹出堆顶元素,并把新的最大值加进去
pqMin.poll();
pqMin.offer(i);
}
}
while (!pqMin.isEmpty()) {
System.out.print(pqMin.poll() + " ");
}
System.out.println();
结果如下:
原始数组内容:
2 5 3 9 6 4 7
PriorityQueue默认的升序(默认是最小堆,每次弹出最小值):
2 3 4 5 6 7 9
PriorityQueue自定义的降序(自定义成最大堆,每次弹出最大值):
9 7 6 5 4 3 2
取出最大的3个元素(默认是最小堆,每次弹出最小值):
6 7 9
取出最小的3个元素(自定义成最大堆,每次弹出最大值):
4 3 2
为什么使用优先队列?(优先队列的应用场景)
- windows任务管理器中选择优先级最高的任务执行
- 请求处理,优先处理重要人的请求
- 从1000000个元素中选出前100名,抽象模型就是从N个元素中选出前M个元素