思路
代码
// 堆排序
public static void heapSort(Integer[] arr) {
heapSort(arr, arr.length - 1);
}
/**
*
* @param arr 要排序的数组
* @param lastIndex 数组中未排好序的最后一位索引
*/
private static void heapSort(Integer[] arr, int lastIndex) {
while (lastIndex > 0) {
// 可自行推导,完全二叉树的最后一个父节点的索引 = (lastIndex - 1) / 2
for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
swap(arr, i, lastIndex);
}
// 排好序后,最大值会出现在索引为0的位置(也就是根节点),然后交换根节点和未排好序的最后一个索引,lastIndex这个位置就排好序了
int temp = arr[lastIndex];
arr[lastIndex] = arr[0];
arr[0] = temp;
lastIndex--;
}
}
/**
* 比较某一节点和其子节点大小,将最大的值移动到父节点
* @param arr 要排序的数组
* @param i 要比较的节点索引
* @param lastIndex 数组中未排好序的最后一位索引
*/
private static void swap(Integer[] arr, int i, int lastIndex) {
// 先比较该节点的子节点大小,默认大的为左边的子节点
int maxIndex = 2 * i + 1;
// 要判断右边的子节点是否存在,存在再和左边的节点进行比较
if (2 * (i + 1) <= lastIndex && arr[2 * (i + 1)] > arr[2 * i + 1]) {
maxIndex = 2 * (i + 1);
}
// 如果子节点比父节点大,交换位置
if (arr[maxIndex] > arr[i]) {
int temp = arr[i];
arr[i] = arr[maxIndex];
arr[maxIndex] = temp;
}
}
总结
堆排序咋一看挺难懂的,还涉及到二叉树,其实也就用到了二叉树一个关于父子节点索引关系的一个特性而已,本质和其它排序差不多,只是其它排序都是相邻的两个数比较,然后选出最大的,而堆排序是跳跃式的比较,最终都是一次循环比较选出一个最大值,然后继续比较剩余的数。