关于堆排序

今天我们不刷力扣了,我们来复习(手撕)一下数据结构中的八大排序算法之一,堆排序

基本概念:

     堆是一种特殊的树形数据结构,即完全二叉树

堆分为大顶堆和小顶堆:

大顶堆:每个节点的值都大于或等于其两个子节点的值,在堆排序算法中用于升序排序。

小顶堆:每个节点的值都小于或等于其两个子节点的值,在堆排序算法中用于降序排序。

映射为数组:

代码实现:

    //堆排序
    public static void heapSort(int[] arr) {
        //构造大根堆
        heapInsert(arr);
        int size = arr.length;
        while (size > 1) {
            //固定最大值
            swap(arr, 0, size - 1);
            size--;
            //构造大根堆
            heapify(arr, 0, size);
 
        }
 
    }
 
    //构造大根堆(通过新插入的数上升)
    public static void heapInsert(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            //当前插入的索引
            int currentIndex = i;
            //父结点索引
            int fatherIndex = (currentIndex - 1) / 2;
            //如果当前插入的值大于其父结点的值,则交换值,并且将索引指向父结点
            //然后继续和上面的父结点值比较,直到不大于父结点,则退出循环
            while (arr[currentIndex] > arr[fatherIndex]) {
                //交换当前结点与父结点的值
                swap(arr, currentIndex, fatherIndex);
                //将当前索引指向父索引
                currentIndex = fatherIndex;
                //重新计算当前索引的父索引
                fatherIndex = (currentIndex - 1) / 2;
            }
        }
    }
    //将剩余的数构造成大根堆(通过顶端的数下降)
    public static void heapify(int[] arr, int index, int size) {
        int left = 2 * index + 1;
        int right = 2 * index + 2;
        while (left < size) {
            int largestIndex;
            //判断孩子中较大的值的索引(要确保右孩子在size范围之内)
            if (arr[left] < arr[right] && right < size) {
                largestIndex = right;
            } else {
                largestIndex = left;
            }
            //比较父结点的值与孩子中较大的值,并确定最大值的索引
            if (arr[index] > arr[largestIndex]) {
                largestIndex = index;
            }
            //如果父结点索引是最大值的索引,那已经是大根堆了,则退出循环
            if (index == largestIndex) {
                break;
            }
            //父结点不是最大值,与孩子中较大的值交换
            swap(arr, largestIndex, index);
            //将索引指向孩子中较大的值的索引
            index = largestIndex;
            //重新计算交换之后的孩子的索引
            left = 2 * index + 1;
            right = 2 * index + 2;
        }
 
    }
    //交换数组中两个元素的值
    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

算法思路:

排序步骤: 

      1.构造一个大顶堆(或小顶堆),取堆顶数字(也就是最大值或最小值)

        2.再将剩下的数字构建一个大顶堆(或小顶堆),取堆顶数字(也就是剩下值当中的最大值(或最小值))

        3.重复以上操作,直到取完堆中的数字,最后得到一个从大到小(或从小到大)排序的序列

基本思路:

将所有元素构成一个堆的形式,然后比较每一个二叉树,将最大的或最小的与根节点元素互换位置,最后将最顶根节点取出,再从左到右、从下到上的方式将尾节点放到最顶根节点上,再重复上述操作进行排序取出最大或最小元素,以此类推,直到所有元素取出。

 

平均时间复杂度:O(n*{log_{2}}^{n}

学习参考: 

堆排序算法(图解详细流程)-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值