1. 程式人生 > 其它 >【資料結構與演算法】堆排序

【資料結構與演算法】堆排序

堆排序

  作為選擇排序的改進版,堆排序可以把每一趟元素的比較結果儲存下來,以便我們在選擇最小/大元素時對已經比較過的元素做出相應的調整。

      堆排序是一種樹形選擇排序,在排序過程中可以把元素看成是一顆完全二叉樹,每個節點都大(小)於它的兩個子節點,當每個節點都大於等於它的兩個子節點時,就稱為大頂堆,也叫堆有序; 當每個節點都小於等於它的兩個子節點時,就稱為小頂堆。                                                                大頂堆                                                                                                              小頂堆
     演算法思想(以大頂堆為例):
  1. 將長度為n的待排序的陣列進行堆有序化構造成一個大頂堆
  2. 將根節點與尾節點交換並輸出此時的尾節點
  3. 將剩餘的n -1個節點重新進行堆有序化
  4.  重複步驟2,步驟3直至構造成一個有序序列

 構造堆

假設待排序陣列為[20,50,10,30,70,20,80]   在構造有序堆時,我們開始只需要掃描一半的元素(n/2-1 ~ 0)即可,為什麼? 因為0 ~(n/2-1)的節點才有子節點,如圖1,n=8, (n/2-1) = 3  即0、1、2、3、4這個四個節點才有子節點。                     (圖1:初始狀態)   第一次for迴圈將節點3和它的子節點7 8的元素進行比較,最大者作為父節點(即元素60作為父節點)【紅色表示交換後的狀態
】     第二次for迴圈將節點2和它的子節點5 6的元素進行比較,最大者為父節點(元素80作為父節點)     第三次for迴圈將節點1和它的子節點3 4的元素進行比較,最大者為父節點(元素70作為父節點)     第四次for迴圈將節點0和它的子節點1 2的元素進行比較,最大者為父節點(元素80作為父節點)   (注意這裡,元素20和元素80交換後,20所在的節點還有子節點,所以還要再和它的子節點5 6的元素進行比較,這就是28行程式碼 i = j 的原因)   至此有序堆已經構造好了!如下圖:       調整堆 下面進行while迴圈 (1)堆頂元素80和尾40交換後-->調整堆   (2)堆頂元素70和尾30交換後-->調整堆   (3)堆頂元素60尾元素20交換後-->調整堆   (4)其他依次類推,最終已排好序的元素如下: