二叉堆是一棵完全二叉树,分为大/小根堆,大根堆每个节点的值都不大于其父节点的值,所以最大值一定在堆顶。在堆排序中和优先队列中可以发挥作用
建堆:堆排序,要先建立一个堆,在建堆的过程中要根据每个节点的值都不大于其父节点的值而建立。由于所有叶子节点都已经是堆了,所以调整堆的过程从最后一个非叶子节点开始,假设数组a[n]表示此堆,那么要从n/2-1节点开始,依次向上直到根节点。在一个节点时,如果此节点的孩子节点没有此节点大,不用调换,否则和左右孩子节点中比较大的那一个调换,直到满足堆的要求。
假设有一组数组{4,1,3,2,16,9,10,14,8,7},那么调堆将会从16开始

二叉堆
排序:由于建好的堆顶就是最大值,因此只要把堆顶的元素和最后一个元素调换,然后再把a[n-1]的元素按照建堆的思路重新调整为一个新堆,重复此步骤就可以了

二叉堆排序过程
hdu 1040 As Easy As A+B
import java.io.BufferedInputStream;
import java.util.Scanner;
import static java.lang.System.out;
public class Main {
private Scanner sc = new Scanner(new BufferedInputStream(System.in));
private int[] a;
private int max(int m, int n) {
return a[m] > a[n] ? m : n;
}
private void swap(int m, int n) {
int t = a[m];
a[m] = a[n];
a[n] = t;
}
public void init() {
int nCase = sc.nextInt();
while (nCase-- > 0) {
int n = sc.nextInt();
a = new int[n];
for (int i = 0; i < n; i++)
a[i] = sc.nextInt();
buildHeap(n);// **********建堆
heapSort(n);// ********排序
for (int i = 0; i < n - 1; i++)
out.printf("%d ", a[i]);
out.println(a[n - 1]);
}
}
private void buildHeap(int n) { // ******** 建堆
int id = ((n >> 1) - 1);
for (int i = id; i >= 0; i--) {
int k = i;
int p = 0;
if (((i << 1) + 2 < n)) {
p = max((i << 1) + 1, (i << 1) + 2);
} else if ((i << 1) + 1 < n && (i << 1) + 2 >= n) {
p = (k << 1) + 1;
} else
break;
while (a[k] < a[p]) {
swap(k, p);
if (((p << 1) + 1 < n) && ((p << 1) + 2 < n)) {
k = p;
p = max((k << 1) + 1, (k << 1) + 2);
} else if ((p << 1) + 1 < n && (p << 1) + 2 >= n) {
k = p;
p = (k << 1) + 1;
} else
break;
}
}
}
private void heapSort(int n) {
int num = n - 1;
for (int i = 0; i < n - 1; i++) {
swap(0, num);
buildHeap((num));
num--;
}
}
public static void main(String[] args) {
new Main().init();
}
}