概念:堆是一棵顺序存储的完全二叉树。
小根堆:其中每个结点的关键字都不大于其孩子结点的关键字。
大根堆:其中每个结点的关键字都不小于其孩子结点的关键字。
对于数组:{R0, R1, ... , Rn}来说,Ri为根节点,R(2i+1)为左子节点,R(2i+2)为右子节点
(1) Ri <= R(2i+1) 且 Ri <= R(2i+2) (小根堆),即每个节点的值都不小于其父节点的值;
(2) Ri >= R(2i+1) 且 Ri >= R(2i+2) (大根堆),即每个节点的值都不大于其父节点的值;
堆排序思想:
(1)根据初始数组去构造初始堆(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大,大根堆)。
(2)每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大根堆。
时间复杂度:排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn)[2]
小根堆:其中每个结点的关键字都不大于其孩子结点的关键字。
大根堆:其中每个结点的关键字都不小于其孩子结点的关键字。
对于数组:{R0, R1, ... , Rn}来说,Ri为根节点,R(2i+1)为左子节点,R(2i+2)为右子节点
(1) Ri <= R(2i+1) 且 Ri <= R(2i+2) (小根堆),即每个节点的值都不小于其父节点的值;
(2) Ri >= R(2i+1) 且 Ri >= R(2i+2) (大根堆),即每个节点的值都不大于其父节点的值;
堆排序思想:
(1)根据初始数组去构造初始堆(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大,大根堆)。
(2)每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大根堆。
时间复杂度:排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn)[2]
public class test4 {
public static void main(String[] args) {
heapSort(new int[] { 1, 3, 7, 5, 2, 8, 4, 6, 10, 9 });
}
//调整堆:利用的思想是比较节点parent和它的孩子节点left(parent),right(parent),选出三者最大(或者最小)者,如果最大(小)值不是节点parent而是它的一个孩子节点,那边交互节点parent和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是O(lgn)的操作,因为是沿着深度方向进行调整的。
public static void HeapAdjust(int[] array, int parent, int length) {
int temp = array[parent]; // temp保存当前父节点
int child = 2 * parent + 1; // 先获得左孩子
while (child < length) {
// 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
if (child + 1 < length && array[child] < array[child + 1]) {
child++;
}
// 如果父结点的值已经大于孩子结点的值,则直接结束
if (temp >= array[child])
break;
// 把孩子结点的值赋给父结点
array[parent] = array[child];
// 选取孩子结点的左孩子结点,继续向下筛选
parent = child;
child = 2 * child + 1;
}
array[parent] = temp;
}
public static void heapSort(int[] list) {
// 循环建立初始堆:这里循环遍历子树,从最靠后的子树开始调整,建立大根堆。
for (int i = list.length / 2; i >= 0; i--) {
HeapAdjust(list, i, list.length);
}
// 进行n-1次循环,完成排序
for (int i = list.length - 1; i > 0; i--) {
// 最后一个元素和第一元素进行交换
int temp = list[i];
list[i] = list[0];
list[0] = temp;
// 筛选 R[0] 结点,得到i-1个结点的堆
HeapAdjust(list, 0, i);
System.out.println(Arrays.toString(list));
}
}
}