思路
这个代码还不错
https://blog.csdn.net/weixin_51609435/article/details/122982075
就是从下往上进行调整
1. 如何将数组映射成树
对于下面这颗树,原来的数组是:
好,如果调整的话,我们第一个应该调整的是最下边,最右边的树,即
5 2 1 根是 5 看看左右孩子有没有比他大的,我们在上边数组中如何确定第一个子树先找5 2 1 呢,
首先可以看一下下面的文章,介绍数组和树映射的
https://blog.csdn.net/qq_44993268/article/details/131452785
我们可以确定的是
这个小树的root 的index = 4 left = 9 right = 10
即 left = 2 * root +1
right = 2 * root +2;
我们现在知道的是数组的长度len,知道最后一个元素last = len-1(数组从0开始)
所以 如果我们设 第一个应该排序的子树即最下最右的子树的根为x
如果len是偶数,则最后一个在左边,即
len-1 = 2* x +1;
x=(len-2)/2
如果len是奇数,则最后一个在右边,即
len-1 = 2* x +2;
x=(len-3)/2
但是我们发现,就是不管奇数还是偶数,都可以用x=(len-2)/2这个来计算
这样我们就找到第一个需要调整的子树,下一个的话就是x-1(自己对着上边的树模拟)
bug
len-- 是下一行才起作用!
还有一个易错点,是 怎么判断三个数的大小,怎么找到三个数中最大的
代码
import java.util.Arrays;public class HeapSortTest {public static void main(String[] args) {int[] arrary = {9,5 ,6,3,5,3,1,0,96,66};heapSort(arrary);System.out.println(Arrays.toString(arrary));}public static void heapSort(int[] nums){int len = nums.length;for (int i = (len-2)/2; i >=0 ; i--) {heapAdjust(i, nums, len);}while (len >1){int temp = nums[0];nums[0] = nums[len-1];nums[len-1] = temp; //最后一个heapAdjust(0, nums,--len);System.out.println(Arrays.toString(nums));}}// start 需要调整的子树的根// len 是目前需要调整的数组的长度private static void heapAdjust(int start, int[] nums, int len) {for (int i = start; i < len;) {//左孩子右孩子都有if (i*2+1 < len && i*2+2 < len){if (nums[i] >= nums[i*2+1] && nums[i] >= nums[i*2+2]){return;} else if (nums[i] >= nums[i*2+1] && nums[i] < nums[i*2+2]) {//右孩子大int temp = nums[i*2+2];nums[i*2+2] = nums[i];nums[i] = temp;i = i*2+2;} else if (nums[i*2+2] < nums[i*2+1]){int temp = nums[i*2+1];nums[i*2+1] = nums[i];nums[i] = temp;i = i*2+1;}else {int temp = nums[i*2+2];nums[i*2+2] = nums[i];nums[i] = temp;i = i*2+2;}} else if (i*2+1 < len) { //只有左孩子if (nums[i] >= nums[i*2+1]){return;}else {int temp = nums[i*2+1];nums[i*2+1] = nums[i];nums[i] = temp;i = i*2+1;}}else { //左右孩子都没有return;}}}}