堆排序的基本介绍
- 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它是最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。
2)堆是具有以下性质的完全二叉树:
大顶堆:每个节点的值都大于或定域其左右子节点的值
小顶堆:每个节点的值都小于或等于其左右子节点的值
注意:没有要求节点的左右子节点的值的大小关系,一般升序采用大顶堆,降序采用小顶堆。
堆排序的基本思想
升序排列
1.将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点
2.将其与末尾元素进行交换,此时末尾就为最大值
3.然后将剩余n-1个元素重新构造成一个堆,这样会得到n的元素的次小值。如此反复执行,便可得到一个有序序列
代码实现
import java.util.Arrays;
/**
* 堆排序
*/
public class HeapSort {
public static void main(String[] args) {
int[] arr = {1,3,6,8,10,14};
heapSort(arr);
}
public static void heapSort(int[] arr){
System.out.println("堆排序");
//构建初始堆,将一个无序堆构建成一个大顶堆
for (int i = arr.length/2-1; i>=0; i --){
adjustHeap(arr,i,arr.length);
}
System.out.println("初始化大顶堆 : "+Arrays.toString(arr));
//将堆顶元素和末尾元素进行交换,将最大元素放置到数组末端
for (int i = arr.length-1; i > 0; i-- ){
//堆顶元素和末尾元素交换
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
adjustHeap(arr,0,i);
}
System.out.println(Arrays.toString(arr));
}
/**
* 完成 节点i 对应的非叶子节点的树调整成大顶堆
* @param arr 需要调整的数组
* @param i 非叶子节点在数组中索引
* @param length 表示对多少个元素进行调整
*/
public static void adjustHeap(int[] arr, int i, int length){
//查看当前节点i的左右字数 左子树 2*i+1 右子树 2*i+2
for (int k = i*2+1; k< length; k = k*2+1){
//判断左右子树的大小,并获取其最大值
//k+1 说明右子树存在 arr[k]<arr[k+1] 说明右子树大于左子树
if (k+1 < length && arr[k] < arr[k+1]){
k++;//此时用k下标记录右子树
}
//子节点 大于父节点 交换位置
if (arr[k] > arr[i]){
int temp = arr[k];
arr[k] = arr[i];
arr[i] = temp;
i = k;//***
}
}
}
}