1. 程式人生 > >排序算法---堆排序

排序算法---堆排序

info details 二叉 for != 最大 else algorithm IT

github:代碼實現
本文算法均使用python3實現


1. 什麽是堆

??堆(heap)是計算機科學中一類特殊的數據結構的統稱。堆通常是一個可以被看做一棵樹的數組對象,且堆總是一棵完全二叉樹。由於堆是基於完全二叉樹的結構,因此可以使用順序存儲結構數組來保存堆,再根據堆的性質,我們可以得到該數組(從0下標開始)的一些性質
??(1)對於數組 $ heap $ 中的第 $ i $ 個節點,其左孩子節點值 $ heap[2i+1] \leq heap[i] $ 且其右孩子節點值 $ heap[2i+2] \leq heap[i] $ ,此時為大根堆。(父親值大於等於孩子值)
??(2)對於數組 $ heap $ 中的第 $ i $ 個節點,其左孩子節點值 $ heap[2i+1] \geq heap[i] $ 且其由孩子節點值 $ heap[2i+2] \geq heap[i] $ ,此時為小根堆

。(父親值小於等於孩子值)

技術分享圖片

??對於大根堆,將其映射到數組中如下:

技術分享圖片


2. 如何構建初始堆

??的構建是一個遞歸的過程。下面以大根堆為例進行講解。具體操作如下:
??構建初始大根堆:從最後一個非葉子節點開始,比較其與其左右孩子值的大小,若其節點值比孩子節點值小,則將其與較大孩子進行交換。然後依次對其它節點進行如此比較與交換,直至根節點,此時根節點的值即為該堆中的最大值。

技術分享圖片


3. 如何進行堆排序

??堆排序是在已經構建好的初始大根堆上進行。主要分為以下幾步:
??(1)對初始序列構建初始大根堆。(按照2中所描述)
??(2)將大根堆的根節點值最後一個節點值交換。

技術分享圖片

??(3)將交換後的堆從數組

上分為兩個區:無序區與有序區。對無序區進行“堆調整”,即將無序區調整為大根堆。(其實建立初始大根堆也是一個不斷調用“堆調整”的過程)

技術分享圖片

技術分享圖片

??(4)將無序區中的根節點值與無序區中的最後一個節點值進行交換。此時無序區長度減 $ 1 $ ,有序區長度加 $ 1 $ ,見下圖。重復(3)直到無序區中只有一個節點為止。

技術分享圖片


4. 實現代碼

class HeapSort:
    '''堆排類'''
    def Max_Heapify(self, heap, heapsize, root):
        '''堆調整,使得根節點值大於子節點值'''
left = root * 2 + 1 # 列表從0開始,左節點下標為 2i+1,右節點下標為 2i+2 right = left + 1 larger = root if left < heapsize and heap[left] > heap[larger]: larger = left if right < heapsize and heap[right] > heap[larger]: larger = right if larger != root: heap[larger], heap[root] = heap[root], heap[larger] self.Max_Heapify(heap, heapsize, larger) else: return def Build_Max_Heap(self, heap): '''構建初始大根堆''' heapsize = len(heap) for i in range((heapsize-2)//2, -1, -1): # 從最後一個非葉子節點開始構建 self.Max_Heapify(heap, heapsize, i) def Heap_Sort(self, heap): '''堆排序''' # 步驟(1)構建初始大根堆 self.Build_Max_Heap(heap) for i in range(len(heap)-1, -1, -1): # 步驟(2)交換無序區第一個節點值與最後一個節點值 heap[0], heap[i] = heap[i], heap[0] # 步驟(3)對無序區進行“堆調整” self.Max_Heapify(heap, i, 0) return heap[::-1]

5. 算法分析

??堆排序是一種選擇排序,且是不穩定排序,整體主要由構建初始堆+交換堆頂元素和末尾元素並重建堆兩部分組成。其中構建初始堆的時間復雜度為 $ O(n) $ ,在交換並重建堆的過程中,需進行 $ n-1 $ 次”堆調整”,而重建堆的過程中,根據完全二叉樹的性質,$ [\log_2(n-1),\log_2(n-2)...1] $ 逐步遞減,近似為 $ O(n \log_2 n) $ 。所以堆排序時間復雜度為是 $ O(n \log_2 n) + O(n) = O(n \log_2 n) $ 。即堆排序的最壞時間復雜度為 $ O(n \log_2 n) $ (平均復雜度接近於最壞情況)。


引用及參考:
[1]《數據結構》李春葆著
[2] https://www.cnblogs.com/chengxiao/p/6129630.html
[3] https://blog.csdn.net/minxihou/article/details/51850001

寫在最後:本文參考以上資料進行整合與總結,屬於原創,文章中可能出現理解不當的地方,若有所見解或異議可在下方評論,謝謝!
若需轉載請註明:https://www.cnblogs.com/lliuye/p/9167471.html

排序算法---堆排序