堆排序(重要)

本文详细介绍了堆排序算法,包括升序排序的实现过程。通过建立大根堆,将最大元素逐步交换到末尾,然后重新调整堆,最终得到有序序列。堆排序的时间复杂度为O(nlogn),空间复杂度为O(1)。文中提供了完整的Java代码实现,包括heapify、siftDown和swap等关键函数。
摘要由CSDN通过智能技术生成

堆,又被命名为优先队列。

//时间复杂度:O(nlogn)
//空间复杂度:O(1)
//升序用大顶堆,降序用小顶堆

堆升序排序的思想就是先将待排序的序列建成大根堆,使得每个父节点的元素大于等于它的子节点。此时整个序列最大值即为堆顶元素,我们将其与末尾元素交换,使末尾元素为最大值,然后再调整堆顶元素使得剩下的 n-1n−1 个元素仍为大根堆,再重复执行以上操作我们即能得到一个有序的序列。

代码如下:

package 排序_重要.选择排序;
//时间复杂度:O(nlogn)
//空间复杂度:O(1)
//升序用大顶堆,降序用小顶堆
public class 堆排序 {

    public static void main(String[] args) {
        int[] nums = {4,6859};
        sortArray(nums);//堆排序
        for (int i : nums){
            System.out.print(i + " ");
        }
    }

    public static int[] sortArray(int[] nums) {
        int last = nums.length-1;//last编号为len-1

        // 将数组整理成大根堆
        heapify(nums);//{9,6,8,5,4}

        // 循环不变量:区间 [0, i] 堆有序
        for (int i = last; i >= 1; ) {
            // 把堆顶元素(当前最大)交换到数组末尾
            swap(nums, 0, i);
            // 逐步减少堆有序的部分
            i--;
            // 下标 0 位置下沉操作,使得区间 [0, i] 堆有序
            siftDown(nums, 0, i);
        }
        return nums;
    }

    /**建立大根堆,掌握
     * 将数组整理成堆(堆有序)
     * @param nums
     */
    private static void heapify(int[] nums) {
        int last = nums.length-1;//last编号为len-1
        // 只需要从 i = (last) / 2 这个位置开始逐层下移
        for (int i = last / 2; i >= 0; i--) {
            siftDown(nums, i, last);
        }
    }

    /**下沉操作,掌握
     * @param nums 当前数组
     * @param i    当前下沉元素的下标
     * @param last  [0, last] 是 nums 的有效部分
     */
    private static void siftDown(int[] nums, int i, int last) {
        while (2 * i + 1 <= last) {
            int j = 2 * i + 1;
            if (j + 1 <= last && nums[j + 1] > nums[j]) {
                j++;
            }

            if (nums[j] > nums[i]) {
                swap(nums, j, i);
            } else {
                break;
            }
            i = j;//继续向下遍历
        }
    }

    //交换函数,掌握
    private static void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学海无涯苦作舟呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值