首先介绍下堆排序吧,说道堆排序就不得不说引发堆排序的一系列问题,就是如何从一堆无序的数中找出最大的数或者最小的数,亦或者找出其他大小的数,实际上就是对一堆数进行排序,能够让一堆无序的数按照大小顺序进行排列。
堆排序的原理其实就是应用了java数据结构中的二叉树结构
堆分为两类,为最大堆和最小堆。
最大堆:任何非叶子节点的值都大于他左右孩子节点的值;
最小堆:任何非叶子节点的值都小于他左右孩子节点的值;
下面描述下最大堆排序
首先找到最后一个非叶子节点,将他的值和左右孩子的值进行比较,如果左右孩子的值比他大,那么就互换值,就这样依次往上传直到最上方的节点最大,这时候输出这个节点的值并且将这个值移出树,再对剩下的数再一次就行排序,就这样依次移出值,直到这堆无序的数被从大到小排好为止。这样我们就得到了一个有序排列的数组,上文提到的问题也就迎刃而解了。排序分为两个阶段,1阶段是调整节点值使之成为最大堆,2阶段是移出树顶点的值,并把最后一个叶子节点的值赋给树顶点,在进行调整。最后就会得到一段排序好的数字了。
下面贴代码,首先是调整节点值的方法(1阶段)
public static void adjust(int[]a,int n,int k){
//n为数组里有效数字个数
int k1=2*k+1;
int k2=2*k+2;
//定义左右孩子的值
int a1=Integer.MAX_VALUE;
int a2=Integer.MAX_VALUE;
//左孩子值
if(k1<n){
a1=a[k1];
}
//右孩子值
if(k2<n){
a2=a[k2];
}
if(a1<a2){
int t=a[k];
a[k]=a[k1];
a[k1]=t;
adjust(a,n,k1);
}else{
int t=a[k];
a[k]=a[k2];
a[k2]=t;
adjust(a,n,k2);
}
}
这里需要注意的是,在子节点和父节点的值互换了之后,可能会对这里的子节点下面的子节点造成影响,使最大堆不成立,所以需要再次调整。
下面是建立堆并且输出堆的方法(2阶段):
public void sort(int[]a){
//建立初始堆,a.length-1/2为最后一个非叶子节点的位置
for(int i=(a.length-1)/2;i>=0;i--){
//边输出顶堆边调整
adjust(a,a.length,i);
}
int n=a.length;
while(n>0){
System.out.print(a[0]+" ");
a[0]=a[n-1];
n--;
adjust(a,n,0);
}
System.out.println();
}
这样最大堆排序就差不多OK了,总的来说,理解其实挺简单的,但是实际操作起来还是不那么简单的,多思考就行了。