目录
1. 基本概念篇
1.1 堆排序
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。
1.2大顶堆和小顶堆
- 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
- 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
扫描二维码关注公众号,回复:
11388727 查看本文章
备注:图片来源https://www.cnblogs.com/chengxiao/p/6129630.html
2. 基本思路与步骤
- 将无序的数组构建成大顶堆(一般升序用大顶堆,降序用小顶堆)
- 将大顶堆的首尾互换,重新构建大顶堆,以此循环。如:第一轮,首位为最大值,互换以后,最大值排在最后一位,再将整体数组的长度-1,重新构建大顶堆,如此反复。
2.1 如何构建大顶堆
- 找到所有非叶子节点坐标,非叶子节点顺序为自下而上,从右到左。即:数组length/2-1~0
- 将非叶子节点,自上而下,从右到左进行互换,最终生成大顶堆。即:当前节点i*2+1为左子节点,i*2+2为右子节点。先将左子节点和右子节点比较,将较大子节点的value和当前节点的value进行互换
注意:每次交换的节点为自下而上、从右到左,但是交换的过程是从该节点自上而下、从右到左。
动态效果可进入网址进行演示:https://visualgo.net/zh/heap,左下角--创建--输入数组--创建,即可查看动态效果
2.2 排序过程
过程不在描述,具体可进入网址,https://visualgo.net/zh/heap,点击堆排序即可查看动态效果。
3. 代码实现
基本每行代码都有注释
/**
* 堆排序
* 动态效果:https://visualgo.net/zh/heap
*
* @author 浪子傑
* @version 1.0
* @date 2020/5/27
*/
public class SortHeapSort {
public static void main(String[] args) {
int[] arr = {4, 6, 8, 9, 5};
sort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 堆排序
*
* @param arr
*/
public static void sort(int[] arr) {
// 将非叶子节点和左右节点自下而上、自右向左循环构建大顶堆
// arr.length/2 -1为第一个非叶子节点
for (int i = arr.length / 2 - 1; i >= 0; i--) {
adjustHeap(arr, i, arr.length);
}
// 将root节点和最后一个节点交换后,自上而下、自右向左构建为大顶堆
for (int i = arr.length - 1; i > 0; i--) {
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
adjustHeap(arr, 0, i);
}
}
/**
* 重点:将以i为节点,自上而下、自右向左构建为大顶堆
*
* @param arr
* @param i 非子节点
* @param length
*/
public static void adjustHeap(int[] arr, int i, int length) {
// 获取到当前i的value
int temp = arr[i];
// i * 2 + 1为当前节点的左子节点
for (int j = i * 2 + 1; j < length; j = j * 2 + 1) {
// 如果左子节点小于右子节点,则让j指向右子节点
if (j + 1 < length && arr[j] < arr[j + 1]) {
j++;
}
// 如果当前子节点的value > 当前节点的value,则交换值
if (arr[j] > temp) {
arr[i] = arr[j];
arr[j] = temp;
// 为下次循环做准备
i = j;
} else {
break;
}
}
}
}