堆排序作为八大排序中较为重要的一种,是每个程序员必须要会并且掌握的
具体思路如下:
首先给定需要排序的数组,构建原始堆
将原始堆调整为大顶堆,思路是这样的,找到第一个非叶子结点(6),判断 6 的左右子树,将左右子树中大的那个与 6 进行交换,然后是第二个飞叶子节点(4),最后是根节点(5),与结点 6 进行交换,结果如下:
此时构造出大顶堆,然后进行对排序的第二步,交换根节点与末尾元素
6 是确定好位置的,脱离整个堆,重新调整堆结构,使它还是成为一个大顶堆
此时继续交换,根节点与最后的结点交换
调整堆结构
同理,最后得出结果:
代码如下:
import java.util.*;
public class Main {
public static void main(String[] args) {
int[] a = new int[]{0, 1, 9, 7, 5, -4, 85, 12};
System.out.println("排序前:" + Arrays.toString(a));
heapSort(a);//开始堆排序
System.out.println("排序后:" + Arrays.toString(a));
}
private static void heapSort(int[] a) {
//第一步,构建大顶堆
for (int i = a.length / 2 - 1; i >= 0; i--) {
adjustHeap(a, i, a.length);//调整堆结构,使整个堆变成一个大顶堆
}
// 第二步,交换位置
for (int i = a.length - 1; i > 0; i--) {
swap(a, i, 0);//交换首位元素
adjustHeap(a, 0, i);//调整大顶堆
}
}
private static void swap(int[] a, int x, int y) {
//由于 java 中没有自带的 swap 函数,所以可以自己写一个,
//当然代码很简单,不写也没问题
int temp = a[x];
a[x] = a[y];
a[y] = temp;
}
private static void adjustHeap(int[] a, int i, int length) {
int temp = a[i];//先将当前元素取出来
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {//每次向下调整
//取得是每个根节点的左孩子,所以 k = k * 2 + 1
if(k + 1 < length && a[k] < a[k + 1]) {
//如果左子树的值小于右子树
k ++;//让右子树交换
}
if(a[k] > temp) {//如果当前子树的值大于根节点,此时我们让子节点上调
a[i] = a[k];//上调
i = k;//记录位置
} else break;
}
a[i] = temp;//再将该位置赋值
}
}