堆排序

首先介绍一下堆。堆是优先队列的一种实现方式(使用完全二叉树来实现),而完全二叉树可以通过数组来存储,因此堆的底层是一个数组。一个数组经过调整关键字顺序形成了堆。
堆排序的基本思路(以最大堆为例):
(1)建堆。将数组进行多次调整形成一个堆。
(2)将堆顶元素移至数组末尾,剩余元素继续调整形成新的堆。
(3)重复步骤(2)直到堆为空。这样首先是最大的数放在了末尾,接着是次大的数,以此类推。
因为元素组下标从0开始,所以根节点下标为0。有:i结点的左孩子2i+1,右孩子2i+2, index结点的父亲:(index-1)/2。

堆调整操作

adjust是一个调整操作,它将当前节点调整到合适的位置。最终以当前节点为根的子树是一个堆。

    //堆调整操作,用于建堆
    //cur为当前节点位置,n为当前堆中的元素个数-1
    public static void adjust(int[]a,int cur,int n){
        int temp=a[cur];
        for(int i=cur*2+1;i<=n;i=2*i+1){
            if(i<n&&a[i]<a[i+1]) i++;
            if(a[i]<=temp) break;
            a[cur]=a[i];
            cur=i;
        }
        a[cur]=temp;
    }

建堆和排序

 public static void heapSort(int[] a){
        int n=a.length-1;
        //将元素组构建为堆
        //最后一个节点下标为n,最后一个非叶节点下标为(n-1)/2。
        for(int i=(n-1)/2;i>=0;--i) adjust(a,i,n);

        for(int i=n;i>0;--i){
            //堆中剩余元素的最大值放到数组尾部。
            //完全二叉树的最后一个节点移至堆顶。
            int temp=a[i];
            a[i]=a[0];
            a[0]=temp;
            //根节点的左右子树均为堆,将根节点调整到适当位置后,整棵树仍然是一个堆。
            adjust(a,0,i-1);
        }
 }

时间复杂度

时间复杂度为O(nlogn),由建堆的过程决定。

原文地址:https://www.cnblogs.com/Frank-Hong/p/14039964.html