堆(英语: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;
    }
}
原文地址:https://www.cnblogs.com/yunfeiqi/p/7942623.html