堆排序

本文深入解析堆排序算法,探讨最大堆和最小堆的概念及其在排序中的应用。通过具体代码实现,展示如何利用最大堆进行升序排序,以及如何利用最小堆进行降序排序,详细解释堆排序的时间复杂度和算法步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前我们了解过最大堆和最小堆

我们知道最大堆的根节点上是数组的最大值,但是子节点的顺序指服从,子节点小于父节点,并没有严格的像二叉搜索树一般

那么今天要说的堆排序就是利用了最大堆和最小堆根的性质所设计的一种排序算法

  • 最大堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;

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

平均时间复杂度:O(NlogN)

算法步骤:

  • 由数组建堆(最大堆或最小堆)

  • 将堆的根节点和最右叶子节点交换位置做一个伪删除

  • 重建堆

  • 反复以上步骤,直到完成排序,最大堆的最小元素上滤到根节点,最小堆的最大元素上滤到根节点

堆排序代码实现:

public class HeapSort {

    /**
     * 堆排序:【最大堆】 --- 升序
     * - 建堆
     * - 删除堆顶
     * - 循环以上两步
     *
     * @param arr
     */
    public void heapSortOfMaxHeap(int[] arr) {
        int len = arr.length;
        //构造最大堆
        buildMaxHeap(arr, len);
        while (len > 1) {
            //取出最大值放于叶子节点,将叶子节点放于根节点
            swap(arr, 0, len - 1);
            //数组长度-1(相当于移除)
            len--;
            //移除了最大值后继续构建最大堆
            heapifyForMaxHeap(arr, 0, len);
        }
    }

    /**
     * 堆排序:【最小堆】 --- 降序
     * - 建堆
     * - 删除堆顶
     * - 循环以上两步
     *
     * @param arr
     */
    public void heapSortOfMinHeap(int[] arr) {
        int len = arr.length;
        buildMinHeap(arr, len);
        while (len > 1) {
            swap(arr, 0, len - 1);
            len--;
            heapifyForMinHeap(arr, 0, len);
        }
    }


    /**
     * 构建最大堆
     *
     * @param arr
     * @param len
     */
    private void buildMaxHeap(int[] arr, int len) {
        for (int i = (int) Math.floor(len / 2); i >= 0; i--) {
            heapifyForMaxHeap(arr, i, len);
        }
    }

    /**
     * 构建最小堆
     *
     * @param arr
     * @param len
     */
    private void buildMinHeap(int[] arr, int len) {
        for (int i = (int) Math.floor(len / 2); i >= 0; i--) {
            heapifyForMinHeap(arr, i, len);
        }
    }

    /**
     * 建堆【建立的是最大堆】
     *
     * @param arr
     * @param i
     * @param len
     */
    private void heapifyForMaxHeap(int[] arr, int i, int len) {
        //每次都是从树根开始下滤
        //左子节点
        int left = 2 * i + 1;
        //右子节点
        int right = 2 * i + 2;
        //执行较大值,父节点
        int largest = i;
        //左子节点在数组内且比父节点大
        if (left < len && arr[left] > arr[largest]) {
            //指向左子节点
            largest = left;
        }
        //右子节点在数组内且比父节点大
        if (right < len && arr[right] > arr[largest]) {
            //指向右子节点
            largest = right;
        }
        //判断是否还在同一位置,不在则需交换
        if (largest != i) {
            swap(arr, i, largest);
            //继续下滤,直到找到合适位置退出
            heapifyForMaxHeap(arr, largest, len);
        }
    }

    /**
     * 构建最小堆
     *
     * @param arr
     * @param i
     * @param len
     */
    private void heapifyForMinHeap(int[] arr, int i, int len) {
        int left = i * 2 + 1;
        int right = i * 2 + 2;
        int largest = i;
        if (left < len && arr[left] < arr[largest]) {
            largest = left;
        }
        if (right < len && arr[right] < arr[largest]) {
            largest = right;
        }
        if (largest != i) {
            swap(arr, i, largest);
            heapifyForMinHeap(arr, largest, len);
        }
    }

    /**
     * 交换函数
     *
     * @param array
     * @param i
     * @param j
     */
    private static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }


    public static void main(String[] args) {
        HeapSort heapSort = new HeapSort();
        int[] a = new int[]{1, 2, 5, 1, 2, 7, 3, 5, 42, 2};
        heapSort.heapSortOfMinHeap(a);
        for (int i : a) {
            System.out.println(i);
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值