堆排序算法
-
堆排序定义:堆排序是将一组无序数组(二叉树)构建成一个堆,分为大顶堆和小顶堆
- 大顶堆:父节点的值永远大于其左子树和右子树的值
-
堆排序思路:将堆顶元素与末尾元素交换,然后重新调整结构,使其满足堆的定义,然后反复执行以上步骤,直到整个数组有序。
- 实现数组元素升序排序,需要先调整为大顶堆,然后依次将堆顶“沉元素”
-
代码实现:
package com.guodaxia.heapsort;
import java.util.Arrays;
/**
* 实现堆排序算法,这里采用数组存储二叉树,对其无序二叉树进行升序处理和降序排序
* @ author Guo daXia
* @ create 2022/11/28
*/
public class HeapsortDemo {
public static void main(String[] args) {
int[] arr={4,9,8,5,6};
System.out.println("排序前:"+Arrays.toString(arr));
HeapSort(arr);
System.out.println("排序后:"+ Arrays.toString(arr));
}
//2.编写一个堆排序方法
public static void HeapSort(int[] arr){
//从左=>右;从下=>上 进行堆排序
for (int i=arr.length/2-1;i>-1;i--){
adjustHeap(arr,i, arr.length);
}
int temp;
//第一个for完成后,已经满足大顶堆定义
for (int j=arr.length-1;j>0;j--){
//交换,将堆顶元素“沉入底”
temp=arr[0];
arr[0]=arr[j];
arr[j]=temp;
//以上步骤打乱了大顶堆定义,故要调整
//i为0表明将交换到堆顶的元素需要沉到满足大顶堆的定义的位置上
//j逐渐减小对大顶堆的规模量进行调整
adjustHeap(arr,0,j);
}
}
/**
* 1.将一个二叉树(数组),调整为大顶堆
* @param arr 要调整的数组
* @param i 除了叶子节点的其他节点索引
* @param length 待调整数组的长度 ,length是逐渐减少的
*/
public static void adjustHeap(int[] arr,int i,int length){
//说明:大顶堆定义:父节点的值大于其左节点或右节点的值,左节点和右节点不需要作比较
//先比较无序数组左右节点的值大小,然后将值较大的子节点交换父节点
int temp=arr[i];//暂时存放当前父节点的值
//k =2*i+1表示左节点 ;k+1表示右节点
for (int k =2*i+1;k<length;k=2*k+1){
if (k< arr.length&&arr[k]<arr[k+1]){
k++;//说明下面代码是右节点进行交换
}
if (arr[k]>temp){
arr[i]=arr[k];
i=k;
}else {
//如果子节点值小于temp
break;
}
}
//结束循环后,说明已经局部堆顶值最大
arr[i]=temp;//因为i一直随着k而改变,所以当i确定了,说明i位置就是已经将最大的值放在局部堆顶了,再将temp值放入arr[i]实现交换
}
}
-
总结
-
难点:方法adjustHeap参数的理解及其
i=k
动态局部堆元素交换的理解;调整后实际交换后还需要进行重新调整。 -
运算速度:80w数据执行3s,相当快。
-
面试:常问,且需要掌握代码书写。
-