前言:堆堆堆~相信有学过数据结构的同学都了解堆的过程和原理(毕竟数据结构考试最喜欢让我们画大小顶堆的生成过程),了解堆,也了解排序的我,在很长一段时间之内都没有理解堆排序真正的含义。
一直认为大小顶堆已经算是有序了呀,所以导致了我一直以为堆排序就是生成一个大(小)顶堆,当然这个想法是错误滴~现在理清了思路,Mark下来,希望能帮到和我一样曾经迷茫的童鞋~
原理:堆的原理这里就不详细讲啦,只需要记住一句话(根节点大于所有的子节点则为大顶堆,根节点小于所有的子节点则为小顶堆)就可以判断一个堆啦。
那么问题来了,如何进行堆排序呢?
顾名思义,就是利用堆,进行排序。以下举例以大顶堆为例。
要进行堆排序,一共需要生成N-1个大顶堆,每生成一个大顶堆,就将根节点与最末尾元素交换,这样最大的元素就被放在了数组的最后面。
然后N–,在剩下N-1个元素中,继续生成大顶堆,将根节点放在这N-1个元素的最后面···
以此类推,每一次都选出当前排列元素的最大值,放置在队尾,直到完成第N-1个大顶堆的交换~
注意:堆排序的思路和选择排序有点类似,都是每次选择最大的元素,但是,由于堆的树形结构的特殊性,可以保存部分排序结果,可以减少比较的次数。
代码如下:
package zj.com.heap;
import java.util.Arrays;
public class HeapSort {
public void BuildHeap(int[] a){
for(int i = 0;i<a.length-1;i++)
{
int lastindex = a.length-1-i;
MaxHeap(a, lastindex);
//交换每次建堆后的首尾元素,实现非降序排列
Swap(a, 0, lastindex);
}
}
//构建大顶堆
public void MaxHeap(int[] a,int lastindex){
for(int i = (lastindex-1)/2;i>=0;i--)
{
int k = i;
int bigest = 2*k+1;
while(bigest<=lastindex)
{
if(bigest<lastindex)
{
if(a[bigest]<a[bigest+1])
{
bigest++;
}
}
if(a[bigest]>a[k])
{
Swap(a, k,bigest);
k = bigest;
}
else
{
break;
}
}
}
}
//交换元素
public void Swap(int[] a,int i ,int j){
int temp = a[i];
a[i] = a[j] ;
a[j] = temp;
}
public static void main(String[] args) {
int[] a = {3,2,1,6,5,4,9,8,7};
HeapSort heapSort = new HeapSort();
heapSort.BuildHeap(a);
System.out.println(Arrays.toString(a));
}
}