堆排序法是选择排序法的改进版,可以减少在选择排序法中的比较次数,进而减少排序时间。堆排序法用到了二叉树的技巧,是利用堆排序来完成排序的。堆积树是一种特殊的二叉树,可分为最大堆积树和最小堆积树两种
最大堆积树满足以下3个条件:
1、它是一颗完全二叉树
2、所有的节点的值都大于或等于它左、右节点的值
3、树根是堆积树中最大的。
最小堆积树满足以下3个条件
1、它是一颗完全二叉树
2、所有节点的值都小于或等于它左、右子节点的值
3、树根是堆积树中最小的
原理实现图:
代码实现:
public class HeapSort {
public static void main(String[] args) {
int[] arr={12,17,24,32,4,16,34,65,87};
sort(arr);
System.out.println(arr);
}
public static void sort(int []arr){
int temp=0;
//注意:先从下到上从左到右进行调整的,所以i--
for (int i=arr.length/2-1;i>=0;i--){
adjustHeap(arr,i,arr.length);
}
for (int i=arr.length-1;i>0;i--){
temp=arr[i];
arr[i]=arr[0];
arr[0]=temp;
adjustHeap(arr,0,i);
}
}
/*
将一个普通房的无序堆变成大根堆
arr:需要调整的数组
i:从哪一个非叶子结点开始调整
length:对对少个元素进行调整
*/
public static void adjustHeap(int[] arr, int i, int length) {
int temp = arr[i]; //临时变量 保存当前父节点的值
for (int k = 2 * i + 1; k < length; k = k * 2 + 1) {
//先判断两个子节点谁大,然后用大的去跟父节点来比较
if (k + 1 < length && arr[k] < arr[k + 1]) { //保证不越界并且 左边的值比右边小
k++; //那么就让右边的跟父节点比较
}
if (arr[k] > temp) { //如果子节点较大的一个比父节点大
arr[i] = arr[k];//把较大的值赋给当前节点
i = k; //继续向下进行循环比较
} else {
break;
}
}
arr[i] = temp;//改变父节点
}
}