堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质
-
堆中某个节点的值总是不大于或不小于其父节点的值;
-
堆总是一棵完全二叉树。
堆分为两中,大顶堆、小顶堆;大顶堆顾名思义就是堆的每个父元素都大于其孩子,小顶堆当然就是每个父节点都小于其子节点,数学定义如下:
大顶堆:arr[k] >= arr[k*2+1] && arr[k] >= arr[k*2+2]
小顶堆:arr[k] <= arr[k*2+1] && arr[k] <= arr[k*2+2]
堆中最后一个非叶子节点为 len/2-1
如何将一个数组构建成一个大顶堆呢?步骤如下:
1. 将该节点和其节点比较,如果子节点值大于该节点,则交换
2. 再次判断当前节点的子节点的子节点,直到所有节点都判断完成
一般步骤都是从最后一层向上判断,所以就是从堆的最后一个非叶子节点开始判断,之后再将调整所有子节点,代码如下:
package struct.tree; import java.util.Random; /** * 堆是一种树,完全二叉树 * 满足如下性值: * 大顶堆:arr[k] >= arr[2*k+1] && arr[k] >= arr[2*k+2] * 小顶堆:arr[k] <= arr[2*k+1] && arr[k] <= arr[2*k+2] * <p> * 创建大顶堆 * 从堆的最后一个非子节点开始,比较该节点和子节点大小,如果小于子节点,则交换 * 重复,直到最后一个非子节点 */ public class Head { public static void main(String[] args) { int data_len = 10; int[] data = new int[data_len]; Random rd = new Random(); for (int index = 0; index < data_len; index++) { data[index] = rd.nextInt(10000); } createHead(data); for (int i = 0; i < data.length; ) { System.out.printf("%d ", data[i++]); } } public static void createHead(int[] arr) { // 找到最后一个非子节点 for (int i = arr.length / 2 - 1; i >= 0; i--) { // 开始调整 adjustHead(arr, i); } } /** * 调整堆 * * @param arr * @param parent */ public static void adjustHead(int[] arr, int parent) { int tmp = arr[parent]; int child = parent * 2 + 1; while (child < arr.length) { //判断该节点下是否还有第二个子节点,找到最大的字节点 if (child + 1 < arr.length && arr[child] < arr[child + 1]) child++; // 如果单前节点大于了子节点,则直接退出,否则将子节点值赋值给单前节点 if (tmp >= arr[child]) break; else arr[parent] = arr[child]; //继续判断子节点的叶子 parent = child; child = parent * 2 + 1; } arr[parent] = tmp; } }