排序算法8-堆排序

描述

该算法将序列构建成大(小)顶堆,即完全二叉树,每次构建大小顶堆后,产出目前序列的最大最小值,逐步完成排序

流程

1、首先将待排序列构建成完全二叉树,从该数非叶子节点开始构建大顶堆
2、构建完成后,最大的元素是二叉树的根节点(序列头),将根节点和最后一个叶子节点(序列尾)交换位置,放置在序列最右,作为有序组
3、将剩下的无序组继续流程1、2,直至排序结束

代码实现

/**
 * 堆排序
 */
public class HeapSort {

    public static void main(String[] args) {
        int[] arr = {50, 10, 90, 30, 70, 40, 80, 60, 20};
        System.out.println("排序前: " + Arrays.toString(arr));
        heapSort(arr);
        System.out.println("排序后: " + Arrays.toString(arr));
    }

    /**
     * 堆排序
     */
    private static void heapSort(int[] arr) {
        // 从堆的底部(即数组的尾部)开始构建大顶堆,但底部都是叶子节点,无构建意义
        // 因此从堆的非叶子节点开始构建,即n/2处开始构建
        for (int i = arr.length / 2; i >= 0; i--) {
            heapAdjust(arr, i, arr.length);
        }

        // 逐步将每个最大值的根节点与末尾元素交换,并且再调整二叉树,使其成为大顶堆
        for (int i = arr.length - 1; i > 0; i--) {
            // 将堆顶记录和当前未经排序子序列的最后一个记录交换
            swap(arr, 0, i);
            // 交换之后,需要重新检查堆是否符合大顶堆,不符合则要调整
            heapAdjust(arr, 0, i);
        }
    }

    /**
     * 构建堆的过程
     *
     * @param arr 需要排序的数组
     * @param i   需要构建堆的根节点的序号
     * @param n   数组的长度
     */
    private static void heapAdjust(int[] arr, int i, int n) {
        int child;
        int father;
        for (father = arr[i]; leftChild(i) < n; i = child) {
            child = leftChild(i);

            // 如果左子树小于右子树,则需要比较右子树和父节点(即从子节点中调出最大的和父节点比较)
            if (child != n - 1 && arr[child] < arr[child + 1]) {
                child++; // 序号增1,指向右子树
            }

            // 如果父节点小于孩子结点,则需要交换
            if (father < arr[child]) {
                arr[i] = arr[child];
            } else {
                break; // 大顶堆结构未被破坏,不需要调整
            }
        }
        arr[i] = father;
    }

    // 获取到左孩子结点
    private static int leftChild(int i) {
        return 2 * i + 1;
    }

    // 交换元素位置
    private static void swap(int[] arr, int index1, int index2) {
        int tmp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = tmp;
    }
}

性能

和归并排序一样,最坏、最好、平均时间复杂度都是O(nlogn)

由于都是在本序列进行排序交换,所以它的空间复杂度是O(1)

它是不稳定的排序算法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值