一、什么是堆排序
- 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点
二、堆排序的基本思想
1、将待排序的序列构成一个大顶堆(即:根节点为树的最大值)
2、然后将大顶堆与末尾元素进行交换
3、再把剩下的n-1个元素元素重新构成一个堆,这样会得到n个元素的次小值。如此反复执行得到一个有序序列
可以看到在构建大顶堆的过程中,元素的个数在逐渐减少,最后得到一个有序序列。
三、图解堆排序过程
我们要知道,堆排序还是在一维数组上操作的,我们只是为了更直观的理解和看到堆排序的过程利用了堆这种数据结构而已
- 假设待排序数组:int []arr = {7,4,3,2,8,0,1,6,9};
当然有同学对上面这交换和交换后怎么操作不太了解,我再画图讲下:
代码也有详细的注释,帮助理解
四、代码实现
//把一个数组(二叉树),调整成一个大顶堆
/**功能:将以 i 指向的非叶子节点的数调整成大顶堆
* @param arr 待调整数组
* @param i 表示叶子节点在数组中的索引
* @param length 对多少个元素进行调整 在逐渐减少
*/
public static void adjustHeap(int[]arr,int i,int length){
int temp = arr[i];//取出当前元素保存起来
//开始调整
//说明:k是i节点的左子节点
for (int k = i*2+1;k<length;k = k*2+1){
if (arr[k]<arr[k+1]&& k+1<length){//左子节点值小于右子节点
k++;//k就指向右子节点
}
if (arr[k]>temp){//这时候k指向的是是左右节点的最大值 子节点大于父节点,交换;然后接着向下判断
arr[i] = arr[k];
i = k;//注意:这时候并不能把arr[i]的值也交换过去,因为并不知道交换后的arr[i]的左右节点是否需要调整
//所以我们先让i= k;接着往下判断
// 注意注意注意:i= k继续判断,temp的值依然是起始的temp,这样才能继续向下判断
}else {
break;//为什么敢break?因为我们向下已经都调整完了,底下没有元素
}
}
//局部调整完了,因为我们只传进来了一个非叶子节点下标 结果得到:以 i 为父节点的树的最大值
arr[i] = temp;
}
//编写一个堆排序的方法
public static void heapSort(int []arr){
int temp = 0;
for(int i = arr.length/2-1;i>=0;i--){
adjustHeap(arr,i,arr.length);
}
System.out.println(Arrays.toString(arr));
for(int j = arr.length-1;j>0;j--){
//交换
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
adjustHeap(arr,0,j);
}
}
主方法测试:
> public static void main(String[] args) {
> int []arr = {4,6,8,5,9};
>
> heapSort(arr);
> System.out.println(Arrays.toString(arr));
> }
附赠好看壁纸一张0.0