1、什么是堆?
堆是一种非线性结构,可以把堆看作一个数组或者一个完全二叉树,通俗来讲堆其实就是利用完全二叉树的结构来维护的一维数组,按照堆的特点可以把堆分为大顶堆和小顶堆。
大顶堆:每个结点的值都大于或等于其左右孩子结点的值
小顶堆:每个结点的值都小于或等于其左右孩子结点的值
(堆的这种特性非常的有用,堆常常被当做优先队列使用,因为可以快速的访问到“最重要”的元素)
我们用简单的公式来描述一下堆的定义就是:
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
2、堆和普通树的区别
内存占用:
普通树占用的内存空间比它们存储的数据要多(必须为节点对象以及左右子节点指针分配额外的内存)
堆仅仅使用数组,且不使用指针
搜索:
二叉树中搜索会很快
堆中搜索会很慢(堆中搜索不是第一优先级,因为其目的是将最大(或最小)的节点放在最前面,从而快速的进行相关插入、删除操作)
3、堆排序实现对数组进行排序
/**
* 下沉操作
*
* @param array
* 建堆的数组
* @param parentIndex
* 父节点
* @param length
* 待排序长度
*/
/**
* 调整堆的下调的步骤
* 1、将当前的父节点和当前父节点的左子节点的下标都那出来,记住当前父节点的值
* 2、是否存在右叶子节点并且比左叶子节点的值小,如果有更新子节点的位置
* 3、如果父节点确定比左右子节点小,则退出循环
* 4、交换孩子父亲节点的值,更新父节点和子节点的下标
*
* @param array
* @param parentIndex
* @param length
*/
public static void HeapSort(int[] array, int parentIndex, int length) {
int childrenIndex = 2 * parentIndex + 1;
int temp = array[parentIndex];
while (childrenIndex < length) {
if (childrenIndex + 1 < length && array[childrenIndex + 1] > array[childrenIndex]) {
childrenIndex++;
}
// 父节点最大则求出大根堆
if (temp >= array[childrenIndex]) {
break;
}
array[parentIndex] = array[childrenIndex];
parentIndex = childrenIndex;
childrenIndex = 2 * childrenIndex + 1;
}
array[parentIndex] = temp;
}
/**
* 建立小根堆
*
* @param array
*/
public static void buildHeap(int[] array) {
// 从i = array.length/2 也就是从左至右的第一个非叶子结点,开始调整二叉堆,得到堆。
for (int i = array.length / 2; i >= 0; i--) {
HeapSort(array, i, array.length);
}
for (int i = array.length - 1; i >= 0; i--) {
int temp = array[0];
array[0] = array[i];
array[i] = temp;
// 需要调整的位置是0位置,所以将此位置放到当前
HeapSort(array, 0, i);
}
}
public static void main(String[] args) {
int[] a = { 3, 9, 7, 5, 4, 15, 6, 2, 0 };
buildHeap(a);
System.out.println(Arrays.toString(a));
//[0, 2, 3, 4, 5, 6, 7, 9, 15]
}