堆排序(C 實現)

2021-07-13 12:18:42 字數 1776 閱讀 8511

堆排序執行時間(n lgn)。它是一種原地(in place)排序演算法:在任何時候,陣列中只有常數個元素儲存在陣列外。堆的資料結構不至少在堆排序中有用,還可以構成乙個有效的優先佇列。

二叉堆資料結構是一種陣列物件,它可以被看做是一棵完全二叉樹。樹中的每個節點與陣列中存放該節點值的那個元素對應。除了最後一層,樹的每一層都是填滿。

假設有陣列a。

樹的根為a[0]現在給定某個節點的下標i,其父節點parent(i),左孩子left(i),右孩子right(i)的下標可以通過簡單的計算得到:

parent(i) = (i-1)/2

left(i) = i*2+1

right(i) = i*2+2

二叉堆有兩種:大根堆和小根堆。在這兩種堆中,節點內的數值都要滿足堆的特性,其細節則根據堆的種類決定。

大根堆指的是除了根節點以外的每個節點,有:

a[parent[i]]>=a[i]
小根堆指的是除了根節點以外的每個節點,有:

a[parent[i]]<=a[i]
此處以大根堆為例:

fixdown過程,其執行時間為o(lg n),是保持大根堆性質的關鍵。

buildheap過程,以線性時間執行,可以在無序的輸入資料基礎上構造處最大堆。

heapsort過程,執行時間為o(n lg n),對乙個陣列進行原地排序。

push、pop過程,執行時間為o(lg n),可以讓堆結構作為優先佇列使用。

當fixdown被呼叫時,我們假定以left(i)和right(i)為根的兩棵二叉樹都是大根堆,但這時a[i]可能小於其子女,這就違反了大根堆的性質。

fixdown讓a[i]在大根堆中「下降」,使得以i為根的子樹成為大根堆。

時間複雜度:o(lg n)

void fixdown(int a,int root,int len)//存放堆的陣列,當前正在調整的子樹的根,陣列允許訪問部分的長度

a[root]=tmp;

}

當buildheap被呼叫時,a[0…n-1]將自下而上得變成乙個最大堆,子陣列a[((n-1)/2+1)…n-1]中的元素都是樹中的葉子,因此葉子都可以被認為是只含有乙個元素的堆,故建樹過程中對每乙個其他節點都進行乙個fixdown的呼叫。

時間複雜度:o(n)

buildheap(int a,int

len)

當pop被呼叫時,我們返回了根結點,此時整棵樹變成了兩棵,這時我們需要將最後乙個資料放置到根節點處,再進行一次fixdown

時間複雜度:o(lg n)

int pop(int a,int

len)

開始時,堆排序演算法先用buildheap將輸入陣列a造成了乙個大根堆,在呼叫heapsort時,可以通過將a[0]同a[n-1]交換來達到最終的目的。現在只需要將陣列的長度減去1,就可以很容易得將剩下的的a[0…n-2]重構成大根堆。原來跟的子女還是大根堆,但新的根元素可能違背了大根堆的性質。這時只需要呼叫fixdown 就能保持這一性質了。堆排序演算法不斷重複這個過程,堆的大小由n變成了1。

演算法複雜度:o(n lg n)

void heapsort(int a,int

len)

c 實現堆排序

include include include using namespace std 對比枝節點和左右子節點,將比較大的節點放置於枝節點 template int heapadjust t t,int i,int size if rightchild size t rightchild t max...

C 實現堆排序

堆排序是一種具有合併排序和插入排序共同優點的排序方法。它的時間複雜度為o nlgn 它也是一種原地排序演算法 在任何時候,陣列中只有常數個元素儲存在輸入陣列以外。要介紹堆排序首先要介紹什麼是堆。1.建堆 堆資料結構是一種陣列物件,它可以被視為一顆完全二叉樹,如下圖。右邊陣列表示的堆可以用左邊的完全二...

C 實現堆排序

c 實現的堆排序,分為三個函式實現 堆調整函式 保持最大 最小堆 堆構建函式 利用堆調整函式建立乙個最大 最小堆 堆排序函式 每次取堆頂元素交換至陣列最後,並將size減一,然後調整堆頂保持最大 最小堆 堆調整函式 調整堆為陣列a,需要調整的結點序號為i,堆大小為size void heapadju...