算法導論--堆排序

堆排序涉及到一個數據結構就是“堆”,所以我們先從“堆”開始講起。

一、堆

堆的存儲方式其實就是一個數組,而堆的邏輯結構是一個完全二叉樹(什麼是完全二叉樹請自行百度)。

這裏寫圖片描述

如圖(a)是一個完全二叉樹,樹的父節點都比孩子節點要大,這個就是“大根堆”,如果樹的父節點都比孩子節點小,那麼就是一個“小根堆”。而圖(b)則表示了一個圖(a)是如何存儲的。

這樣就很容易計算每個節點的父節點,左孩子節點,右孩子節點。
例如索引是i的節點:
父節點: i/2
左孩子:i*2
右孩子: i*2+1

大根堆化

爲了保持大根堆的性質,我們稱這個程序的名稱爲MAX-HEAPFY。其實就是假設一個節點的左孩子子樹,和右孩子子樹都滿足了大根堆的性質,但是這個節點可能比它的孩子要小,所以需要進行節點位置的調整,這個過程稱爲“大根堆化”。僞代碼如下:
這裏寫圖片描述
這裏寫圖片描述

來來來算一下時間複雜度:從這個過程來看,最壞的情況下:是根節點的元素移動到葉子節點。所以也就是執行了lgn次,也就是說,最壞情況下的時間複雜度是log2(n)。

生成大根堆

接下來的問題就是用“大根堆化”這個方法從一個無序的數組生成一個“大根堆”。容易知道,數組A[n/2+1]以及之後的元素都是葉子節點。所以我們可以用自底向上的方法生成一個大根堆。僞代碼如下:
這裏寫圖片描述
這個僞代碼的講解書上講的比較繁瑣,這裏簡單講一下,其實就是自底向上的不斷的生成子大根堆,然後最後到根節點。直接上圖說話:
這裏寫圖片描述
時間複雜度也可以簡單說一下,每一次的大根堆化的上界是O(log2(n)),然後總共執行了n/2次所以整個的執行時間是O(nlog2(n))

堆排序

僞代碼如下:
這裏寫圖片描述
先生成一個大根堆,然後將第一個元素與最後一個元素交換位置,這樣最大值就放在最後了,再執行一次“大根堆化”然後遞歸執行上述過程就行了。

堆排序是一個非常棒的算法,但是在實踐過程中,經常被快速排序在性能上被快速排序擊敗。但是堆排序有其他更好性質就是可以作爲優先級隊列來使用。這裏只簡單說一下:
返回最大元素:直接返回第一個元素A[1]
返回最大元素並移除:拿到第一個元素的引用, 然後將A[1]和最後一個元素互換位置,執行大根堆化, length = length -1
插入元素:將元素插入到尾部,然後將元素跟自己父節點比較,如果大於父節點則互換位置,遞歸執行
增加元素的key:將元素跟自己父節點比較,如果大於父節點則互換位置,遞歸執行。
具體參加《算法導論》6.3節

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章