一.简单介绍一下二叉堆
下面是百度百科对二叉堆的说明解释。其他二叉堆的说明就不一一介绍了,本身算是个算法小白.
https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E5%A0%86/10978086?fr=aladdin
二. 二叉堆的简单实现
二叉堆最核心的操作是上浮和下沉。
上浮是添加元素到队尾元素,然后经过与上一级节点比较,将队尾元素变动到合适的位置。
下沉是头结点元素,跟左右叶子节点比较,下沉到合适位置。
简单的代码实现:
public static void buildUpHeap(int[] arr) {
for (int i = arr.length - 1; i >= 0;) {
upAdjust(arr, i);
i = i - 2;
}
}
public static void buildDownHeap(int[] arr) {
for (int i = (arr.length - 2) / 2; i >= 0; i--) {
downAdjust(arr, i, arr.length);
}
}
public static void downAdjust(int[] arr, int parentInx, int length) {
int temp = arr[parentInx];
int childInx = parentInx * 2 + 1;
while (childInx < length) {
// 计算那个子树比较小
if (childInx + 1 < length && arr[childInx + 1] < arr[childInx]) {
childInx++;
}
if (temp <= arr[childInx]) {
break;
}
// 单边赋值
arr[parentInx] = arr[childInx];
parentInx = childInx;
childInx = childInx * 2 + 1;
}
arr[parentInx] = temp;
}
public static void upAdjust(int[] arr, int childInx) {
int parentInx = (childInx - 1) / 2;
int temp = arr[childInx];
while (childInx > 0 && temp < arr[parentInx]) {
arr[childInx] = arr[parentInx];
childInx = parentInx;
parentInx = (parentInx - 1) / 2;
}
arr[childInx] = temp;
}
三 二叉堆在jdk中有哪些具体的实现?
1. DelayedWorkQueue
这个是在ScheduledThreadPoolExecutor线程池调度执行器里面,任务可延迟队列的实现。内部存在siftUp siftDown
2. PriorityQueue PriorityBlockingQueue
2个优先级队列, 这边不说明了
3. TaskQueue
TaskQueue 是早期定时任务Timer中队列的实现方法。内部存在 fixUp fixDown
上述几个对列,内部都是以二叉堆的方式实现的。虽然方法名称不太一样,但是实现逻辑大同小异。
四. 什么样的场景适合二叉堆?
1)比如topK问题。 从一亿数据中找出排名前10的数据, 这个可以使用最小堆实现
2)堆排序, 二叉堆本身就是一个有序的近似完全二叉堆
3)数据量小的场景。因为二叉堆,内部通过数组实现。 如果父节点位置为n, 那么子节点为2*n+1, 2*n+2, 如果n比较大,那么很浪费存储空间