最簡單,最直接的講述堆排序
一、什麼是堆,何來堆排序呢?
堆是一顆完全二叉樹,且父節點必須大於子節點。什麼叫完全二叉樹呢,完全二叉樹指的是前面n個節點都是滿二叉樹中的節點換句話說就是完全二叉樹的子節點必須處於樹的最後兩行,且是從左到右的順序。
二、堆排序的基本思想
通過對堆的調整得到根節點,因為調整後的根節點是整棵樹最大的,這樣就得到了此時的最大值,這時將這個根節點下標識陣列第乙個數,所以將其與最後乙個數交換位置,這樣,得到了第乙個最大值,以此類推,可以得到一列數的順序。這樣得到的是最大推,當然也存在最小堆了,道理是一樣的,只是父節點都小於子節點罷了。很多書上寫的都是最大堆,我來寫最小堆吧。
1、 在這裡我們可以看到以陣列為10 的例子來講,首先這是一顆完全二叉樹,但還不是堆,此時我們需要滿足對的條件,那麼我們需要子節點小於父節點那麼這樣才是乙個堆。
2、我們通過對這個原理掃瞄一趟可以看到所有的父節點大於子節點,這樣會出現乙個問題,是什麼問題呢,我們會驚人的發現在根節點的數大於任何乙個節點的數這樣我們就得到了這個陣列中的最大值。按此結論我們可以通過10次迴圈可以不斷的得到倒數第二大的數,倒數第三大的數以此類推,可以得到這個陣列的順序。
3、這裡我們先需要解決乙個問題,構建堆,第一次掃瞄我們知道了最大值,我們對剩餘的數再建堆就可以得到第二大的數,我們可以放與陣列的最後一這位交換位置,直到所有數都排序完畢。這個堆必須從底層向上掃瞄,因為我們知道做節點left = 2*i+1,右節點right = 2*i+2這樣的話,必須從陣列的最後向前掃瞄。我們通過遞迴呼叫我們的建堆就可以得到所有的父節點大於子節點直到根節點為當前的最大數。
4、這裡最關見的乙個問題是:我們必須在乙個父節點,兩個子節點中得出最大的值並交換位置,這樣我們做遞迴呼叫就可以實現對整棵樹的掃瞄。
關鍵步驟:
第一步是要得到乙個子節點與父節點中的最小的然後交換得到父節點為此節點中最小的。
**:
//建立堆的交換操作實現調整
/***@param int a表示陣列
*@param int pos 表示比較的位置,可理解為父節點的下標
*@param int max 表示陣列長度
*@return 無
*/int heapadjust(int a,int pos,int maxlength)
if(right=a[right])
if(p != pos )
}else
cout<
第三步是堆的排序,將得到的根節點中的最小值放入對應的陣列中。
**:
//用來排序的將每一次得到的最小值進行排序/***@param int a 用來接收要排序的陣列
*@param int maxlength 表示陣列的長度
*@return int
*/void heap_sort(int a,int maxlength)
if(right=a[right])
if(p != pos )
}else
cout<
getheap(a,i+1);//此處i+1是為了保持陣列的長度不變
temp = a[0];
a[0]=a[i];
a[i] =temp;
count++;
cout<
cout <
排序系列 堆排序
1 堆排序定義 n個關鍵字序列kl,k2,kn稱為堆,當且僅當該序列滿足如下性質 簡稱為堆性質 1 ki k2i且ki k2i 1 或 2 ki k2i且ki k2i 1 1 i 若將此序列所儲存的向量r 1.n 看做是一棵完全二叉樹的儲存結構,則堆實質上是滿足如下性質的完全二叉樹 樹中任一非葉結點...
排序系列 堆排序
排序系列 堆排序.cpp 定義控制台應用程式的入口點。說明 堆排序其實是對簡單選擇排序的一種改進演算法,因為簡單的選擇排序在每次比較時沒有儲存上一趟比較的結果 導致對前一趟做過的比較有重複了一次,這樣就會大大降低效率,而堆排序就可以儲存每次的比較結果 在vs2010上編譯通過 堆排序思想 堆是具有以...
堆排序《一》 簡單結構堆排序
堆排序 利用最大堆 最小堆完成排序 用陣列儲存,但邏輯結構為 完全二叉樹 heapelem arr 物理結構 邏輯結構 i 3 要調整的結點 j i 2 1 左孩子結點 對 3 7 8 進行判斷,已符合最小堆規則 則不調整 break arr i tmp pos 開始迴圈調整 2位置的 while ...