堆排序简单实现

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

 1、创建大根堆,从后往前遍历所有非叶子节点(非叶子节点都有两个子节点),依次调整,得到一个大根堆,条件满足任何一个非叶子节点大于它的两个子节点。

 private void createMaxHeap(int[] arr, int size) {
        for (int i= arr.length / 2 - 1  ; i >= 0 ; i --){
            adjustHeap(arr,i,size);
        }
 }

2、调整堆函数,主要算法,父节点和左右子节点对比,子节点大于父节点,则交换

    /**
     * 堆调整算法逻辑,非叶子节点和左右子节点比较,子节点大于则调整
     */
    private void adjustHeap(int[] arr,int index, int size){
        //左节点
        int left = 2 * index + 1;

        int right = 2 * index + 2;

        int largest = index;

        if(left < size && arr[left] > arr[largest]){
            largest = left;
        }

        if(right < size && arr[right] > arr[largest]){
            largest = right;
        }

        if(largest != index){
            swap(arr,index,largest);
            adjustHeap(arr , largest ,size);
        }
    }

3、交换函数

private void swap(int[] arr , int i ,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
}

全部代码

public void main(){
        int[] arr = {56,36,78,94,13,47,32,51,22,-12,-89,3,23,3,94};
        long startTime = System.currentTimeMillis();
        System.out.println("原始数据排序:" + Arrays.toString(arr));
        heapSort(arr);
        long endTime = System.currentTimeMillis();
        System.out.println("最终数据排序:" + Arrays.toString(arr));
        System.out.println("花费时间:" + (endTime - startTime) + "毫秒");
    }

    /**
     * 堆排序
     * @param arr
     */
    private void heapSort(int[] arr){
        //大根堆长度
        int size = arr.length;
        //创建大根堆
        createMaxHeap(arr , size);
        System.out.println("创建大根堆后:" + Arrays.toString(arr));
        //将堆顶的元素和最后一个互换
        swap(arr,0,size -1);
        //大根堆长度减1,末尾存好堆顶元素就不动了
        size -- ;   
        while (size > 1){
            //调整堆
            adjustHeap(arr,0 ,size);
            System.out.println("调整堆排序后:" + Arrays.toString(arr));
            swap(arr,0,size - 1);
            size -- ;
        }
    }

    /**
     * 创建大根堆,从后往前遍历所有非叶子节点(非叶子节点都有两个子节点),依次调整
     */
    private void createMaxHeap(int[] arr, int size) {
        for (int i= arr.length / 2 - 1  ; i >= 0 ; i --){
            adjustHeap(arr,i,size);
        }
    }

    /**
     * 堆调整算法逻辑,非叶子节点和左右子节点比较,子节点大于则调整
     */
    private void adjustHeap(int[] arr,int index, int size){
        //左节点
        int left = 2 * index + 1;

        int right = 2 * index + 2;

        int largest = index;

        if(left < size && arr[left] > arr[largest]){
            largest = left;
        }

        if(right < size && arr[right] > arr[largest]){
            largest = right;
        }

        if(largest != index){
            swap(arr,index,largest);
            adjustHeap(arr , largest ,size);
        }
    }

    //交换元素
    private void swap(int[] arr , int i ,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

运行代码结果详细解析:

原始数据排序:[56, 36, 78, 94, 13, 47, 32, 51, 22, -12, -89, 3, 23, 3, 94]
创建大根堆后:[94, 56, 94, 51, 13, 47, 78, 36, 22, -12, -89, 3, 23, 3, 32]
调整堆排序后:[94, 56, 78, 51, 13, 47, 32, 36, 22, -12, -89, 3, 23, 3, 94]
调整堆排序后:[78, 56, 47, 51, 13, 23, 32, 36, 22, -12, -89, 3, 3, 94, 94]
调整堆排序后:[56, 51, 47, 36, 13, 23, 32, 3, 22, -12, -89, 3, 78, 94, 94]
调整堆排序后:[51, 36, 47, 22, 13, 23, 32, 3, 3, -12, -89, 56, 78, 94, 94]
调整堆排序后:[47, 36, 32, 22, 13, 23, -89, 3, 3, -12, 51, 56, 78, 94, 94]
调整堆排序后:[36, 22, 32, 3, 13, 23, -89, -12, 3, 47, 51, 56, 78, 94, 94]
调整堆排序后:[32, 22, 23, 3, 13, 3, -89, -12, 36, 47, 51, 56, 78, 94, 94]
调整堆排序后:[23, 22, 3, 3, 13, -12, -89, 32, 36, 47, 51, 56, 78, 94, 94]
调整堆排序后:[22, 13, 3, 3, -89, -12, 23, 32, 36, 47, 51, 56, 78, 94, 94]
调整堆排序后:[13, 3, 3, -12, -89, 22, 23, 32, 36, 47, 51, 56, 78, 94, 94]
调整堆排序后:[3, -12, 3, -89, 13, 22, 23, 32, 36, 47, 51, 56, 78, 94, 94]
调整堆排序后:[3, -12, -89, 3, 13, 22, 23, 32, 36, 47, 51, 56, 78, 94, 94]
调整堆排序后:[-12, -89, 3, 3, 13, 22, 23, 32, 36, 47, 51, 56, 78, 94, 94]
最终数据排序:[-89, -12, 3, 3, 13, 22, 23, 32, 36, 47, 51, 56, 78, 94, 94]
花费时间:4毫秒

原理很简单,每次创建出新堆,堆顶为此时堆的最大值,堆顶和堆尾交换,堆长度减1,重新创建新堆,不断重复,直到堆长度为1结束,此时形成一个升序数组。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值