堆排序是一种高效的排序算法,它的时间复杂度为O(nlogn),并且不需要额外的存储空间。
什么是堆排序?
堆排序是一种基于堆的排序算法。堆是一种特殊的树形数据结构,它满足以下两个条件:
- 堆是一个完全二叉树。
- 堆中的每个节点都大于等于(或小于等于)它的子节点。
根据堆的定义,我们可以将堆分为两种类型:最大堆和最小堆。最大堆的根节点是堆中最大的元素,最小堆的根节点是堆中最小的元素。
堆排序的基本思想是:首先将待排序的序列构建成一个最大堆(或最小堆),然后将根节点与最后一个节点交换位置,并将剩余的节点重新构建成一个最大堆(或最小堆)。重复这个过程,直到整个序列有序。
Java实现堆排序
在Java中,我们可以使用数组来表示堆。对于任意一个节点i,它的左子节点为2i+1,右子节点为2i+2,父节点为(i-1)/2。
下面是Java实现堆排序的代码:
public class HeapSort {
public static void heapSort(int[] arr) {
if (arr == null || arr.length == 0) {
return;
}
int len = arr.length;
// 构建最大堆
buildMaxHeap(arr, len);
// 将根节点与最后一个节点交换位置,并重新构建最大堆
for (int i = len - 1; i > 0; i--) {
swap(arr, 0, i);
len--;
heapify(arr, 0, len);
}
}
private static void buildMaxHeap(int[] arr, int len) {
for (int i = len / 2 - 1; i >= 0; i--) {
heapify(arr, i, len);
}
}
private static void heapify(int[] arr, int i, int len) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int largest = i;
if (left < len && arr[left] > arr[largest]) {
largest = left;
}
if (right < len && arr[right] > arr[largest]) {
largest = right;
}
if (largest != i) {
swap(arr, i, largest);
heapify(arr, largest, len);
}
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
在上面的代码中,我们首先判断数组是否为空,然后构建最大堆。构建最大堆的过程是从最后一个非叶子节点开始,依次向上调整。调整过程使用heapify方法实现。
在构建完成最大堆之后,我们将根节点与最后一个节点交换位置,并将剩余的节点重新构建成一个最大堆。重复这个过程,直到整个序列有序。
测试代码如下:
public static void main(String[] args) {
int[] arr = {5, 3, 8, 4, 2, 1, 9, 6, 7};
HeapSort.heapSort(arr);
System.out.println(Arrays.toString(arr));
}
输出结果为:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
总结
堆排序是一种高效的排序算法,它的时间复杂度为O(nlogn),并且不需要额外的存储空间。Java实现堆排序的过程比较简单,只需要构建最大堆,并依次将根节点与最后一个节点交换位置即可。