数组array{2, 1, 4, 3, 6, 5, 7, 8}为例,假设看做:
堆排序:
1、初建堆:把原数组调整成大根堆(根最大)自下而上,自右向左;
最下面(最右)第一个非叶子节点开始即arr[array.length / 2 - 1],比如上面数组是从arr[3]开始
2、调整,把最大数的调整到根节点:自上而下,自左向右
3、把根节点 a[0] (此时已经是最大)和最后一个叶子节点 arr[n] 调换位置,这样最后一个节点就是最大的了。
4、对着a[0]~a[n-1]重复步骤2和步骤3
慢慢的数组从尾部开始逐渐有序递增: a[n] > a[n-1] > a[n-2] >~~ >a[0]
import java.util.Arrays;
public class HeapSort{
public static void main(String[] args) {
int[] array = new int[]{2, 1, 4, 3, 6, 5, 7, 8};
// 排序的主体逻辑
sort(array);
System.out.println(Arrays.toString(array));
}
public static void sort(int[] array) {
// 建堆,按照自下而上,自右向左;(array.length / 2 - 1)是右下角非叶子节点
for (int i = array.length / 2 - 1; i >= 0; i--) {
adjustHeap(array, i, array.length);
}
// 下面,开始排序逻辑,j是前一趟调整范围内数组的尾部
for (int j = array.length - 1; j > 0; j--) {
// 把大顶堆的根元素,放到数组的最后
swap(array, 0, j);
//自上而下,自左向右进行调整的
adjustHeap(array, 0, j);
}
}
public static void adjustHeap(int[] array, int s, int length) {
//自上而下,自左向右一点点调整整棵树的部分,直到每一颗小子树都满足大根堆的规律为止
//a[s]的左子树是a[2s+1],从左子树开始比较
//循环2i+1是下一层的左子树
for (int i = 2 * s + 1; i < length; i = 2 * i + 1) {
//i + 1 < length放前面先判断,否则i+1容易数组下标越界
if (i + 1 < length && array[i] < array[i + 1]) {
i++;//[i]和[i+1]是左右子树,先找到比较大的那个,记录值较大的子树的下标i
}
// 如果子节点更大,根小,则两值进行交换,记录原根此时位置
if (array[i] > array[s]) {
swap(array, s, i);
//s记录原根此时位置
s = i;
} else {
// 如果根大,就直接终止循环了
break;
}
}//for
}
public static void swap(int[] arr, int a, int b) {
//三次异或交换两变量值
arr[a]^=arr[b];
arr[b]^=arr[a];
arr[a]^=arr[b];
}
}//HeapSort