要想学会堆排序,就要知道什么是堆。
堆,分为大根堆和小根堆,学过数据结构的人都知道二叉树,而堆就类似于数据结构中的完全二叉树
如果想要正常排序,我们需要先把这个堆调成大根堆,或者小根堆
大根堆:根节点永远大于叶子节点
小根堆:根节点永远小于叶子节点
那么如何调整这棵二叉树调整成大根堆呢?
像以上这种调整,便可完成一次大根堆调整,那么如何用代码实现呢 ?
以下是我用递归实现的做一次大根堆调整
public static void swap(int[]array,int n,int m){
int temp=array[n];
array[n]=array[m];
array[m]=temp;
}
public static void heap(int[] array,int start,int end){
if(start>=end){
return;
}
int c1=2*start+1;
int c2=2*start+2;
int max=start;
if(c1<end&&array[c1]>array[max]){
max=c1;
}
if(c2<end&&array[c2]>array[max]){
max=c2;
}
if(max!=start){
swap(array,max,start);
heap(array,max,end);
}
}
以上是我进行了一次大根堆调整,如果要进行一整个堆的大根堆调整,则只需要
假设数组的长度是n,那么不难求得它的父节点为 (n-1)/2,然后根据上面堆的特性,我们可以知道,只需从最后一个父节点开始往前遍历,每一个数调整一次即可
public static void buildHeap(int[] array,int end){
int n=end-1;
int parent=(n-1)/2;
for(int i=parent;i>=0;i--){
heap(array,i,end);
}
}
那么之后如何得到一个正常个顺序的一列数组呢?
当建立好一个大根堆之后
如上图所示,我们可以确认的是,最上面的根节点一定是最大的,所以首先需要将第一个拿出来,和最后一个节点做交换,然后将最后一个根节点放出来,此时剩下的二叉树就不是一个大根堆了,然后重新进行堆化,再重复以上操作即可,代码实现如下:
public static void HeapSort(int [] array,int length){
buildHeap(array,length);
for(int i=length-1;i>=0;i--){//根据数组的长度将数组第一个和最后一个交换
swap(array,i,0);
buildHeap(array,i);
}
}
以上,一个堆排序就完成了。
完整代码如下:
public static void swap(int[]array,int n,int m){
int temp=array[n];
array[n]=array[m];
array[m]=temp;
}
public static void HeapSort(int [] array,int length){
buildHeap(array,length);
for(int i=length-1;i>=0;i--){//根据数组的长度将数组第一个和最后一个交换
swap(array,i,0);
buildHeap(array,i);
}
}
public static void buildHeap(int[] array,int end){
int n=end-1;
int parent=(n-1)/2;
for(int i=parent;i>=0;i--){
heap(array,i,end);
}
}
public static void heap(int[] array,int start,int end){
if(start>=end){
return;
}
int c1=2*start+1;
int c2=2*start+2;
int max=start;
if(c1<end&&array[c1]>array[max]){
max=c1;
}
if(c2<end&&array[c2]>array[max]){
max=c2;
}
if(max!=start){
swap(array,max,start);
heap(array,max,end);//循环做一个往回倒的堆化
}
}