基本思路:
1)将待排序序列构造成一个大顶堆
2)此时,整个序列中的最大值就是顶堆的根节点
3)将其与末尾元素进行交换,此时末尾就为最大值
4)然后将剩余n-1个元素重新构造成一个堆,这样就会得到n个元素的次小值.如此反复执行,便能得到一个有序序列
代码如下
public class HeapSort {
public static void main(String[] args) {
int arr[] = {4,6,8,5,9,2,3,15,0,-1,-9};
heapsort(arr);
System.out.println(Arrays.toString(arr));
}
//编写一个堆排序的方法
public static void heapsort(int arr[]){
int temp = 0;
System.out.println("堆排序!!!");
//将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
for(int i = arr.length/2-1;i>=0;i--){
adjustHeap(arr,i,arr.length);
}
for (int j =arr.length-1;j>0;j--){
//交换
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
adjustHeap(arr,0,j);
}
}
/**
* 功能:完成将以i对应的非叶子节点的数调整成大顶堆
* 举例:int arr[] = {4,6,8,5,9} => i=1 => adjustHeap => 得到{4,9,8,5,6}
* @param arr 待调整的数组
* @param i 表示非叶子结点在数组中索引
* @param length 表示对多少个元素进行调整,length是在逐渐地减少
*/
public static void adjustHeap(int arr[],int i,int length){
int temp = arr[i];//先取出当前元素的值,保存在临时变量
//开始调整
//1.k=i*2+1 中k是i结点的左子结点
for(int k = i*2+1;k<length;k=k*2+1){
if(k+1<length && arr[k]<arr[k+1]){//说明左子结点的值小于右子结点的值
k++;//k指向右子结点
}
if(arr[k]>temp){//如果子结点大于父结点
arr[i]=arr[k];
i=k;//i指向k,继续循环比较
}else {
break;
}
}
//当for循环结束后,我们已经将以i为父结点的数的最大值放在了最顶
arr[i]=temp;//将temp值放在调整后的位置
}
}