private void buildHeap(int[] h) {
int l = h.length;
//这里需要从下向上调整,因为从上向下调整只能让最小值下到底端,只有从下向上调整可以让最大值上到顶端
//shiftDown需要递归,如果不递归,这里只能保证最大的元素在堆顶,但是不能保证子分支都是最大堆
//这里下标 l/2 -1 是倒数第二层中从左到右最后一个非叶子节点(倒数第二层中最后一个含有子节点的节点)的数组下标
for (int i = (l / 2 - 1) ; i >= 0; i--) {
shiftDown(h, i);
}
}
private void shiftDown(int[] h, int i) {
int l = h.length;
//右子节点的数组下标大于 数组最后一个元素下标,没有右子节点
if (2 * i + 2 > l - 1) {
//左子节点的数组下标大于数组最后一个元素的下标
if (2 * i + 1 > l - 1) {
//没有左节点,不需要交换
return;
} else {
if (h[i] < h[2 * i + 1]) {
//交换根和左子节点
swap(h, i, 2 * i + 1);
shiftDown(h, 2 * i + 1);
} else {
//如果不需要交换,下面递归也不需要,因为调整是从下向上,如果这里没有交换,那么下面的子分支没有受到影响也不需要调整
return;
}
}
} else {
if (h[2 * i + 1] > h[2 * i + 2]) {
//左节点大与右子节点
if (h[i] < h[2 * i + 1]) {
//左子节点大于根节点
swap(h, i, 2 * i + 1);
shiftDown(h, 2 * i + 1);
} else {
return;
}
} else {
//右节点大
if (h[i] < h[2 * i + 2]) {
swap(h, i, 2 * i + 2);
shiftDown(h, 2 * i + 2);
} else {
return;
}
}
}
}
private void swap(int[] h, int i, int j) {
int temp = h[i];
h[i] = h[j];
h[j] = temp;
}