排序演算法5 堆排序

2021-08-26 09:44:04 字數 1200 閱讀 4991

堆排序是利用堆這種資料結構進行的排序。堆通常使用一維陣列來實現,是一種近似完全二叉樹的結構。堆排序分為大根堆和小根堆。堆排序滿足這樣的乙個特性:大根堆父節點的值總是大於子節點,小根堆的父節點值總是小於子節點。

我們在拿到乙個陣列時,首先將它構造成為乙個大根堆/小根堆,這個過程我們叫做建堆。然後將根節點元素和最末尾元素交換,此時最末尾成為有序區。除去最末尾元素的剩下元素所構成的樹此時已經不叫堆了,因為它不滿足堆的特性。所以我們繼續進行調整,使得最小(或最大)的值再次移到根節點,隨後交換它與此時堆中的末尾節點,有序區+1...如此反覆,直至堆的大小為1(無序區中只有乙個數字,代表排序完成)。

首先我們寫出堆排序的主體:

void heapsort(int arr,int len)

}

上面這個heapsort函式就是我們的堆排序的主體部分,首先根據實參傳入的陣列長度決定堆的大小,進行建堆(buildheap函式將在下面書寫)。建堆函式要完成的功能就是將乙個無序的陣列調整成為乙個大根堆或者小根堆。建堆完成之後,如果heap_size(無序區)中存留的數字大於1,即這個堆中還有超過乙個以上的數字那麼證明還需要繼續排序。進入迴圈,不論是剛建成乙個堆還是已經經過調整,我們首先都需要將arr[0]這個根節點的元素和當前的堆的末尾元素進行交換,交換完成之後將它放入有序區,即heapsize--,然後對交換過後已經有可能被破壞的堆進行重新調整,重複選出數字放入有序區的這個過程。

接下來我們編寫建堆函式,此處要求公升序排序我們需要建立大根堆。

void buildheap(int arr,int len)

}

建立堆的第一步就是從二叉樹的倒數第乙個非葉子節點(len/2-1)開始,從下至上對每乙個根節點進行調整。

最後編寫調整函式。它只需要注意處理上層節點調整之後下層節點同樣有可能需要調整的情況,可以使用遞迴解決。其餘只需要實現簡單的資料交換即可。

void heapadjust(int arr,int i,int len)

}

引數中的i就代表從i節點開始進行調整,經過資料交換後(如果有這個必要的話),將繼續下探(因為如果這個和它的父節點交換過的節點有子節點的話,交換之後可能不滿足堆的定義,所以需要下探調整。)直至調整完成,此時又是乙個新的堆。

排序演算法 5 堆排序

這篇部落格從以下幾個方面來說 什麼是最大堆以及 實現 堆排序基礎 一次優化 提高效率 二次優化 原地堆排序,無需額外空間 1.什麼是最大堆以及 實現 這裡可以參考言簡意賅的部落格 堆與最大堆 2.堆排序基礎 import com.heap.maxheap import utils.createran...

排序演算法整理 5 堆排序

程式參考了clrs的 演算法導論 第六章 heap sort。由於最大堆和最小堆是對稱的,下文都說最大堆。1 堆的定義 最大堆就是這樣一種樹,每個節點而言,如果它有兒子,那麼此節點比它的兒子都大。需要注意的有兩點。首先,堆幾乎是一種完全二叉樹,也可能是不完全的,下面第4部分中的圖一。其次,如果要用陣...

排序(5) 堆排序

1.堆 堆這種資料結構其實就是完全二叉樹,堆分為兩種,大頂堆和小頂堆。因此,堆是具有下列性質的完全二叉樹 每個節點的值都大於或等於其左右孩子節點的值稱為大頂堆 每個節點的值都小於或等於其左右孩子節點的值稱為小頂堆。2.堆排序演算法 堆排序就是利用堆這種資料結構進行排序的方法。它的基本思想是 將待排序...