算法-堆排序(Java)

在这里插入图片描述
最近在看左神的算法课,理解之后在此将代码记录下来

大根堆

任何一棵子树的最大值为树的根
例:
1、3入堆,为根结点
2、5入堆,为3的左孩子,判断是否比3大,大的话交换位置
3、7入堆,为5的右孩子,判断是否比5大,大的话交换位置
4、6入堆,为3的左孩子,判断是否比3大,大的话交换位置
5、4入堆,为6的右孩子,判断是否比6大,大的话交换位置

小根堆

任何一棵子树的最小值为树的根
例:
1、3入堆,为根结点
2、5入堆,为3的左孩子,判断是否比3小,小的话交换位置
3、7入堆,为3的右孩子,判断是否比3小,小的话交换位置
4、6入堆,为5的左孩子,判断是否比5小,小的话交换位置
5、4入堆,为5的右孩子,判断是否比5小,小的话交换位置

在这里插入图片描述
堆排序

/**
     * 堆排序
     *
     * @param arr 待排数组
     */
    private static void heapSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        //将数组转换成大根堆
        for (int i = 0; i < arr.length; i++) {
            heapInsert(arr, i);
        }
        //默认堆大小
        int heapSize = arr.length;
        //交换根结点和最后一个叶子结点的位置
        swap(arr, 0, --heapSize);
        while (heapSize > 0) {
            //重新调整位置,使数组符合大根堆
            heapify(arr, 0, heapSize);
            swap(arr, 0, --heapSize);
        }
    }

    /**
     * 大根堆转换
     * 将数组构想成二叉树,即对应关系为
     * 父结点i的左孩子=2 * i + 1
     * 父结点i的右孩子=2 * i + 2
     * 左右孩子i的父结点=(i - 1) / 2
     *
     * @param arr   待转数组
     * @param index 待转索引位
     */
    private static void heapInsert(int[] arr, int index) {
        while (arr[index] > arr[(index - 1) / 2]) {//当前位置的值比父节点的值大
            swap(arr, index, (index - 1) / 2);//交换它们位置
            index = (index - 1) / 2;//当前位置指向父节点
        }
    }

    /**
     * 调整堆
     *
     * @param arr      数组
     * @param index    当前位置
     * @param heapSize 堆大小
     */
    private static void heapify(int[] arr, int index, int heapSize) {
        int left = index * 2 + 1;//当前位置节点的左孩子
        while (left < heapSize) {
            int largest = (left + 1 < heapSize) && arr[left + 1] > arr[left]
                    ? left + 1
                    : left;//右孩子存在且其值大于左孩子,那么返回右孩子索引位,否则返回左孩子索引位
            largest = arr[largest] > arr[index] ? largest : index;//左右孩子中最大值比当前结点大,返回largest
            if (largest == index) {//否则结束比较
                break;
            }
            swap(arr, largest, index);//交换位置
            index = largest;
            left = index * 2 + 1;
        }
    }

    /**
     * 交换数组中i和j的位置
     *
     * @param arr 数组
     * @param i   i
     * @param j   j
     */
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值