堆排序是指利用堆这种数据结构所设计的一种排序算法。堆的特点是子结点总是小于(或者大于)它的父节点,根节点最大的堆叫做最大堆,根节点最小的堆叫做最小堆。根据升序或降序的排序需求选择使用最大堆还是最小堆,本文以升序排列为例,所以选用最大堆。
堆排序的基本思想是:将原始序列先调整为一个最大堆,这样根顶元素就是整个序列的最大值;将其与末尾元素交换,这样该序列最大元素就归位了;将剩下的N-1个元素再调整为最大堆,再次交换根顶元素和本次末尾元素,这样次大值也归位了;反复循环,直到整个序列都有序。
java示例:
public class HeapSort {
public static void main(String[] args) {
int[] arr = {1,3,2,6,4,66,32,65,34,67,45,77,78,36,56};
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
sort(arr);
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr) {
//构建最大堆
for (int i = arr.length/2 - 1; i >= 0; i--) {
handleHeap(arr, i, arr.length);//从最末尾的非叶子节点,自右至左,自下而上调整
}
for (int j = arr.length - 1; j > 0; j--) {
swap(arr, 0, j);//交换根顶元素和末尾元素
handleHeap(arr, 0, j);//重新调整成最大堆
}
}
//调整最大堆(建立在最大堆已构建的基础上)
public static void handleHeap(int[] arr, int i, int length) {
int temp = arr[i];//先取出当前元素i
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {//从i结点的左子结点开始,也就是2i+1处开始
if (k + 1 < length && arr[k] < arr[k + 1]) {//如果左子结点小于右子结点,k指向右子结点
k++;
}
if (arr[k] > temp) {//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
arr[i] = arr[k];
i = k;
} else {
break;
}
}
arr[i] = temp;//将temp值放到最终的位置
}
//交换数组中两个元素
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
执行结果:
排序前:
[1, 3, 2, 6, 4, 66, 32, 65, 34, 67, 45, 77, 78, 36, 56]
排序后:
[1, 2, 3, 4, 6, 32, 34, 36, 45, 56, 65, 66, 67, 77, 78]
Process finished with exit code 0