堆的应用----堆排序

  • 堆排序 : 核心就是不断查询最大的元素 然后放到数组尾部即可

    • 把数组堆化(大顶堆) 此时根节点就是最大的元素
    • 把根节点值和数组最后一个元素进行替换 此时最大值就在末尾(之后进行替换时需要倒叙挨个往前替换)
    • 对于替换后的堆 已经不满足大顶堆的定义 对其再次堆化 (注意 : 这里堆化时不包含已经替换到数组末尾的元素)
    • 堆化完成后 根节点是最大元素 然后循环执行上面的步骤 直到最后一个元素
  • 看如下例子 目前是一个已经堆化数组

在这里插入图片描述

  • 替换首尾元素
    在这里插入图片描述
    在这里插入图片描述

  • 由于此时已经不满足堆的定义 再次进行堆化
    在这里插入图片描述

  • 堆化后 进行元素替换
    在这里插入图片描述
    在这里插入图片描述

  • 堆化
    在这里插入图片描述

  • 依次执行如上步骤 最终结果如下
    在这里插入图片描述

  • 将其放到数组后如下 注意 下标为0的位置为空 更节从下标为1的3开始 发现排序完成
    在这里插入图片描述

2. 数组图示

在这里插入图片描述

3. 代码实现
import java.util.Arrays;

public class HeapSort {

    public static void main(String[] args) {
        int[] array = {8,6,5,9,2,10,3,1,15,22,22};
        int[] sort = sort(array);
        System.out.println(Arrays.toString(sort));
    }

    /**
     * 排序方法 : 注意这里的核心是吧最大的元素放到数组最后面(就是一个在不断查询最大值的操作)
     *      1.把堆化后的数组 根节点元素(最大的)和数组最后一个元素替换 此时堆顶元素不是最大值不满足大顶堆
     *      2.需要重新进行堆化 有点类似于删除顶元素的操作
     *      3.如此循环一下 就把最大的元素都依次放到了数组进行倒叙遍历的位置上
     *      4.完成排序
     * @param array
     */
    public static int[] sort(int[] array){
        int[] heapArray = array2Heap(array);//堆化数组
        int n = heapArray.length - 1;
        while (n > 0) {//当n<0时 说明数组已经遍历结束 即已经排序完成
            //把堆顶元素和数组最后元素替换 没替换一次 进行n--操作 下一次就替换倒数第二个
            // 以此类推 当最后一个元素替换完成后 则排序完成
            swap(heapArray,1,n--);
            //交换后需要进行一次堆化操作
            //注意堆化的最后一个元素也要进行--操作 因为此时最大的元素已经在最后面 所以无需在进行操作
            bigHeapDate2high(heapArray,1,n);
        }
        //由于之前堆化时 做了一个从1开始索引元素 现在 排序完成 在复制为从0开始
        System.arraycopy(heapArray,1,array,0,array.length);
        return array;
    }

    /**
     * 把数组堆化方法 这里使用大顶堆
     * @param array 堆化数组
     */
    public static int[] array2Heap(int[] array) {
        //把原数组复制到一个新数组  令其元素从1开始
        int[] copy = new int[array.length + 1];
        System.arraycopy(array,0,copy,1,array.length);
        int endIndex = copy.length - 1;//数组最后一个元素下标
        //endIndex / 2 : 获取到最后一个节点的父节点下标
        for (int i = endIndex / 2; i > 0; i--) {
            bigHeapDate2high(copy, i, endIndex);
        }
        return copy;
    }

    /**
     * 堆化为大顶堆
     *
     * @param data
     * @param beginIndex 替换后的节点索引
     * @param endIndex   结束位置索引
     */
    public static void bigHeapDate2high(int[] data, int beginIndex, int endIndex) {
        int left,right;
        while (true) {//当前元素下标小于总元素个数时 进行替换操作
            //判断节点和左子树大小且左子树值要小于右子树值时  大于就替换位置
            if ((left = 2 * beginIndex) <= endIndex
                    && data[beginIndex] < data[left]
                    && ((right = 2 * beginIndex + 1) > endIndex ? true : data[left] > data[right])) {
                swap(data, beginIndex, left);
                beginIndex = left;
            } else if ((right = 2 * beginIndex + 1) <= endIndex && data[beginIndex] < data[right]) {
                //否则判断节点和右子树大小  大于就替换位置
                swap(data, beginIndex, right);
                beginIndex = right;
            }else {
                break;
            }
        }
    }

    //替换元素位置
    public static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值