基本思想:
堆排序是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。
首先可以把给出的一个数组,先按照完全二叉树的样子摆出来,然后我们从底往顶地排好序,按大顶堆来讲满足Key[i]>=Key[2i+1]&&key>=key[2i+2]这个特性,也就是每个子二叉树的跟节点比孩子大,最后堆顶是最大的数,这样就找到了整个数列中最大的,然后把这个最大数从整个二叉树中移掉放在一个队列中,再次重构剩余的二叉树,最后整个队列就有序了。当然这里我们不需要搞什么队列,直接就在同一个数组里做,我们可以把每次取得的堆顶和最后的数对调,然后我们在重构的时候就不要把那个最后的数考虑在整个二叉树中。这样最终整个数组就是有序的了。
代码:
public class Heapsort {
//初始化堆,把上面的整形数据,按照二叉树形式形成一个大顶堆(大的在上面,最大的在堆顶),初始化为自底向上来递归的
public void initMaxHeap(int[] array){
if(array==null||array.length<=1){
System.out.println("您输入的数组为空或者长度小于等于1");
return;
}
int nodesize=array.length/2-1;
for(int i=nodesize;i>=0;i--){
buildOnceNode(array,array.length,i);
}
System.out.println("初始化第一次排序:");
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
//重构一次子二叉树,这里可以递归调用来确保当上面一层的二叉树排好序后对下层的二叉树破坏大顶堆时再对下层进行排序
public void buildOnceNode(int[] array,int len,int index){
int left=index*2+1; //左孩子
int right=index*2+2;//右孩子
int large=index; //根节点,假设根节点是最大的
if(left<len&&array[left]>array[large]){
large=left;
}
if(right<len&&array[right]>array[large]){
large=right;
}
if(large!=index){
swap(array,index,large);
buildOnceNode(array,len,large);
}
}
private void swap(int[] array, int index, int large) {
int temp=array[index];
array[index]=array[large];
array[large]=temp;
}
//进行完整的排序,每排完一次序就交换最后一个与第一个的数,这样最后一个的数就是最大的了,而每次取得最大的值,我们应该把最后的数除去在外然后在重新排序
public int[] sortMaxheap(int[] array){
initMaxHeap(array);
int j=2;
for(int i=array.length-1;i>=1;i--){
swap(array,0,i);
buildOnceNode(array,i,0); //重构堆,自顶向下,因为在buildOnceNode这个函数中有向下递归
System.out.println("\n第"+j+"次排序");
for (int k = 0; k<array.length ; k++) {
System.out.print(array[k]+" ");
}
j++;
}
return array;
}
public static void main(String[] args){
int[] a={3,18,7,6,23,4,100,121,2,3,885};
Heapsort h=new Heapsort();
int[] result= h.sortMaxheap(a);
System.out.println("\n最终结果:");
for (int i = 0; i <result.length ; i++) {
System.out.print(result[i]+" ");
}
}
}