算法简介
堆排序(Heapsort)是基于堆这种结构而设计的一种程序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为 。且是一种不稳定排序。
堆是具有以下性质的完全二叉树:
每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆。
注意 : 没有要求结点的左孩子的值和右孩子的值的大小关系。
算法描述
- 将初始待排序关键字序列 构建成大顶堆,此堆为初始的无序区;
- 将堆顶元素 与最后一个元素 交换,此时得到新的无序区 和新的有序区 ,且满足 ;
- 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区 调整为新堆,然后再次将 与无序区最后一个元素交换,得到新的无序区 和新的有序区 。不断重复此过程直到有序区的元素个数为 ,则整个排序过程完成。
动图演示
代码实现
public class Head {
// 堆排序
public static int[] headSort(int[] arr) {
int n = arr.length;
//构建大顶堆
for (int i = (n - 2) / 2; i >= 0; i--) {
downAdjust(arr, i, n - 1);
}
//进行堆排序
for (int i = n - 1; i >= 1; i--) {
// 把堆顶元素与最后一个元素交换
int temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
// 把打乱的堆进行调整,恢复堆的特性
downAdjust(arr, 0, i - 1);
}
return arr;
}
//下沉操作
public static void downAdjust(int[] arr, int parent, int n) {
//临时保存要下沉的元素
int temp = arr[parent];
//定位左孩子节点的位置
int child = 2 * parent + 1;
//开始下沉
while (child <= n) {
// 如果右孩子节点比左孩子大,则定位到右孩子
if(child + 1 <= n && arr[child] < arr[child + 1])
child++;
// 如果孩子节点小于或等于父节点,则下沉结束
if (arr[child] <= temp ) break;
// 父节点进行下沉
arr[parent] = arr[child];
parent = child;
child = 2 * parent + 1;
}
arr[parent] = temp;
}
}