堆排序

参考:https://www.cnblogs.com/onepixel/articles/7674659.html

其他排序算法传送门:https://blog.csdn.net/jkdcoach/article/details/87442482

源码:https://github.com/sunrui849/sort

堆排序

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

1.1 算法描述

  • 将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
  • 将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];
  • 由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

1.2 动图演示

1.3特性

时间复杂度固定为 n*(log n) ,并且无需额外的空间,采用堆的数据结构进行排序,堆是一颗完全二叉树。常用于取n个数中前K大(小)的数。

1.4代码实现


    //记录已排序的最小索引,在构建最大堆时初始化
    private static int num = 0;
    /**
     * 堆排序
     * 从小到大
     * @param arr
     * @return
     */
    public static int[] sort(int[] arr) {
        if (arr == null || arr.length == 0){
            return arr;
        }

        buildHeap(arr);//将无序数组构建成最大堆

        //只需要遍历完剩余两个节点时即可结束
        for (int i = num - 1; i > 0; i--){
            swap(arr,0,i);
            num--;//此时数组后面 下标是num开始的到最后 的均为已排好序的
            heapify(arr,0);//此时堆中只有根节点是错误的,调整即可
        }
        return arr;
    }

    /**
     * 构建最大堆
     * @return
     */
    private static int[] buildHeap(int[] arr) {
        num = arr.length;

        //最后一个元素的父节点为 num/2 向下取整,构建最大堆也就是从倒数第二层开始调整
        for (int i = num/2 ; i >= 0; i--){
            heapify(arr,i);
        }

        return arr;
    }


    /**
     * 调整堆
     * @param arr
     * @param index
     * @return
     */
    private static int[] heapify(int[] arr, int index){

        int leftChildIndex = index * 2 + 1;
        int rightChildIndex = index * 2 + 2;
        int parentIndex = index;

        //比较父节点和左子节点的值,大的改为父节点
        if (leftChildIndex < num && arr[leftChildIndex] > arr[parentIndex]){
            parentIndex = leftChildIndex;
        }

        //比较父节点和右子节点的值(此时父节点为原来的左节点和父节点中的最大值),大的改为父节点
        if (rightChildIndex < num && arr[rightChildIndex] > arr[parentIndex]){
            parentIndex = rightChildIndex;
        }

        //如果父节点改变了,那么开始交换位置,并向下继续调整(这个递归的逻辑是为了改变根节点时的调整,构建最大堆时这个递归代码是冗余的)
        if (parentIndex != index){
            swap(arr,parentIndex,index);
            heapify(arr,parentIndex);
        }

        return arr;
    }

    /**
     * 交换位置
     * @param arr
     * @param i
     * @param j
     * @return
     */
    private static int[] swap(int[] arr,int i,int j){
        int flag = arr[i];
        arr[i] = arr[j];
        arr[j] = flag;
        return arr;
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值