算法描述开始:
①堆排序算法:假设已经建立好了最大堆,将堆顶元素跟最后一个元素交换,然后将堆的长度减1,此时堆可能已经不是最大堆了,所以需要将减1之后的堆变成最大堆,即始终保持待排序的堆是最大堆,直到堆的大小变为1,结束。
②保持最大堆(递归体):假设左右子树都是最大堆,比较根元素跟左右孩子的大小,若根元素小于左孩子或者右孩子的大小,调整它们的值,使得根元素最大。调整后,左子树或者右子树已经不是最大堆了,递归调用,让调整的子树变成最大堆。
③建堆:由于堆是一个完全二叉树,所以从第a.length/2+1个元素开始到最后一个元素,都是叶节点,从a.length/2到第一个元素都是父节点,于是可以从第a.length/2到第一个元素开始,让它们保持最大堆,即调用步骤②。
算法描述结束。
下面用Java代码实现上述描述:
public class HeapSort {
/**堆排序算法步骤:
* ①让数组保持最大堆性质
* ②建立最大堆
* ③堆排序
*/
public static int heapSize;
/**
*
* @param i
* @return 父节点编号
*/
public static int parentId(int i){
return i/2;
}
/**
*
* @param i
* @return 左孩子节点编号
*/
public static int leftChildId(int i){
return 2*i;
}
/**
*
* @param i
* @return 右孩子节点编号
*/
public static int rightChildId(int i){
return 2*i +1;
}
/**
* 保持最大堆的性质
* ①比较左(右)孩子元素跟父节点元素的大小,调整它们大小,使得父节点元素最大
* ②使调整的左(右)子树也保持最大堆性质
* @param array
* @param i
*/
public static void maxHeapity(int []array,int i){
int left = leftChildId(i);
int right= rightChildId(i);
int largest ;
//比较左、父、右节点元素,获得最大元素的下标
if(left < heapSize && array[left] > array[i]){
largest = left;
}else{
largest = i;
}
if(right < heapSize && array[right] > array[largest]){
largest = right;
}
if(largest == i){
return ;
}else{
int temp = array[i];
array[i] = array[largest];
array[largest] = temp;
maxHeapity(array,largest);
}
}
/**
* 根据数组元素建立最大堆
* @param array
*/
public static void buildMaxHeap(int []array){
for(int i = array.length/2;i>=0;i--){
maxHeapity(array,i);
}
}
/**
* 使用堆实现元素递增排序
* @param array
*/
public static void heapSort(int[] array){
buildMaxHeap(array);
for(int i =array.length -1;i>=1;i--){
int temp = array[0];
array[0] = array[i];
array[i] = temp;
heapSize --;
maxHeapity(array, 0);
}
}
public static void main(String[] args){
int[] array = {18,25,34,9,16,20,41,43,56,26};
heapSize = array.length;
heapSort(array);
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
}
程序运行结果: