排序算法-堆排序

堆是一个完全二叉树
堆排序是指利用堆这种数据结构所设计的一种排序算法
大顶堆:每个结点的值都大于或等于其左右孩子结点的值
arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
在这里插入图片描述
小顶堆:每个结点的值都小于或等于其左右孩子结点的值
arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
在这里插入图片描述
堆排序的基本思想是:将待排序序列构造成一个大顶堆(小顶堆同理),此时,整个序列的最大值就是堆顶的根节点。 将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得 到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

堆排序的过程

1.将给定无序队列构成一个二叉堆(一般升序排序会将这个二叉堆调整成大顶堆,降序队列调整成小顶堆)
arr=4 6 8 5 9

在这里插入图片描述
2.从最后一个非叶子节点开始从左至右调整,上面的5,9,8都是叶子节点,所以从6开始
最后一个非叶子节点index=arr.length/2-1=5/2-1=1
arr[1]=6
把arr[1]和它的左右儿子(arr[12+1],arr[12+2])比较,把最大的调整到arr[1]的位置上
在这里插入图片描述
3.找到倒数第二个非叶子节点4,和它的左右子节点比较交换
在这里插入图片描述
4.交换指挥456顺序不正确继续调整
在这里插入图片描述
这是这已经是一个大顶堆了

5、将堆顶元素与末尾元素进行交换(交换后不参与重建),使末尾元素最大。然后继续调整堆,再次变成大顶堆后将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换,重建。

在这里插入图片描述

6.反复交换重建

在这里插入图片描述

在这里插入图片描述
代码实现

public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {1,7, 6, 4, 3, 5, 2, 10, 9, 8};
        System.out.println("排序前:" + Arrays.toString(arr));
        sort(arr);
        System.out.println("排序后:" + Arrays.toString(arr));
    }

    public static void sort(int[] array) {
        // 1. 把无序数组构建成最大堆,从最后 非叶子节点开始
        for (int i = array.length / 2 - 1; i >= 0; i--) {
            adjustHeap(array, i, array.length);
        }
        // 2. 调整堆结构+交换堆顶元素与末尾元素,调整堆产生新的堆顶
        for (int i = array.length - 1; i > 0; i--) {
            // 最后1个元素和第1个元素进行交换
            int temp = array[i];
            array[i] = array[0];
            array[0] = temp;
            // “下沉”调整最大堆
            adjustHeap(array, 0, i);

        }
    }

    public static void adjustHeap(int[] array, int parentIndex, int length) { 
        // temp 保存父节点值,用于最后的赋值
        int temp = array[parentIndex];
        int childIndex = 2 * parentIndex + 1;
        while (childIndex < length) {
            // 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子
            if (childIndex + 1 < length && array[childIndex + 1] >array[childIndex]) {
                childIndex++;
            }
            // 如果父节点大于任何一个孩子的值,则直接跳出
            if (temp >= array[childIndex]) {
                break;
            }
            //无须真正交换,单向赋值即可
            array[parentIndex] = array[childIndex];
            parentIndex = childIndex;
            //下一个左孩子
            childIndex = 2 * childIndex + 1;
        }
        array[parentIndex] = temp;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值