堆排序怎麼建立初始堆 學習筆記 詳解堆排序

2021-10-18 02:00:11 字數 1917 閱讀 9328

堆排序(英語:heapsort)是指利用堆這種資料結構所設計的一種排序演算法。堆是乙個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。

堆(heap)是電腦科學中一類特殊的資料結構的統稱。堆是一種非線性結構。可以把堆看作乙個陣列,也可以被看作乙個完全二叉樹,通俗來講堆其實就是利用完全二叉樹的結構來維護的一維陣列。此處用到的堆一般是指大頂堆或小頂堆。

大頂堆

每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆。如下圖所示。

小頂堆

每個結點的值都小於或等於其左右孩子結點的值,稱為小頂堆。如下圖所示。

將待排序序列構造成乙個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。然後將剩餘n-1個元素重新構造成乙個堆,這樣會得到n個元素的次小值,如此反覆執行,便能得到乙個有序序列了。需要注意的是建立大頂堆時是從最後乙個非葉子節點開始從下往上調整的。

1. 建立乙個堆 r[0……n-1];

2. 把堆首(最大值)和堆尾互換;

3. 把堆的尺寸縮小 1(已經有序的部分不進入下一輪);

4. 重複步驟 2,直到堆的尺寸為 1。

操作過程如下:

1,初始化堆:將r[1..n]構造為堆;

2,將當前無序區的堆頂元素r[1]同該區間的最後乙個記錄交換,然後將新的無序區調整為新的堆。

#include  #define elemtype int /*元素型別*/int k=1;//輪次記錄 //列印函式 void print (elemtype arr, int len)else    }} //排序   void sort(elemtype a, int len)         for (i = len - 1; i > 0; i--)     }int main() ;    printf("待排序的序列為:");    print(arr, 9);      printf("");        sort (arr,9);    printf("");    printf("排好序的結果如下:");    print(arr, 9);       }

時間複雜度堆排序的執行時間主要是消耗在構建堆和在重建堆時的反覆篩選上。在構建堆的過程,因為我們是從完全二叉樹最下層的非葉子結點開始構建的,將它與其孩子結點進行比較和有必要的互換,對於每個非葉子結點來說,其實最多2次比較和互換,故初始化堆的時間複雜度為o(n)。在正式排序的時候,第i次取堆頂記錄和重建堆需要o(logi)的時間(完全二叉樹的某個結點到根結點的距離為log2i+1),並且需要取n-1次堆頂記錄,因此重建堆的時間複雜度為o(nlogn)。所以總的來說,堆排序的時間複雜度為o(nlogn)。由於堆排序對元素記錄的排序狀態不敏感,因此它無論最好,最壞,和平均時間複雜度均為o(nlogn)。

空間複雜度

堆排序中只有交換元素時需要1個輔助空間,與問題規模無關,空間複雜度為o(1)。

排序穩定性

在構建堆的過程中無法保證相同值構建前後的相對位置,所以堆排序是不穩定的。

堆排序建立初始堆

假設我們有乙個陣列int a 如果把這個陣列看作是完全二叉樹的順序儲存,那麼它對應圖1 1 a 完全二叉樹。所謂最大堆就是a i a 2i 1 且a i a 2i 2 i在此處對應0 5 這個描述即第四步的結果。也就是說我們把陣列a經過4步調整,最終構建出了它的最大堆,如圖1 1 d 另外需要說明的...

堆排序之建初始堆

在牛客網上看到一道題 答案是c,但是之前只接觸插入法建堆,沒了解篩選法建初始堆,於是網上衝浪,查詢了一波解析,於是有了現在這個思路總結 看半天也沒有看到比較靠譜的 然後總結了一下,按照這種思路,能得到c答案,但仍然存在一點疑惑 初始堆難道不應該是大頂堆或者小頂堆嘛,這結果也不是呀,還是說,有什麼定義...

《演算法導論》學習筆記(1) 堆與堆排序

堆排序 heapsort 是指利用 堆 這種資料結構 所設計的一種排序演算法 堆是一種資料結構,是乙個陣列。它可以被看成乙個近似的完全二叉樹,樹上的每乙個結點對應陣列中的乙個元素。除了最底層外,即葉子結點,該樹是完全充滿的,而且是從左到右填充。最大堆的每個結點都要滿足堆的性質,此外還有其他的約束 堆...