排序算法之堆排序

完全二叉树

在这里插入图片描述

描述

当前层数是满的情况下是从左至右的没满的情况下也是从左至右的,不能出现中间空,右边有值的情况

如果把数组的值放入这颗完全二叉树中这里面的数字就是数组的下标

计算: 左子集 i * 2 + 1 右子集 i * 2 + 2 父级 (i - 1) / 2

大根堆

每个节点的头节点都是最大值

小根堆

每个节点的头节点都是最小值

堆排序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BPWgGboo-1657527409833)(Java数据结构与算法.assets/image-20220322104028007.png)]

描述

我们了解完堆完后可以开始操作堆排序流程了,让一个数组组成一个堆结构,使用下面代码中的heapInsert方法可以实现,完成后,我们每次把最后一元素和堆根进行交换然后让最后一个元素断开堆关联(heapSize - 1)并调用heapify再次形成大根堆,因为大根堆的特性堆根一定是最大的数字,然后再heapify就能让他再次形成大根堆,重复操作,我们就发现我们的数组就是有序的了,因为每次都把最大数放入了数组最后一个位置

package com.yuan.struck_data.sort;

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

    /**
     * 堆排序
     *
     * @param arr 整型数组
     */
    public static void heapSort(int[] arr) {
        // 捣乱数据
        if (arr == null || arr.length < 2) {
            return;
        }
        // 先插入到堆中让他成为大根堆
        for (int i = 0; i < arr.length; i++) {
            heapInserter(arr, i);
        }
        // 获取堆大小
        int heapSize = arr.length;
        // 循环
        while (heapSize > 0) {
            // 每次最后一个换到最前面并取消堆关联
            swap(arr, --heapSize, 0);
            // 是否可以下移
            heapify(arr, 0, heapSize);
        }
    }


    /**
     * 添加
     *
     * @param arr   数组
     * @param index 插入的数字下标
     */
    public static void heapInserter(int[] arr, int index) {
        // 循环向上对比
        while (arr[index] > arr[(index - 1) / 2]) {
            // 交换
            swap(arr, index, (index - 1) / 2);
            // 当前数字下标
            index = (index - 1) / 2;
        }
    }

    /**
     * 是否可以下移
     *
     * @param arr      数组
     * @param index    插入的数字
     * @param heapSize 二叉树大小
     */
    public static void heapify(int[] arr, int index, int heapSize) {
        // 先拿到左节点
        int leftChildIndex = index * 2 + 1;
        // 不能越界
        while (leftChildIndex < heapSize) {
            // 右节点也不能越界
            int point = leftChildIndex + 1 < heapSize && arr[leftChildIndex] < arr[leftChildIndex + 1] ? leftChildIndex + 1 : leftChildIndex;
            //
            point = arr[point] > arr[index] ? point : index;
            // 如果当前最大是当前index
            if (point == index) {
                break;
            }
            // 交换
            swap(arr, point, index);
            // 更新下标
            index = point;
            // 再次计算左子节点下标
            leftChildIndex = index * 2 + 1;
        }
    }

    /**
     * 交换
     *
     * @param arr 整型数组
     * @param L   左index
     * @param R   右index
     */
    public static void swap(int[] arr, int L, int R) {
        int temp = arr[L];
        arr[L] = arr[R];
        arr[R] = temp;
    }

    // 测试方法
    public static void main(String[] args) {
        int[] arr = {9, 8, 7, 0, 3, 2, 6};
        heapSort(arr);
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

我是本期小编⚪⚪
遇到Bug需要帮助,
欢迎加wx:
xmzl1988
备注"csdn博客“
温馨提示此为有偿服务;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值