算法(四):堆排序的思考

  1. 堆排序
    堆排序(heapsort)是一種樹形選擇排序,是對直接選擇排序的有效改進。
    直接選擇排序:數據直接進行比較置換,第一個位置保存最小值,依此類推排序。簡單代碼如下:
for(int i=0;i<d.length-1;i++)  {  
    int min=d[i],tmp; //記錄第i位置 
    for(int j=i+1;j<d.length;j++) { //與i後的所有數據比較 
        if(d[j]<min){tmp=d[j];d[j]=min;min=tmp;}//置換(不穩定)
    d[i]=min;//得到n-i個元素中最小的元素
}

基本的思考:
堆排序是把序列看作是一棵順序存儲的二叉樹(一維數組存儲二叉樹),調整存儲序,使之成爲一個堆,將堆頂元素輸出,得到n 個元素中最小(或最大)的元素。依此類推。
列出問題:
①如何將n 個待排序的數建成堆;
②輸出堆頂元素後,怎樣調整剩餘n-1 個元素,使其成爲一個新堆。

    int[] data = {81,94,11,96,12,35,17,95,28,58,41,75,15};
    //大頂堆
    public static void heapSort(int[] d) {
        //建堆
        for(int i=(d.length-1)/2;i>=0;i--) {
            heapSortBig(d,i,d.length);
        }
        //輸出堆頂
        int tmp;
        for(int i=d.length-1;i>0;i--) {
            //交換堆頂元素和堆中最後一個元素
            tmp =d[i];d[i]=d[0];d[0]=tmp;
            //每次交換堆頂元素和堆中最後一個元素之後,重建堆
            heapSortBig(d,0,i);//d[i]=11 12 15 17 ...
        }
        //打印排序結果(大頂堆從小到大排序)
        for(int a:d) {
            System.out.print(" "+a);
        }       
    }
public static void heapSortBig(int[] array, int s, int length) {
        int tmp = array[s];//堆頂
        int child = 2 * s + 1;// 左孩子結點的位置
        while (child < length) {
          // child + 1 是當前調整結點的右孩子
          // 如果有右孩子且小於左孩子,使用右孩子與結點進行比較,否則使用左孩子
          if (child + 1 < length && array[child] > array[child + 1]) {
            child++;
          }
          // 如果較小的子孩子比此結點小
          if (array[s] > array[child]) {
            array[s] = array[child];// 把較小的子孩子向上移動,替換當前待調整結點
            s = child;// 待調整結點移動到較小子孩子原來的位置
            array[child] = tmp;
            child = 2 * s + 1;// 繼續判斷待調整結點是否需要繼續調整
          } else {
            System.out.println("子孩子均比其大,調整結束");
            break;// 當前待調整結點小於它的左右孩子,不需調整,直接退出
          }
        }
    }

思考:
基礎:第一階段構建堆最多用到2N次比較。第二階段比較最多是2NlogN-O(N)次了。 是個非常穩定的算法。

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