最近学习数据结构时,发现堆排序的算法实际上挺复杂的,然后做了分析绘制了图解。堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
堆
堆是以顺序存储方式存储在一个一维数组当中
可以看作一棵完全二叉树
父节点>=两个左右子节点称:大顶堆(大根堆)
父节点<=两个左右子
堆排序步骤
Step 1: 调整
将一个无序的数组,调整成一个初始的大顶堆(小顶堆)。
Step 2: 排序
将排好序的堆顶的元素(此时堆顶要么是数组的最大值,要么是最小值)与堆的末尾元素交换,最末尾的确定下来后,将前面的元素再次调整成大顶堆(小顶堆),重复这个过程。
堆排序图示
堆排序源码:
Heap.java
public class Heap {
private int temp=0;
/**
* 1.先将无序的数组调整成大顶堆
* 2.将堆顶和最后一个元素交换
* 3.将前 n-1 个元素再进行大顶堆调整,再交换
*/
//完整的堆排序过程
public void sort(int[] arr,int len){
//先将原来的数组t调整成大顶堆
for(int i=(arr.length/2)-1;i>=0;i--){ //从编号最大的非叶子结点开始,length/2-1,
SortHeap(arr, i, arr.length);
}
//交换和调整
for(int i=len-1;i>0;i--){ //下标从 0开始,所以长度要 减去1 ,循环 n-1次(1.交换 2.调整)
swap(arr,0,i); //堆顶元素与末尾元素进行交换
SortHeap(arr, 0, i); //交换后重新调整
}
}
//调整成大顶堆
private void SortHeap(int[] arr,int i,int length){
temp=arr[i]; //暂存树的根节点
for(int k=i*2+1;k<length;k=k*2+1){ //
if(k+1<length&&arr[k]<arr[k+1]){ //只有小于length的情况下才有右子节点,比较左右节点
k++; //如果右节点更大,则 k 指向右节点
}
if(arr[k]>temp){ //左子节点或者右子节点如果大于temp
arr[i]=arr[k]; //将较大的子节点与正在处理的根节点互换
i=k; //
}else{
break;
}
}
arr[i]=temp;
}
//交换
private void swap(int[] arr,int i, int j) {
int temp = arr[i];
arr[i] =arr[j];
arr[j]= temp;
}
}
Test.java
import java.util.Arrays;
public class Test {
public static void main(String[] args){
int[] array = new int[]{4,6,8,5,9};
Heap arr = new Heap();
System.out.println("堆排序前:"+Arrays.toString(array));
arr.sort(array, array.length);
System.out.println("堆排序后:"+Arrays.toString(array));
}
}
10.24 KFXL