排序演算法之堆排序

2021-06-21 15:03:29 字數 1410 閱讀 5683

宣告:本博文**為樓主親自編寫並測試,其它內容引用至我一直很崇拜的牛人morewindows。他對排序演算法的講解通俗易懂,給人一種耳目一新的感覺。

堆排序與快速排序、歸併排序

一樣都是時間複雜度為o(n*logn)的幾種常見排序方法。

最小堆的講解以及最小堆元素的插入和刪除參見最小堆操作。

以下繼續引用以下牛人morewindows寫的部落格堆與堆排序中的內容:

有了堆的插入和刪除後,再考慮下如何對乙個資料進行堆化操作。要乙個乙個的從陣列中取出資料來建立堆吧,不用!先看乙個陣列,如下圖:

很明顯,對葉子結點來說,可以認為它已經是乙個合法的堆了即20,60, 65, 4, 49都分別是乙個合法的堆。只要從a[4]=50開始向下調整就可以了。然後再取a[3]=30,a[2] = 17,a[1] = 12,a[0] = 9分別作一次向下調整操作就可以了。下圖展示了這些步驟:

在堆排序之前,首先建立乙個該陣列的最小堆。

private void makeminheap(int array, int length)  

private void minheapfixdown(int array, int i, int length) 

if(array[j] >= temp)

array[i] = array[j];

i = j;

j = 2 * i + 1;

} array[i] = temp;

}

然後再對最小堆進行排序。

引用(首先可以看到堆建好之後堆中第0個資料是堆中最小的資料。取出這個資料再執行下堆的刪除操作。這樣堆中第0個資料又是堆中最小的資料,重複上述步驟直至堆中只有乙個資料時就直接取出這個資料。

由於堆也是用陣列模擬的,故堆化陣列後,第一次將a[0]與a[n - 1]交換,再對a[0…n-2]重新恢復堆。第二次將a[0]與a[n – 2]交換,再對a[0…n - 3]重新恢復堆,重複這樣的操作直到a[0]與a[1]交換。由於每次都是將最小的資料併入到後面的有序區間,故操作完成後整個陣列就有序了。)

private void heapsort(int array, int length) 

}

private void swap(int array, int i, int j)
注意使用最小堆排序後是遞減陣列,要得到遞增陣列,可以使用最大堆。

由於每次重新恢復堆的時間複雜度為o(logn),共n - 1次重新恢復堆操作,再加上前面建立堆時n / 2次向下調整,每次調整時間複雜度也為o(logn)。二次操作時間相加還是o(n * logn)。故堆排序的時間複雜度為o(n * logn)。stl也實現了堆的相關函式,可以參閱《stl系列之四 heap 堆》。

排序演算法之堆排序

前言 今天我來介紹下堆排序,在寫堆排序 之前,我們要知道堆的概念!堆的定義 n個關鍵字序列kl,k2,kn稱為 heap 當且僅當該序列滿足如下性質 簡稱為堆性質 1 ki k 2i 且ki k 2i 1 1 i n 當然,這是小根堆,大根堆則換成 號。k i 相當於二叉樹的非葉子結點,k 2i 則...

排序演算法之堆排序

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

排序演算法之堆排序

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