堆 排序

基本思想:

堆 排序是对简单选择排序的改进, 其利用了大根堆或者小根堆的性质.

大致过程为 先对一个数列 自底向上 构建一个大根堆, 然后交换第一个元素和最后一个元素, 交换后再 自顶向下 构建大根堆后, 再把第一个元素和倒数第二个元素交换, 重复这个过程.

图:

在这里插入图片描述

在这里插入图片描述




最好最坏时间复杂度:

堆排序是不稳定排序, 时间复杂度总能维持在 O(N*logN).

在这里插入图片描述



java 实现:
package my.code.repository.study.algorithm.sort;


import java.util.Arrays;

/**
 * @author djh on  2019/5/29 18:55
 * @E-Mail 1544579459@qq.com
 */
public class HeapSort {

    public static void main(String[] args) {
        int[] nums = new int[]{1, 2, 22, 33, 11, 234, 66, 3, 4, 6, 7, 5, 77, 89, 345, 123, 45, 342};
        heapSort(nums);
        System.out.println(Arrays.toString(nums));
    }

    private static void heapSort(int[] nums) {
        // 先自底向上构建一个大根堆
        buildMaxRootHeap(nums, nums.length - 1);

        int length = nums.length - 1;
        for (int i = length; i >= 0; ) {
            // 交换最后一个元素和第一个元素
            int temp = nums[0];
            nums[0] = nums[i];
            nums[i] = temp;
            // 让 i-- 从而禁止访问到最后一个元素.
            i--;
            // 自顶向下构建大根堆
            maxHeap(nums, i, 0);
        }
    }

    /**
     * @param nums   Build a large heap of elements
     * @param length The length of the array that can be accessed
     */
    private static void buildMaxRootHeap(int[] nums, int length) {
        // 获取最后一个叶子节点的父节点的索引, 然后从这个父节点开始自底向上构建大根堆.
        int parentIndex = parentIndex(nums.length - 1);

        // 自底向上构建大根堆.
        for (int i = parentIndex; i >= 0; i--) {
            maxHeap(nums, length, i);
        }
    }

    /**
     * @param nums   Build a large heap of elements
     * @param length Ability to access array length
     * @param index  Build a large root heap from this index
     */
    private static void maxHeap(int[] nums, int length, int index) {
        int leftChildIndex = leftChildIndex(index);
        int rightChildIndex = rightChildIndex(index);
        int currentPoint = index;

        if (leftChildIndex <= length && nums[leftChildIndex] > nums[currentPoint]) {
            currentPoint = leftChildIndex;
        }

        if (rightChildIndex <= length && nums[rightChildIndex] > nums[currentPoint]) {
            currentPoint = rightChildIndex;
        }

        if (currentPoint != index) {
            int temp = nums[index];
            nums[index] = nums[currentPoint];
            nums[currentPoint] = temp;
        } else {
            return;
        }

        // 递归构建大根堆主要用在 自顶向下 构建大根堆上.
        maxHeap(nums, length, currentPoint);
    }

    private static int parentIndex(int childIndex) {
        return (childIndex - 1) / 2;
    }

    private static int leftChildIndex(int parentIndex) {
        return parentIndex * 2 + 1;
    }

    private static int rightChildIndex(int parentIndex) {
        return parentIndex * 2 + 2;
    }
}

参考:
https://blog.csdn.net/sunnylinner/article/details/52585225
https://zhuanlan.zhihu.com/p/39615266

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值