堆排序采用二叉树结构组合数据,有大顶堆和小顶堆两种。堆排序的原理就是通过叶子节点与父节点的对比挪位,将最小或最大值挪至树顶;再将其排出后重复该动作,因此分为两步:1.建堆 2.排除堆顶
二叉树父节点索引值:(k - 1) / 2 子节点索引值:2 * k + 1、2 * k + 2 |
package com.h3c.paixu;
public class 堆排序Demo {
public static void main(String[] args) {
// 1. 初始化一个无序数组
int[] myArr = { 23, 35, 73, 27, 4, 77, 54, 84, 47, 56, 34, 32, 75, 32,
31, 0, 99, 7, 54, 57 };
for (int k = myArr.length - 1; k > 0; k--) {
myArr = 堆排序(k, myArr);
for (int i : myArr) {
System.out.print(i + " ");
}
System.out.println("");
}
}
public static int[] 堆排序(int startIndex, int[] arr) {
int 最后一个非叶子节点 = (startIndex - 1) / 2; // 二叉树父节点索引(len - 1)/2
for (int n = 最后一个非叶子节点; n >= 0; n--) {
int 左儿子 = 2 * n + 1;
int 右儿子 = 2 * n + 2;
if (右儿子 < startIndex && arr[右儿子] > arr[n]) {
int tempIndex = arr[右儿子];
arr[右儿子] = arr[n];
arr[n] = tempIndex;
}
if (arr[左儿子] > arr[n]) {
int tempIndex = arr[左儿子];
arr[左儿子] = arr[n];
arr[n] = tempIndex;
}
}
// 将本轮获取的最大值放在数组最后,下次循环尾标-1
int tempIndex = arr[0];
arr[0] = arr[startIndex];
arr[startIndex] = tempIndex;
return arr;
}
}
堆排序跟直接选择排序相比并不能减少遍历的次数,但是可以减少每次遍历对比元素的次数,因此略优于直接选择排序,但是其实现逻辑较为复杂,一般很少用到。
时间复杂度为:O(nlog2^n) ,空间复杂度为:O(1),堆排序是不稳定排序。