【算法】堆排序以及應用

一、堆性質

n個關鍵字序列k1,k2,.........kn當且僅當滿足一下性質是爲一個堆

  • k[i]<=k[2i]
  • k[i]<=k[2i+1](1≤i≤ n/2)
以上是小頂堆的定義,大頂堆則相反吧<=改爲大於等於即可。若將堆看成一顆二叉樹,那麼則樹中任一非葉子結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。

1、堆的構建

找到第一個非葉子節點,根據大頂堆或者小頂堆的性質進行調整,當前以及其左右子節點比較。
注意,被調整的節點,還有子節點的情況,需要遞歸進行調整。

2、堆的插入

插入節點時,先插入到最後,然後再調整堆

3、堆的刪除

刪除最小節點即刪除根節點,先將根節點和最後一個節點交換,再調整堆。

二、堆排序

堆排序(Heapsort)是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。可以利用數組的特點快速定位指定索引的元素。堆分爲大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在數組的非降序排序中,需要使用的就是大根堆,因爲根據大根堆的要求可知,最大的值一定在堆頂。

package Sort;

/**
 * Created by LemonTree on 2017/4/5.
 */
public class HeapSort {

    /**
     * 調整堆
     * @param array  原始堆
     * @param index  調整位置
     * @param heapSize 堆大小
     */
    public static void adjustHeap(int[] array,int index, int heapSize){
        int left = 2*index+1;
        int right = 2*index+2;
        int largest = index;
        if(left<heapSize && array[index]<array[left])
            largest = left;
        if(right<heapSize && array[largest]<array[right])
            largest = right;
        if(largest!=index) {
            int temp = array[largest];
            array[largest] = array[index];
            array[index] = temp;
            adjustHeap(array, largest, heapSize); //遞歸調整
        }
    }

    /**
     * 建立堆
     * @param array  待建堆序列
     */
    public static void buildHeap(int array[]){
        for(int i=array.length/2-1;i>=0;i--){
            adjustHeap(array,i,array.length); //如看成完全二叉樹,那麼則從樹的第一個非葉子節點進行調整,順序爲array.length/2-1 ------>0,從後向前
        }
    }

    /**
     * 堆排序
     * @param array  堆排序
     */
    public static void sort(int[] array){
        buildHeap(array);
        for(int i=array.length-1;i>=0;i--){
            int temp = array[0];
            array[0] = array[i];
            array[i] = temp;
            adjustHeap(array,0,i);          //每次堆的大小遞減
        }
    }

    public static void main(String[] args) {
        int[] array={9,3,4,6,1,2,3,45,6};
        sort(array);
        for(int num:array){
            System.out.print(String.valueOf(num)+"  ");
        }

    }
}

三、應用

題目:從1億個數中求出最大的前100個數。

思路:建立一個100元素的小頂堆,每次從剩下的數裏面取插入,如果比堆頂小則不比較,如果比堆頂大則相比較調整堆。大頂堆雖然也可以,但是浪費了堆的性質,不能像小頂堆一樣減少比較的次數。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章