import java.util.Arrays;
/*
* 大顶堆(小顶堆)中某个节点的值总是大于(小于)等于其子节点的值,并且堆是一颗完全二叉树。
* 大顶堆用于升序排列
*
* 最好时间O(nlogn);平均时间O(nlogn); 最坏时间O(nlogn); 辅助存储O(1) 不稳定; n大时较好
*
*/
public class MaxHeapSort {
public static void main(String[] args) {
int[] a = new int[] {9,4,5,7,1,2,0,3,10,6,8,3};
System.out.println(Arrays.toString(a));
heapSort(a);
System.out.println(Arrays.toString(a));
}
/* 大顶堆用于升序排列,pos: 完全二叉树中需要调整的位置(parent node)
size: 传来的数组的最大下标值(下标0时,也储存元素)|数组长度 */
public static void maxHeap( int[] a, int pos, int size ) {
int temp;
int child;
for (temp = a[pos]; 2*pos+1 <= size; pos=child) {
child = 2*pos+1;
//选出左右孩子最大的那个
if (child<size && a[child]<a[child +1]) {
child++;
}
//如果 temp(原需要调整的结点的数据)小于孩子;则下沉
if (temp < a[child]) {
a[pos]=a[child]; // 大值(node)往上传
}
//如果temp大于左右孩子,则跳出循环,已构成该位置的大顶堆
else {
break;
}
}
//把temp下沉到pos(已表示子节点)位置
a[pos]=temp;
}
public static void heapSort(int[] arr) {
int n = arr.length;
//初始化,将数组元素改为大顶堆 2*parents+1=n-1
for (int i =(n-2)/2; i>=0; i--) {
maxHeap(arr,i,n-1);
}
//遍历所有数组元素,排序
for (int i = n-1; i >=0 ; i--) {
//将最后一个元素与堆顶元素调换
int tem = arr[0];
arr[0] = arr[i];
arr[i] = tem;
//将完全二叉树最后一个结点剔除,对根结点进行大顶堆调整
maxHeap(arr,0,i-1);
}
}
}
参考文献:
何昊,薛鹏,叶向阳.Java程序员面试笔试宝典[M].北京:机械工业出版社,2014.6.