排序演算法之堆排序

2021-06-21 10:46:21 字數 1887 閱讀 9287

前言:今天我來介紹下堆排序,在寫堆排序**之前,我們要知道堆的概念!

堆的定義:n個關鍵字序列kl,k2,…,kn稱為(heap),當且僅當該序列滿足如下性質(簡稱為堆性質):

(1)ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n),當然,這是小根堆,大根堆則換成》=號。//k(i)相當於二叉樹的非葉子結點,k(2i)則是左子節點,k(2i+1)是右子節點

若將此序列所儲存的向量r[1..n]看做是一棵完全二叉樹的儲存結構,則堆實質上是滿足如下性質的完全二叉樹:

樹中任一非葉子結點的關鍵字

均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。

堆的分類:

1).大根堆和小根堆:根結點(亦稱為堆頂)的

關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。

2).根結點(亦稱為堆頂)的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。

注意:①堆中任一子樹亦是堆。②以上討論的堆實際上是二叉堆(binary heap),類似地可定義k

堆排序的思想:

1).先將初始檔案r[1..n]建成乙個大根堆,此堆為初始的無序區

2).再將關鍵字最大的記錄r[1](即堆頂)和無序區的最後乙個記錄r[n]交換,由此得到新的無序區r[1..n-1]和有序區r[n],且滿足r[1..n-1].keys≤r[n].key

3).由於交換後新的根r[1]可能違反堆性質,故應將當前無序區r[1..n-1]調整為堆。然後再次將r[1..n-1]中關鍵字最大的記錄r[1]和該區間的最後乙個記錄r[n-1]交換,由此得到新的無序區r[1..n-2]和有序區r[n-1..n],且仍滿足關係r[1..n-2].keys≤r[n-1..n].keys,同樣要將r[1..n-2]調整為堆。

1

//堆排序,偽**2//

heapsort(a)3//

build-max-heap(a)4//

for i=a.length downto 25//

exchange a[1] with a[i]

//將第乙個元素和第i個元素交換6//

a.heap-size = a.heap-size - 1;7//

max-hep-apify(a,1);89

void heapadjust(int iarr,int start,int

len)

1019

if(iarr[i] 2025}26

}27void heapsort(int iarr,int

len)

2835

for(i = 0;i < len; ++i)

3639 cout <40for(i = len - 1; i > 0; --i)

4148}49

intmain()50;

52 heapsort(a,10

);53

for(int i=0;i < 10; ++i)

54 cout << a[i] << "";

55return0;

56 }

演算法分析:

堆排序的時間,主要由建立初始堆和反覆重建堆這兩部分的時間開銷構成,它們均是通過呼叫heapadjust實現的。

平均效能:o(n*logn) = o(n)(heapsort中的兩個for迴圈的時間複雜度)*o(lonn)(heapadjust中的for迴圈的時間複雜度)。

由於建初始堆所需的比較次數較多,所以堆排序不適宜於記錄數較少的檔案。

堆排序是就地排序,輔助空間為o(1).

它是不穩定的排序方法。

排序演算法之堆排序

堆排序演算法是選擇排序的一種,該演算法只是通過堆,最大堆 或者最小堆選擇出乙個待排序序列中的最大值,或者最小值。要想實現堆排序演算法,就需要構建什麼堆,這裡也最小堆為例。說明什麼是堆,怎麼構建乙個堆。假設待排序序列為a n 為乙個陣列。陣列的長度為n 陣列下標為 0,1,2,i,2i,2i 1 n ...

排序演算法之堆排序

宣告 本博文 為樓主親自編寫並測試,其它內容引用至我一直很崇拜的牛人morewindows。他對排序演算法的講解通俗易懂,給人一種耳目一新的感覺。堆排序與快速排序 歸併排序 一樣都是時間複雜度為o n logn 的幾種常見排序方法。最小堆的講解以及最小堆元素的插入和刪除參見最小堆操作。以下繼續引用以...

排序演算法之堆排序

堆排序是一種樹形選擇排序,是對直接選擇排序的有效改進。堆是一種資料結構,其定義 任何乙個非葉結點的值,都不大於 或不小於 其左右孩子結點的值。若父親大孩子小,則這樣的堆叫做大頂堆 若父親小孩子大,則這樣的堆叫做小頂堆。顧名思義,大頂堆的根結點的值是最大的,小頂堆的根結點的值是最小的。首先,將乙個無序...