堆排序Java

思路

这个代码还不错
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;
            }

        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值