首页 > 代码库 > 学习堆排序

学习堆排序

  首先,看一下堆的定义;

  n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。

  情形1:k<= k2i 且k<= k2i+1 最小化堆小顶堆

  情形2:k>= k2i 且k>= k2i+1 (化堆大顶堆

  其中i=1,2,…,n/2向下取整;            

      该排序的思想是;首先建立二叉堆,这个阶段花费O(N)时间,然后我们执行N次deleteMin操作。按照顺序,最小的元素先离开堆,通过将这些元素记录到第二数组,最后在将数组拷贝回来,得到N个元素的顺序,由于每个deleteMIn花费时间O(logN), 因此,总的运行时间是O(NlogN). 优先队列,可以用于O(NlogN)时间排序, 基于该思想的算法叫做堆排序。

     该算法的主要问题是使用一个附加的数组,一次存储需求增加一倍,为了回避使用第二个数组的,可以在每次deleteMin之后,堆缩减1,因此,位于堆中左后的单元,可以存储刚刚存放删除的元素。使用这种策略,该数组将以递减的的顺序包含这些元素.

      java代码的例子:

   

public class HeapSort {

    public static void main(String[] args) throws Exception{
        Integer [] a  = new Integer[]{32,12,345,5,66,23};
        heapSort(a);

        Arrays.stream(a).forEach(System.out::println);
    }

    /**
     * Internal method for heapSort that is used in  deleteMax and buiildHeap
     * @param i the position from which to percolate down
     * @param n the binary size of the binary heap
     */
    public static void percDown(Integer[] a,int i, int n){
        int child;
        int temp;

        for(temp= a[i]; leftChild(i) < n; i = child){
            child = leftChild(i);

            if(child != n-1  && a[child] < a[child+1])
                child++;

            if(temp < a[child])
                a[i] = a[child];
            else
                break;
        }
         a[i] = temp;
    }


    private static int leftChild(int i){
        return 2 * i + 1;
    }

    public static void heapSort(Integer[] a){

        /**初始化堆的时候是对所有的非叶子结点进行筛选。
        最后一个非终端元素的下标是[n/2]向下取整,所以筛选只需要从第[n/2]向下取整个元素开始,从后往前进行调整。
         */
        for(int i = a.length/2-1; i>=0; i--){ //buildHeap
            percDown(a,i,a.length);
        }

        for(int i=a.length-1; i > 0; i--){
            swapReferences(a,0,i);  //deleteMax
            percDown(a,0,i);
        }
    }

    //deleteMax
    public static void swapReferences(Integer[] a, int i, int n){
        Integer temp=a[i];
        a[i] = a[n];
        a[n] = temp;
    }

}

  堆排序方法对记录数较少的文件并不值得提倡,但对n较大的文件还是很有效的。因为其运行时间主要耗费在建初始堆和调整建新堆时进行的反复“筛选”上

  堆排序在最坏的情况下,其时间复杂度也为O(nlogn)。相对于快速排序来说,这是堆排序的最大优点。

  

   

        

  

     

    

         

   

学习堆排序