徹底理解堆排序

2021-08-27 00:21:40 字數 3383 閱讀 3064

堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即a[parent[i]] >= a[i]。在陣列的非降序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。

既然是堆排序,自然需要先建立乙個堆,而建堆的核心內容是調整堆,使二叉樹滿足堆的定義(每個節點的值都不大於其父節點的值)。調堆的過程應該從最後乙個非葉子節點開始,假設有陣列a = 。那麼調堆的過程如下圖,陣列下標從0開始,a[3] = 5開始。分別與左孩子和右孩子比較大小,如果a[3]最大,則不用調整,否則和孩子中的值最大的乙個交換位置,在圖1中是a[7] > a[3] > a[8],所以a[3]與a[7]對換,從圖1.1轉到圖1.2。

所以建堆的過程就是

for ( i = headlen/2; i >= 0; i++)

2:
3:

do adjustheap(a, heaplen, i)

調堆:如果初始陣列是非降序排序,那麼就不需要調堆,直接就滿足堆的定義,此為最好情況,執行時間為θ(1);如果初始陣列是如圖1.5,只有a[0] = 1不滿足堆的定義,經過與子節點的比較調整到圖1.6,但是圖1.6仍然不滿足堆的定義,所以要遞迴調整,一直到滿足堆的定義或者到堆底為止。如果遞迴調堆到堆底才結束,那麼是最壞情況,執行時間為o(h) (h為需要調整的節點的高度,堆底高度為0,堆頂高度為floor(logn) )。

建堆完成之後,堆如圖1.7是個大根堆。將a[0] = 8 與 a[heaplen-1]交換,然後heaplen減一,如圖2.1,然後adjustheap(a, heaplen-1, 0),如圖2.2。如此交換堆的第乙個元

素和堆的最後乙個元素,然後堆的大小heaplen減一,對堆的大小為heaplen的堆進行調堆,如此迴圈,直到heaplen == 1時停止,最後得出結果如圖3。

輸入:陣列a,堆的長度hlen,以及需要調整的節點i

3:

功能:調堆

4:

*/

5:
6:

void adjustheap(int a, int hlen, int i)

7:
19:
20:

if (right < hlen && a[largest] < a[right])

21:
24:
25:

if (i != largest) //如果最大值不是父節點

26:
35:

else

36:
39:     }
40: }
41:
42:

/*

43:

輸入:陣列a,堆的大小hlen

44:

功能:建堆

45:

*/

46:

void buildheap(int a, int hlen)

47:
54: }
55:
56:

/*

57:

輸入:陣列a,待排序陣列的大小alen

58:

功能:堆排序

因此,建堆的執行時間是o(n)。

總執行時間t(n) = o(nlogn) + o(n) = o(nlogn)。對於堆排序的最好情況與最壞情況的執行時間,因為最壞與最好的輸入都只是影響建堆的執行時間o(1)或者o(n),而在總體時間中佔重要比例的是迴圈調堆的過程,即o(nlogn) + o(1) =o(nlogn) + o(n) = o(nlogn)。因此最好或者最壞情況下,堆排序的執行時間都是o(nlogn)。而且堆排序還是原地演算法(in-place algorithm)

下面貼出堆排序的演算法:

// heapsort.cpp : 定義控制台應用程式的入口點。

//#include "stdafx.h"

#include

using namespace std;

//以下是針對堆進行調整

void heapajust(int data,int i,int length)

if(ntemp//堆排序

void heapsort(int data,int length)

for(int j=length-1;j>0;--j)

}int _tmain(int argc, _tchar* argv)

;int len = sizeof(data)/sizeof(int);

heapsort(data,len);

for (int i=0;isystem("pause");

return 0;

}

// heapsort.cpp : 定義控制台應用程式的入口點。

//#include "stdafx.h"

#include using namespace std;

//以下是針對堆進行調整

void heapajust(int data,int i,int length)

if(ntemp>1)-1;i>=0;i--)//注意這個地方:i=(length>>1)-1,加上括號,原因:優先順序的問題

for(int j=length-1;j>0;--j) }

int _tmain(int argc, _tchar* argv)

; int len = sizeof(data)/sizeof(int);

heapsort(data,len);

for (int i=0;i

堆排序python理解 堆排序Python實現

def heap sort nos global size size len nos print the size of the list is d size build heap size,nos for i in range size 1,0,1 nums 0 nums i nums i num...

徹底理解各種排序演算法

排序 1 氣泡排序 bubbler sort 前面剛說了氣泡排序的壞話,但氣泡排序也有其優點,那就是好理解,穩定,再就是空間複雜度低,不需要額外開闢陣列元素的臨時儲存控制項,當然了,編寫起來也容易。其演算法很簡單,就是比較陣列相鄰的兩個值,把大的像泡泡一樣 冒 到陣列後面去,一共要執行n的平方除以2...

堆排序 自己的理解

堆排序 heapsort 是指利用堆積樹 堆 這種資料結構所設計的一種排序演算法,可以利用陣列的特點快速定位指定索引的元素。要理解排序演算法首先要知道堆的定義 堆 即一顆完全二叉樹,樹中任乙個非葉子節點的關鍵字均不大於 或者均不小於 其左右孩子 若存在 節點的關鍵字。比如說想下面這樣的完全二叉樹就叫...