先附上代码:
public class Heapify {
//从n/2开始查找
public void buildHeapify(int[] list){
//从一开始存
//int[] list ={0,4,2,6,24,12,9}; length=7 max=6
int start=(list.length-1)/2;
for(;start>0;start--){
heapify(list,start);
}
}
public void heapify(int[] list, int start){
int largest = start;//这里从根节点,左子数,右子数选择最大的然后才交换;
if((start*2<= list.length-1) && (list[start*2]>list[start]) ){
largest = start*2;
//heapify(list, start*2);
}
if( (start*2+1 <= list.length-1) &&list[start*2+1]>list[largest]){
largest= start*2 +1;
// heapify(list, start*2+1);
}
if(largest!= start){
//需要交换,并且继续深层堆化
int temp =list[largest];
list[largest]=list[start];
list[start]=temp;
heapify(list,largest);
}
}
}
public class HeapSort {
//堆的性质, 堆顶输出最大值, 交换,再堆化,线性输出
public static void main(String args[]){
int[] list={0,4,2,6,24,12,9};
Heapify h = new Heapify();
for(int i=1;i<7;i++){
h.buildHeapify(list);
System.out.println(list[1]);
for(int j=2;j<list.length;j++){
list[j-1]=list[j];
}
//清零
list[list.length-1]=0;
}
}
}
输出结果:
24 12 9 6 4 2
堆可以理解为一个完全二叉树,即按照顺序每一层由左到右依次填满这棵二叉树,因此在分布上有如下规律,
如果一个结点存在左右孩子,那么那么之间的关系:(我在实现时数组的第一个位置不放数字)
父:i ,左:2* i ,右 2*i+1
堆具有的属性是:对于每一个结点,他的左右孩子左孩子比它小,右孩子比它大(某个结点的值最多与父结点一样大)
推排序主要分为两个部分:1. 建堆,要求堆的堆顶输出的一定是最大的数。 2.每次堆顶输出最大的元素,然后再重新堆化(这里可以有多种实现,我选择的是输出最大值后将数组往前移一位,然后在数组后面补上一个0),依次输出堆顶元素,直至全部输完。
可以发现,在实际进行堆化的时候,是从(list.length-1)/2 处开始一直往堆顶的方向堆化。如果发现当前结点的值小于子结点的时候,要交换位置,并且要再以比它大的子结点为根结点继续堆化。
对于算法的时间复杂度的问题,等日后再补上。