堆是一种基于数的数据结构,这些数必须满足堆性质,即任一父节点都大(小)于或等于它的任一子节点。
常见的堆结构有二叉堆,二项堆和fibonacci堆。
二叉堆是一棵完全二叉树。包括了小顶堆(最小堆)和大顶堆(最大堆)。
性质:
对于大顶堆,树中的任一父节点的值始终大于或等于全部子节点的值。反之为小顶堆。
堆的实现一般直接使用数组作为存储结构,而不必自己构建二叉树。
二叉堆的元素,使用数组来进行表示:
arr[i]的左右子节点分别为arr[2i+1]和arr[2i+2];
arr[i]的父节点为arr[floor((i-1)/2)]和arr[2i+2],floor():向下取整。
二叉堆的构建一般采用自下而上的方式。
int[] arr = {0, 3, 1, 5, 6, 4, 2};
----------------------创建大顶堆----------------------
自下而上,自右向左:
step1:将数组构造为二叉树,注意,并不是真的构建为二叉树,仅仅是将其看作一棵二叉树。
step2:从非叶子节点的最底层开始,检查子树是否符合二叉堆性质,即子树的父节点是否比子节点大。如果子节点比父节点大,则对调。
![创建大顶堆的过程](https://i-blog.csdnimg.cn/blog_migrate/e0633b10fa4512c91a681746343d478c.png)
step1:数组头元素(最大值)与末尾元素交换,将最大元素放置到数组末端
step2:将指针往前移使得已获得的最大值不参与接下来堆的创建
总结:就是不断的选堆顶放到数组的尾部。
public class HeapSort {
public static void main(String[] args) {
int[] arr = {0, 3, 1, 5, 6, 4, 2};
heapSort(arr);
}
public static void heapSort(int[] arr) {
int n = 1;
for (int i = arr.length / 2 - 1; i >= 0; i--) {
createHeap(arr, i, arr.length);
System.out.println("-------------第 "+(n++)+" 次对调----------------------");
for (int ij : arr) {
System.out.printf("%d\t", ij);
}
System.out.println();
}
System.out.println();
for (int i : arr) {
System.out.printf("%d\t", i);
}
int temp = 0;
for (int j = arr.length - 1; j > 0; j--) {
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
createHeap(arr, 0, j);
}
System.out.println();
for (int i : arr) {
System.out.printf("%d\t", i);
}
}
public static void createHeap(int[] arr, int i, int len) {
int temp = arr[i];
for (int k = 2 * i + 1; k < len; k = k * 2 + 1) {
if (k + 1 < len && arr[k] < arr[k + 1]) {
k++;
}
if (arr[k] > temp) {
arr[i] = arr[k];
i = k;
} else
break;
}
arr[i] = temp;
}
}