堆排序

标签: 数据结构与算法

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图:
  在这里插入图片描述
同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子
在这里插入图片描述
该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

堆排序基本思想及步骤

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

示例代码:

package Sort;

import java.util.Arrays;

/**
 * @Auther: wj
 * @Date: 2020/2/6
 * @Description: 最大堆排序
 * @version: 1.0
 */
public class HeapSort {

    public static void main(String[] args){
        int[] arr={2,1,7,9,5,4};
        for(int i=0;i<arr.length;i++){
            maxHeapify(arr,arr.length-i);//arr.length-i 表示每次最大值存贮在数组最后一位
            //由于是最大堆排序,每次全数组排序后,最大值都在arr[0]
            int temp=arr[0];
            arr[0]=arr[arr.length-i-1];
            arr[arr.length-i-1]=temp;
        }
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 一次全数组的堆排序
     * @param arr 待排序数组
     * @param size 数组大小
     */
    public static void maxHeapify(int[] arr,int size){
        for(int i=size-1;i>=0;i--){
            Heapify(arr,i,size);
        }
    }

    /**
     * 堆排序(父与子之间)
     * @param arr 待排序数组
     * @param root 根节点
     * @param size 数组大小
     */
    public static void Heapify(int[] arr,int root,int size){
        int left=2*root+1;//左孩子
        int right=2*root+2;//右孩子
        int max=root;//假设最大值为根节点

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

        if(right<size){
            if(arr[right]>=arr[max]){
                max=right;
            }
        }
        //最大值不是根元素,就交换
        if(root!=max){
            int temp=arr[root];
            arr[root]=arr[max];
            arr[max]=temp;
        }
        //叶子节点,直接返回上一层
        if(root==max) return;
        //当前父子节点比较完成,继续比较
        Heapify(arr, max, size);

    }

















   /* public static void main(String[] args) {
        int[] arr={2,1,8,9,5,4};
        //每次彻底堆排序后,最大元素在前,排除一个元素size-1
        for(int i=0;i<arr.length;i++){
            maxHeapify(arr,arr.length-i);
            //彻底一次排序后,最大值arr[0]与最后元素进行交换
            int temp=arr[0];
            arr[0]=arr[(arr.length-1)-i];
            arr[(arr.length-1)-i]=temp;
        }
        System.out.println(Arrays.toString(arr));
    }

    *//**
     * 一次彻底的堆排序,可以找出当前数组最大值
     * @param arr 排序数组
     * @param size 需要排序数组大小
     *//*
    public static void maxHeapify(int[] arr,int size){
        for(int i=size-1;i>=0;i--){
            heapify(arr,i,size);
        }
    }

    *//**
     * 堆排序(一次父与子)
     * @param arr 排序数组
     * @param root 当前父节点
     * @param size 数组大小(判断是否还存在子节点)
     *//*
    public static void heapify(int[] arr,int root,int size){
        //如果当前父节点存在
        if(root<size){
            int left=2*root+1;//左孩子
            int right=2*root+2;//右孩子
            //默认当前节点为最大值
            int max=root;

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

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

            //最大值不是根元素,就交换
            if(max!=root){
                int temp=arr[root];
                arr[root]=arr[max];
                arr[max]=temp;
            }

            // 只存在当前节点。没有叶子节点存在-->结束递归条件
            if(max==root) return;

            //当前父子节点比较完成,完成下一次比较
            heapify(arr, max, size);
        }

    }*/
}

参考思路:堆排序

原文链接:加载失败,请重新获取