堆排序讲解及Java实现

堆排序

一、首先先解释一下什么是堆?

堆可以看做是一颗树,而且是一颗完全二叉树。不同的二叉树请看下图:
各种树

二、堆排序的特性
首先介绍复杂度:
时间复杂度:O(nlgn)…
空间复杂度:O(1)
鉴于堆这种数据结构本身的特性可以发现(以最大堆为例),根节点为数组中最大元素,左右子节点小于等于根节点。
另外,假设某个元素为序号为i(Java数组从0开始,i为0到n-1), 如果它有左子树,那么左子树的位置是2i+1,如果有右子树,右子树的位置是2i+2,如果有父节点,父节点的位置是(n-1)/2取整。

三、堆排序步骤
堆排序主要分为两步:
1. 根据数组构建一个堆
2. 排序

直接上代码

public class HeapSort {
    static int N = 0;
    public static void main(String[] args) {
        int array[]={5,1,3,11,2,6,7,8,4,9,10,12};
        N = array.length;
        printArray(array);
        buildHeap(array);

        sort(array);
    }

    private static void sort(int[] array) {
        System.out.println("开始排序...");
        for(int i=N-1;i>=1;i--){
            exch(array,0,i);//交换根元素和尾元素
            adjustHeap(array,i,0);
        }
        System.out.println("排序完毕!结果如下:");
        printArray(array);
    }

    private static void buildHeap(int[] array) {
        System.out.println("开始构建堆...");
        //构建堆
        for(int i=(array.length-1)/2;i>=0;i--){
            //从最后一颗子树开始
            adjustHeap(array,array.length,i);
        }
        System.out.println("堆构建完毕!结果如下:");
        printArray(array);
    }

    private static void printArray(int[] array) {
        for(int n:array){
            System.out.print(n+",");
        }
        System.out.println("");
    }

    /**
     * Parent = (k-1)/2
     * Left = 2i+1;
     * Right = 2i+2;
     * @param a 数组
     * @param k 下标
     */
    private static void adjustHeap(int[] a,int length,int k){
        while(2*k+2 <= length ){
            int left = 2*k+1;
            int max = left;
            if(left + 1 < length){
                int right = left+1;

                if(less(a,left,right)){
                    max = right;
                }
            }

            if(less(a,max,k)){
                break;
            }

            exch(a,k,max);
            printArray(a);
            k = max;
         }

  }

    private static boolean less(int[] a,int i,int j){
        return a[i]<a[j];
    }

    private static void exch(int[] a,int i,int j){
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }

}

以上就是堆排序的Java实现代码,基本思想就是先构建堆,从最后一个子树开始逐一构建;当堆构建完毕之后,基于最大堆的特性,把根元素和最后一个未排序的元素互换,交换完毕后再重新构建堆。

注:如果想要倒序排列数组,则需要构建最小堆,把代码中的less方法修改成>即可。

发布了61 篇原创文章 · 获赞 9 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/fly_yuge/article/details/51305658