堆排序(Heapsort)
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
-
大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
-
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
算法描述
- 创建一个堆 H[0……n-1];
- 把堆首(最大值)和堆尾互换;
- 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
- 重复步骤 2,直到堆的尺寸为 1。
例子
数组: 4 6 8 5 9
第一次: 4 6 8 5 9 ===>>> 4 9 8 5 6
第二次: 4 9 8 5 6 ===>>> 9 4 8 5 6
第三次: 9 4 8 5 6 ===>>> 9 6 8 5 4
第四次: 9 6 8 5 4 ===>>> 4 6 8 5 9
第五次: 4 6 8 5 9 ===>>> 8 6 4 5 9
第六次: 8 6 4 5 9 ===>>> 5 6 4 8 9
第七次: 5 6 4 8 9 ===>>> 6 5 4 8 9
第八次: 6 5 4 8 9 ===>>> 4 5 6 8 9
最终 4 5 6 8 9
结束
算法复杂度
空间复杂度: O(1)
时间复杂度:
排序不稳定,原来相等的两个参数排在前面的可能排在后面。
代码实现
public static void sort(int[] sourceArray) throws Exception {
// 对 arr 进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
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 = (int) Math.floor(len / 2); 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;
System.out.println(Arrays.toString(arr));
}
运行结果
输入数组:int[] arr = {4,6,8,5,9};
[4, 9, 8, 5, 6]
[9, 4, 8, 5, 6]
[9, 6, 8, 5, 4]
[4, 6, 8, 5, 9]
[8, 6, 4, 5, 9]
[5, 6, 4, 8, 9]
[6, 5, 4, 8, 9]
[4, 5, 6, 8, 9]
[5, 4, 6, 8, 9]
[4, 5, 6, 8, 9]
但是按照上面的步骤,这时候我们可以看到和演算结果一致,最后多了一轮,自己演示的时候会在结果正确的时候停止。