堆排序
基本介绍
1、堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。
2、堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆。每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆
注意 : 没有要求结点的左孩子的值和右孩子的值的大小关系。
映射到数组
基本思想
1、将待排序序列构造成一个大顶堆
2、此时,整个序列的最大值就是堆顶的根节点。
3、将其与末尾元素进行交换,此时末尾就为最大值。
4、然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。
图解
1、从最后一个非叶子结点(arr.length/2-1)开始,此时值为6,从下至上,从左至右进行判断,此时[6,5,9]构成一棵局部树,从中找出最大值9>6,所以9与6互换,此时局部树满足了大顶堆堆要求。
2、依次类推,[4,9,8]也构成一棵局部树,4和9进行交互即满足了大顶堆堆要求。
3,但此时[4,5,6]不满足要求,那么继续交换,直至满足整个树为大顶堆要求
4、当满足大顶堆后,数组第一位即最大的树,与末尾交换,即把最大的数放至最后
5、交换后,除去最后一位,从新在构建除数组最后一位的大顶堆
9、如此反复,直到数组第一位排序完
代码
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
int arr[] = {5, 4, 3, 2, 1};
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void heapSort(int arr[]) {
int temp = 0;
for (int i = arr.length / 2 - 1; i >= 0; i--) {
adjustHeap(arr, i, arr.length);
}
for (int j = arr.length - 1; j > 0; j--) {
// 构建顶堆完成后,将最大值(首位)与末尾互换
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
adjustHeap(arr, 0, j);
}
}
/**
* 完成将以 i 对应对非叶子结点调整成大顶堆
*
* @param arr 待调整待数组
* @param i 表示非叶子结点在数组待索引
* @param length 表示对多少个元素继续调整,length逐渐减少
*/
public static void adjustHeap(int arr[], int i, int length) {
int temp = arr[i];
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
// 左右子结点判断,找最大的一方
if (k + 1 < length && arr[k] < arr[k + 1]) {
k++;
}
// 与上述最大的子结点,进行判断,若子结点大,则与之互换
if (arr[k] > temp) {
arr[i] = arr[k];
i = k;
} else {
break;
}
}
arr[i] = temp;
}
}
图片参考:
https://www.cnblogs.com/chengxiao/p/6129630.html